Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp
Warning:line 10155, column 7
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -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=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/battery -I /var/lib/jenkins/workspace/firefox-scan-build/dom/events -I /var/lib/jenkins/workspace/firefox-scan-build/dom/media -I /var/lib/jenkins/workspace/firefox-scan-build/dom/network -I /var/lib/jenkins/workspace/firefox-scan-build/caps -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/file -I /var/lib/jenkins/workspace/firefox-scan-build/dom/geolocation -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/dom/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/dom/storage -I /var/lib/jenkins/workspace/firefox-scan-build/dom/svg -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xml -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/extensions/spellcheck/src -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/2d -I /var/lib/jenkins/workspace/firefox-scan-build/image -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/loader -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/layout/forms -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/parser/htmlparser -I /var/lib/jenkins/workspace/firefox-scan-build/security/manager/ssl -I /var/lib/jenkins/workspace/firefox-scan-build/third_party/xsimd/include -I /var/lib/jenkins/workspace/firefox-scan-build/widget -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/build -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/ds -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/sctp/datachannel -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -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/gtk-3.0/unix-print -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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-deprecated-this-capture -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 -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 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/* A namespace class for static layout utilities. */
8
9#include "nsContentUtils.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#include "BrowserChild.h"
20#include "DecoderTraits.h"
21#include "ErrorList.h"
22#include "HTMLSplitOnSpacesTokenizer.h"
23#include "ImageOps.h"
24#include "InProcessBrowserChildMessageManager.h"
25#include "MainThreadUtils.h"
26#include "PLDHashTable.h"
27#include "ReferrerInfo.h"
28#include "ScopedNSSTypes.h"
29#include "ThirdPartyUtil.h"
30#include "Units.h"
31#include "chrome/common/ipc_message.h"
32#include "gfxDrawable.h"
33#include "harfbuzz/hb.h"
34#include "imgICache.h"
35#include "imgIContainer.h"
36#include "imgILoader.h"
37#include "imgIRequest.h"
38#include "imgLoader.h"
39#include "js/Array.h"
40#include "js/ArrayBuffer.h"
41#include "js/BuildId.h"
42#include "js/GCAPI.h"
43#include "js/Id.h"
44#include "js/JSON.h"
45#include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty
46#include "js/PropertyDescriptor.h"
47#include "js/Realm.h"
48#include "js/RegExp.h"
49#include "js/RegExpFlags.h"
50#include "js/RootingAPI.h"
51#include "js/TypeDecls.h"
52#include "js/Value.h"
53#include "js/Wrapper.h"
54#include "jsapi.h"
55#include "jsfriendapi.h"
56#include "mozAutoDocUpdate.h"
57#include "mozIDOMWindow.h"
58#include "nsIOService.h"
59#include "nsObjectLoadingContent.h"
60#include "mozilla/AlreadyAddRefed.h"
61#include "mozilla/ArrayIterator.h"
62#include "mozilla/ArrayUtils.h"
63#include "mozilla/AsyncEventDispatcher.h"
64#include "mozilla/AtomArray.h"
65#include "mozilla/Atomics.h"
66#include "mozilla/Attributes.h"
67#include "mozilla/AutoRestore.h"
68#include "mozilla/BackgroundHangMonitor.h"
69#include "mozilla/Base64.h"
70#include "mozilla/BasePrincipal.h"
71#include "mozilla/BasicEvents.h"
72#include "mozilla/BloomFilter.h"
73#include "mozilla/CORSMode.h"
74#include "mozilla/CallState.h"
75#include "mozilla/CheckedInt.h"
76#include "mozilla/ClearOnShutdown.h"
77#include "mozilla/Components.h"
78#include "mozilla/ContentBlockingAllowList.h"
79#include "mozilla/CycleCollectedJSContext.h"
80#include "mozilla/DOMEventTargetHelper.h"
81#include "mozilla/DebugOnly.h"
82#include "mozilla/ErrorResult.h"
83#include "mozilla/EventDispatcher.h"
84#include "mozilla/EventListenerManager.h"
85#include "mozilla/EventQueue.h"
86#include "mozilla/EventStateManager.h"
87#include "mozilla/FlushType.h"
88#include "mozilla/FOGIPC.h"
89#include "mozilla/HTMLEditor.h"
90#include "mozilla/HangAnnotations.h"
91#include "mozilla/IMEStateManager.h"
92#include "mozilla/InputEventOptions.h"
93#include "mozilla/InternalMutationEvent.h"
94#include "mozilla/Latin1.h"
95#include "mozilla/Likely.h"
96#include "mozilla/LoadInfo.h"
97#include "mozilla/Logging.h"
98#include "mozilla/MacroForEach.h"
99#include "mozilla/ManualNAC.h"
100#include "mozilla/Maybe.h"
101#include "mozilla/MediaFeatureChange.h"
102#include "mozilla/MouseEvents.h"
103#include "mozilla/NotNull.h"
104#include "mozilla/NullPrincipal.h"
105#include "mozilla/OriginAttributes.h"
106#include "mozilla/Preferences.h"
107#include "mozilla/PresShell.h"
108#include "mozilla/ProfilerRunnable.h"
109#include "mozilla/RangeBoundary.h"
110#include "mozilla/RefPtr.h"
111#include "mozilla/Result.h"
112#include "mozilla/ResultExtensions.h"
113#include "mozilla/ScrollbarPreferences.h"
114#include "mozilla/ScrollContainerFrame.h"
115#include "mozilla/ShutdownPhase.h"
116#include "mozilla/Span.h"
117#include "mozilla/StaticAnalysisFunctions.h"
118#include "mozilla/StaticPrefs_browser.h"
119#include "mozilla/StaticPrefs_dom.h"
120#ifdef FUZZING
121# include "mozilla/StaticPrefs_fuzzing.h"
122#endif
123#include "mozilla/StaticPrefs_nglayout.h"
124#include "mozilla/StaticPrefs_privacy.h"
125#include "mozilla/StaticPrefs_test.h"
126#include "mozilla/StaticPrefs_ui.h"
127#include "mozilla/StaticPtr.h"
128#include "mozilla/TextControlState.h"
129#include "mozilla/TextEditor.h"
130#include "mozilla/TextEvents.h"
131#include "mozilla/UniquePtr.h"
132#include "mozilla/Unused.h"
133#include "mozilla/Variant.h"
134#include "mozilla/ViewportUtils.h"
135#include "mozilla/dom/AncestorIterator.h"
136#include "mozilla/dom/AutoEntryScript.h"
137#include "mozilla/dom/AutocompleteInfoBinding.h"
138#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
139#include "mozilla/dom/BindingDeclarations.h"
140#include "mozilla/dom/BindingUtils.h"
141#include "mozilla/dom/BlobImpl.h"
142#include "mozilla/dom/BlobURLProtocolHandler.h"
143#include "mozilla/dom/BorrowedAttrInfo.h"
144#include "mozilla/dom/BrowserBridgeParent.h"
145#include "mozilla/dom/BrowserParent.h"
146#include "mozilla/dom/BrowsingContext.h"
147#include "mozilla/dom/BrowsingContextGroup.h"
148#include "mozilla/dom/CacheExpirationTime.h"
149#include "mozilla/dom/CallbackFunction.h"
150#include "mozilla/dom/CallbackObject.h"
151#include "mozilla/dom/ChromeMessageBroadcaster.h"
152#include "mozilla/dom/ContentChild.h"
153#include "mozilla/dom/ContentFrameMessageManager.h"
154#include "mozilla/dom/ContentParent.h"
155#include "mozilla/dom/CustomElementRegistry.h"
156#include "mozilla/dom/CustomElementRegistryBinding.h"
157#include "mozilla/dom/CustomElementTypes.h"
158#include "mozilla/dom/DOMArena.h"
159#include "mozilla/dom/DOMException.h"
160#include "mozilla/dom/DOMExceptionBinding.h"
161#include "mozilla/dom/DOMSecurityMonitor.h"
162#include "mozilla/dom/DOMTypes.h"
163#include "mozilla/dom/DataTransfer.h"
164#include "mozilla/dom/DocGroup.h"
165#include "mozilla/dom/Document.h"
166#include "mozilla/dom/DocumentFragment.h"
167#include "mozilla/dom/DocumentInlines.h"
168#include "mozilla/dom/Element.h"
169#include "mozilla/dom/ElementBinding.h"
170#include "mozilla/dom/ElementInlines.h"
171#include "mozilla/dom/Event.h"
172#include "mozilla/dom/EventTarget.h"
173#include "mozilla/dom/FileBlobImpl.h"
174#include "mozilla/dom/FileSystemSecurity.h"
175#include "mozilla/dom/FilteredNodeIterator.h"
176#include "mozilla/dom/FormData.h"
177#include "mozilla/dom/FragmentOrElement.h"
178#include "mozilla/dom/FromParser.h"
179#include "mozilla/dom/HTMLElement.h"
180#include "mozilla/dom/HTMLFormElement.h"
181#include "mozilla/dom/HTMLImageElement.h"
182#include "mozilla/dom/HTMLInputElement.h"
183#include "mozilla/dom/HTMLTemplateElement.h"
184#include "mozilla/dom/HTMLTextAreaElement.h"
185#include "mozilla/dom/IPCBlob.h"
186#include "mozilla/dom/IPCBlobUtils.h"
187#include "mozilla/dom/MessageBroadcaster.h"
188#include "mozilla/dom/MessageListenerManager.h"
189#include "mozilla/dom/MessagePort.h"
190#include "mozilla/dom/MouseEventBinding.h"
191#include "mozilla/dom/NameSpaceConstants.h"
192#include "mozilla/dom/NodeBinding.h"
193#include "mozilla/dom/NodeInfo.h"
194#include "mozilla/dom/PBrowser.h"
195#include "mozilla/dom/PContentChild.h"
196#include "mozilla/dom/PrototypeList.h"
197#include "mozilla/dom/ReferrerPolicyBinding.h"
198#include "mozilla/dom/ScriptSettings.h"
199#include "mozilla/dom/Selection.h"
200#include "mozilla/dom/ShadowRoot.h"
201#include "mozilla/dom/Text.h"
202#include "mozilla/dom/TrustedHTML.h"
203#include "mozilla/dom/TrustedTypesConstants.h"
204#include "mozilla/dom/TrustedTypeUtils.h"
205#include "mozilla/dom/UserActivation.h"
206#include "mozilla/dom/ViewTransition.h"
207#include "mozilla/dom/WindowContext.h"
208#include "mozilla/dom/WorkerCommon.h"
209#include "mozilla/dom/WorkerPrivate.h"
210#include "mozilla/dom/WorkerRunnable.h"
211#include "mozilla/dom/XULCommandEvent.h"
212#include "mozilla/glean/GleanPings.h"
213#include "mozilla/fallible.h"
214#include "mozilla/gfx/2D.h"
215#include "mozilla/gfx/BaseMargin.h"
216#include "mozilla/gfx/BasePoint.h"
217#include "mozilla/gfx/BaseSize.h"
218#include "mozilla/gfx/DataSurfaceHelpers.h"
219#include "mozilla/gfx/Point.h"
220#include "mozilla/gfx/Rect.h"
221#include "mozilla/gfx/Types.h"
222#include "mozilla/ipc/ProtocolUtils.h"
223#include "mozilla/ipc/SharedMemory.h"
224#include "mozilla/net/UrlClassifierCommon.h"
225#include "mozilla/Tokenizer.h"
226#include "mozilla/widget/IMEData.h"
227#include "nsAboutProtocolUtils.h"
228#include "nsArrayUtils.h"
229#include "nsAtomHashKeys.h"
230#include "nsAttrName.h"
231#include "nsAttrValue.h"
232#include "nsAttrValueInlines.h"
233#include "nsBaseHashtable.h"
234#include "nsCCUncollectableMarker.h"
235#include "nsCOMPtr.h"
236#include "nsCRT.h"
237#include "nsCRTGlue.h"
238#include "nsCanvasFrame.h"
239#include "nsCaseTreatment.h"
240#include "nsCharSeparatedTokenizer.h"
241#include "nsCharTraits.h"
242#include "nsCompatibility.h"
243#include "nsComponentManagerUtils.h"
244#include "nsContainerFrame.h"
245#include "nsContentCreatorFunctions.h"
246#include "nsContentDLF.h"
247#include "nsContentList.h"
248#include "nsContentListDeclarations.h"
249#include "nsContentPolicyUtils.h"
250#include "nsCoord.h"
251#include "nsCycleCollectionNoteChild.h"
252#include "nsDOMMutationObserver.h"
253#include "nsDOMString.h"
254#include "nsTHashMap.h"
255#include "nsDebug.h"
256#include "nsDocShell.h"
257#include "nsDocShellCID.h"
258#include "nsError.h"
259#include "nsFocusManager.h"
260#include "nsFrameList.h"
261#include "nsFrameLoader.h"
262#include "nsFrameLoaderOwner.h"
263#include "nsGenericHTMLElement.h"
264#include "nsGkAtoms.h"
265#include "nsGlobalWindowInner.h"
266#include "nsGlobalWindowOuter.h"
267#include "nsHTMLDocument.h"
268#include "nsHTMLTags.h"
269#include "nsHashKeys.h"
270#include "nsHtml5StringParser.h"
271#include "nsIAboutModule.h"
272#include "nsIAnonymousContentCreator.h"
273#include "nsIAppShell.h"
274#include "nsIArray.h"
275#include "nsIAsyncVerifyRedirectCallback.h"
276#include "nsIBidiKeyboard.h"
277#include "nsIBrowser.h"
278#include "nsICacheInfoChannel.h"
279#include "nsICachingChannel.h"
280#include "nsICategoryManager.h"
281#include "nsIChannel.h"
282#include "nsIChannelEventSink.h"
283#include "nsIClassifiedChannel.h"
284#include "nsIConsoleService.h"
285#include "nsIContent.h"
286#include "nsIContentInlines.h"
287#include "nsIContentPolicy.h"
288#include "nsIContentSecurityPolicy.h"
289#include "nsIContentSink.h"
290#include "nsIDOMWindowUtils.h"
291#include "nsIDocShell.h"
292#include "nsIDocShellTreeItem.h"
293#include "nsIDocumentEncoder.h"
294#include "nsIDocumentLoaderFactory.h"
295#include "nsIDocumentViewer.h"
296#include "nsIDragService.h"
297#include "nsIDragSession.h"
298#include "nsIFile.h"
299#include "nsIFocusManager.h"
300#include "nsIFormControl.h"
301#include "nsIFragmentContentSink.h"
302#include "nsIFrame.h"
303#include "nsIGlobalObject.h"
304#include "nsIHttpChannel.h"
305#include "nsIHttpChannelInternal.h"
306#include "nsIIOService.h"
307#include "nsIImageLoadingContent.h"
308#include "nsIInputStream.h"
309#include "nsIInterfaceRequestor.h"
310#include "nsIInterfaceRequestorUtils.h"
311#include "nsILoadContext.h"
312#include "nsILoadGroup.h"
313#include "nsILoadInfo.h"
314#include "nsIMIMEService.h"
315#include "nsIMemoryReporter.h"
316#include "nsINetUtil.h"
317#include "nsINode.h"
318#include "nsIObjectLoadingContent.h"
319#include "nsIObserver.h"
320#include "nsIObserverService.h"
321#include "nsIParserUtils.h"
322#include "nsIPermissionManager.h"
323#include "nsIPrincipal.h"
324#include "nsIProperties.h"
325#include "nsIProtocolHandler.h"
326#include "nsIRequest.h"
327#include "nsIRunnable.h"
328#include "nsIScreen.h"
329#include "nsIScriptError.h"
330#include "nsIScriptGlobalObject.h"
331#include "nsIScriptObjectPrincipal.h"
332#include "nsIScriptSecurityManager.h"
333#include "nsISerialEventTarget.h"
334#include "nsIStreamConverter.h"
335#include "nsIStreamConverterService.h"
336#include "nsIStringBundle.h"
337#include "nsISupports.h"
338#include "nsISupportsPrimitives.h"
339#include "nsISupportsUtils.h"
340#include "nsITransferable.h"
341#include "nsIURI.h"
342#include "nsIURIMutator.h"
343#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
344# include "nsIURIWithSpecialOrigin.h"
345#endif
346#include "nsIUserIdleServiceInternal.h"
347#include "nsIWeakReferenceUtils.h"
348#include "nsIWebNavigation.h"
349#include "nsIWebNavigationInfo.h"
350#include "nsIWidget.h"
351#include "nsIWindowMediator.h"
352#include "nsIXPConnect.h"
353#include "nsJSPrincipals.h"
354#include "nsJSUtils.h"
355#include "nsLayoutUtils.h"
356#include "nsLiteralString.h"
357#include "nsMargin.h"
358#include "nsMimeTypes.h"
359#include "nsNameSpaceManager.h"
360#include "nsNetCID.h"
361#include "nsNetUtil.h"
362#include "nsNodeInfoManager.h"
363#include "nsPIDOMWindow.h"
364#include "nsPIDOMWindowInlines.h"
365#include "nsParser.h"
366#include "nsParserConstants.h"
367#include "nsPoint.h"
368#include "nsPointerHashKeys.h"
369#include "nsPresContext.h"
370#include "nsQueryFrame.h"
371#include "nsQueryObject.h"
372#include "nsRange.h"
373#include "nsRefPtrHashtable.h"
374#include "nsSandboxFlags.h"
375#include "nsScriptSecurityManager.h"
376#include "nsServiceManagerUtils.h"
377#include "nsStreamUtils.h"
378#include "nsString.h"
379#include "nsStringBundle.h"
380#include "nsStringFlags.h"
381#include "nsStringFwd.h"
382#include "nsStringIterator.h"
383#include "nsStringStream.h"
384#include "nsTArray.h"
385#include "nsTLiteralString.h"
386#include "nsTPromiseFlatString.h"
387#include "nsTStringRepr.h"
388#include "nsTextFragment.h"
389#include "nsTextNode.h"
390#include "nsThreadManager.h"
391#include "nsThreadUtils.h"
392#include "nsTreeSanitizer.h"
393#include "nsUGenCategory.h"
394#include "nsURLHelper.h"
395#include "nsUnicodeProperties.h"
396#include "nsVariant.h"
397#include "nsWidgetsCID.h"
398#include "nsView.h"
399#include "nsViewManager.h"
400#include "nsXPCOM.h"
401#include "nsXPCOMCID.h"
402#include "nsXULAppAPI.h"
403#include "nsXULElement.h"
404#include "nsXULPopupManager.h"
405#include "nscore.h"
406#include "prinrval.h"
407#include "xpcprivate.h"
408#include "xpcpublic.h"
409
410#if defined(XP_WIN)
411// Undefine LoadImage to prevent naming conflict with Windows.
412# undef LoadImage
413#endif
414
415extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
416 const char** next, char16_t* result);
417extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
418 const char** colon);
419
420using namespace mozilla::dom;
421using namespace mozilla::ipc;
422using namespace mozilla::gfx;
423using namespace mozilla::layers;
424using namespace mozilla::widget;
425using namespace mozilla;
426
427const char kLoadAsData[] = "loadAsData";
428
429nsIXPConnect* nsContentUtils::sXPConnect;
430nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
431nsIPrincipal* nsContentUtils::sSystemPrincipal;
432nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
433nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal;
434nsIConsoleService* nsContentUtils::sConsoleService;
435
436static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
437static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
438static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
439nsIStringBundleService* nsContentUtils::sStringBundleService;
440
441static StaticRefPtr<nsIStringBundle>
442 sStringBundles[nsContentUtils::PropertiesFile_COUNT];
443
444nsIContentPolicy* nsContentUtils::sContentPolicyService;
445bool nsContentUtils::sTriedToGetContentPolicy = false;
446StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
447uint32_t nsContentUtils::sScriptBlockerCount = 0;
448uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
449AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
450 nullptr;
451uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
452nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
453
454bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
455
456nsString* nsContentUtils::sShiftText = nullptr;
457nsString* nsContentUtils::sControlText = nullptr;
458nsString* nsContentUtils::sCommandOrWinText = nullptr;
459nsString* nsContentUtils::sAltText = nullptr;
460nsString* nsContentUtils::sModifierSeparator = nullptr;
461
462bool nsContentUtils::sInitialized = false;
463#ifndef RELEASE_OR_BETA
464bool nsContentUtils::sBypassCSSOMOriginCheck = false;
465#endif
466
467nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
468nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
469
470nsContentUtils::UserInteractionObserver*
471 nsContentUtils::sUserInteractionObserver = nullptr;
472
473nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
474nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
475nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
476bool nsContentUtils::sFragmentParsingActive = false;
477
478bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false;
479bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false;
480
481mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
482 "nsResistFingerprinting");
483mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
484
485int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
486uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
487
488template Maybe<int32_t> nsContentUtils::ComparePoints(
489 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary);
490template Maybe<int32_t> nsContentUtils::ComparePoints(
491 const RangeBoundary& aFirstBoundary,
492 const RawRangeBoundary& aSecondBoundary);
493template Maybe<int32_t> nsContentUtils::ComparePoints(
494 const RawRangeBoundary& aFirstBoundary,
495 const RangeBoundary& aSecondBoundary);
496template Maybe<int32_t> nsContentUtils::ComparePoints(
497 const RawRangeBoundary& aFirstBoundary,
498 const RawRangeBoundary& aSecondBoundary);
499
500template int32_t nsContentUtils::ComparePoints_Deprecated(
501 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary,
502 bool* aDisconnected);
503template int32_t nsContentUtils::ComparePoints_Deprecated(
504 const RangeBoundary& aFirstBoundary,
505 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
506template int32_t nsContentUtils::ComparePoints_Deprecated(
507 const RawRangeBoundary& aFirstBoundary,
508 const RangeBoundary& aSecondBoundary, bool* aDisconnected);
509template int32_t nsContentUtils::ComparePoints_Deprecated(
510 const RawRangeBoundary& aFirstBoundary,
511 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
512
513// Subset of
514// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
515enum AutocompleteUnsupportedFieldName : uint8_t {
516#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
517 eAutocompleteUnsupportedFieldName_##name_,
518#include "AutocompleteFieldList.h"
519#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
520};
521
522enum AutocompleteNoPersistFieldName : uint8_t {
523#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
524 eAutocompleteNoPersistFieldName_##name_,
525#include "AutocompleteFieldList.h"
526#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
527};
528
529enum AutocompleteUnsupportFieldContactHint : uint8_t {
530#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
531 eAutocompleteUnsupportedFieldContactHint_##name_,
532#include "AutocompleteFieldList.h"
533#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
534};
535
536enum AutocompleteFieldName : uint8_t {
537#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
538#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
539 AUTOCOMPLETE_FIELD_NAME(name_, value_)
540#include "AutocompleteFieldList.h"
541#undef AUTOCOMPLETE_FIELD_NAME
542#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
543};
544
545enum AutocompleteFieldHint : uint8_t {
546#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
547#include "AutocompleteFieldList.h"
548#undef AUTOCOMPLETE_FIELD_HINT
549};
550
551enum AutocompleteFieldContactHint : uint8_t {
552#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
553 eAutocompleteFieldContactHint_##name_,
554#include "AutocompleteFieldList.h"
555#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
556};
557
558enum AutocompleteCredentialType : uint8_t {
559#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
560 eAutocompleteCredentialType_##name_,
561#include "AutocompleteFieldList.h"
562#undef AUTOCOMPLETE_CREDENTIAL_TYPE
563};
564
565enum AutocompleteCategory {
566#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
567#include "AutocompleteFieldList.h"
568#undef AUTOCOMPLETE_CATEGORY
569};
570
571static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
572#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
573 {value_, eAutocompleteUnsupportedFieldName_##name_},
574#include "AutocompleteFieldList.h"
575#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
576 {nullptr, 0}};
577
578static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = {
579#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
580 {value_, eAutocompleteNoPersistFieldName_##name_},
581#include "AutocompleteFieldList.h"
582#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
583 {nullptr, 0}};
584
585static const nsAttrValue::EnumTable
586 kAutocompleteUnsupportedContactFieldHintTable[] = {
587#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
588 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
589#include "AutocompleteFieldList.h"
590#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
591 {nullptr, 0}};
592
593static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
594#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
595 {value_, eAutocompleteFieldName_##name_},
596#include "AutocompleteFieldList.h"
597#undef AUTOCOMPLETE_FIELD_NAME
598 {nullptr, 0}};
599
600static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
601#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
602 {value_, eAutocompleteFieldName_##name_},
603#include "AutocompleteFieldList.h"
604#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
605 {nullptr, 0}};
606
607static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
608#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
609 {value_, eAutocompleteFieldHint_##name_},
610#include "AutocompleteFieldList.h"
611#undef AUTOCOMPLETE_FIELD_HINT
612 {nullptr, 0}};
613
614static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
615#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
616 {value_, eAutocompleteFieldContactHint_##name_},
617#include "AutocompleteFieldList.h"
618#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
619 {nullptr, 0}};
620
621static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = {
622#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
623 {value_, eAutocompleteCredentialType_##name_},
624#include "AutocompleteFieldList.h"
625#undef AUTOCOMPLETE_CREDENTIAL_TYPE
626 {nullptr, 0}};
627
628namespace {
629
630static PLDHashTable* sEventListenerManagersHash;
631
632// A global hashtable to for keeping the arena alive for cross docGroup node
633// adoption.
634static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
635 sDOMArenaHashtable;
636
637class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter {
638 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)static size_t MallocSizeOf(const void* aPtr) { mozilla::dmd::
Report(aPtr); return moz_malloc_size_of(aPtr); }
639
640 ~DOMEventListenerManagersHashReporter() = default;
641
642 public:
643 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:
644
645 NS_IMETHODvirtual nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
646 nsISupports* aData, bool aAnonymize) override {
647 // We don't measure the |EventListenerManager| objects pointed to by the
648 // entries because those references are non-owning.
649 int64_t amount =
650 sEventListenerManagersHash
651 ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
652 MallocSizeOf)
653 : 0;
654
655 MOZ_COLLECT_REPORT((void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table."
), aData)
656 "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table."
), aData)
657 amount, "Memory used by the event listener manager's hash table.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table."
), aData)
;
658
659 return NS_OK;
660 }
661};
662
663NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)MozExternalRefCountType DOMEventListenerManagersHashReporter::
AddRef(void) { static_assert(!std::is_destructible_v<DOMEventListenerManagersHashReporter
>, "Reference-counted class " "DOMEventListenerManagersHashReporter"
" 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
663; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("DOMEventListenerManagersHashReporter" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("DOMEventListenerManagersHashReporter" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"DOMEventListenerManagersHashReporter\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 663; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("DOMEventListenerManagersHashReporter" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"DOMEventListenerManagersHashReporter"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType DOMEventListenerManagersHashReporter
::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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 663
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("DOMEventListenerManagersHashReporter" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("DOMEventListenerManagersHashReporter" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"DOMEventListenerManagersHashReporter\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 663; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("DOMEventListenerManagersHashReporter" " not thread-safe"
); const char* const nametmp = "DOMEventListenerManagersHashReporter"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult DOMEventListenerManagersHashReporter
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 663); 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<DOMEventListenerManagersHashReporter, nsIMemoryReporter
>, int32_t( reinterpret_cast<char*>(static_cast<nsIMemoryReporter
*>((DOMEventListenerManagersHashReporter*)0x1000)) - reinterpret_cast
<char*>((DOMEventListenerManagersHashReporter*)0x1000))
}, {&mozilla::detail::kImplementedIID<DOMEventListenerManagersHashReporter
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIMemoryReporter*>((
DOMEventListenerManagersHashReporter*)0x1000))) - reinterpret_cast
<char*>((DOMEventListenerManagersHashReporter*)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; }
664
665class EventListenerManagerMapEntry : public PLDHashEntryHdr {
666 public:
667 explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {}
668
669 ~EventListenerManagerMapEntry() {
670 NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM")do { if (!(!mListenerManager)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "caller must release and disconnect ELM", "!mListenerManager"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 670); MOZ_PretendNoReturn(); } } while (0)
;
671 }
672
673 protected: // declared protected to silence clang warnings
674 const void* mKey; // must be first, to look like PLDHashEntryStub
675
676 public:
677 RefPtr<EventListenerManager> mListenerManager;
678};
679
680static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry,
681 const void* key) {
682 // Initialize the entry with placement new
683 new (entry) EventListenerManagerMapEntry(key);
684}
685
686static void EventListenerManagerHashClearEntry(PLDHashTable* table,
687 PLDHashEntryHdr* entry) {
688 EventListenerManagerMapEntry* lm =
689 static_cast<EventListenerManagerMapEntry*>(entry);
690
691 // Let the EventListenerManagerMapEntry clean itself up...
692 lm->~EventListenerManagerMapEntry();
693}
694
695class SameOriginCheckerImpl final : public nsIChannelEventSink,
696 public nsIInterfaceRequestor {
697 ~SameOriginCheckerImpl() = default;
698
699 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:
700 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
701 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
702};
703
704} // namespace
705
706void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
707 // Note: Document::SuppressEventHandling will also automatically suppress
708 // event handling for any in-process sub-documents. However, since we need
709 // to deal with cases where remote BrowsingContexts may be interleaved
710 // with in-process ones, we still need to walk the entire tree ourselves.
711 // This may be slightly redundant in some cases, but since event handling
712 // suppressions maintain a count of current blockers, it does not cause
713 // any problems.
714 aDoc->SuppressEventHandling();
715}
716
717void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
718 aDoc->UnsuppressEventHandlingAndFireEvents(true);
719}
720
721AutoSuppressEventHandling::~AutoSuppressEventHandling() {
722 UnsuppressDocuments();
723}
724
725void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
726 AutoSuppressEventHandling::SuppressDocument(aDoc);
727 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
728 win->Suspend();
729 mWindows.AppendElement(win);
730 }
731}
732
733AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
734 for (const auto& win : mWindows) {
735 win->Resume();
736 }
737}
738
739/**
740 * This class is used to determine whether or not the user is currently
741 * interacting with the browser. It listens to observer events to toggle the
742 * value of the sUserActive static.
743 *
744 * This class is an internal implementation detail.
745 * nsContentUtils::GetUserIsInteracting() should be used to access current
746 * user interaction status.
747 */
748class nsContentUtils::UserInteractionObserver final
749 : public nsIObserver,
750 public BackgroundHangAnnotator {
751 public:
752 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:
753 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
754
755 void Init();
756 void Shutdown();
757 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
758
759 static Atomic<bool> sUserActive;
760
761 private:
762 ~UserInteractionObserver() = default;
763};
764
765static constexpr nsLiteralCString kRfpPrefs[] = {
766 "privacy.resistFingerprinting"_ns,
767 "privacy.resistFingerprinting.pbmode"_ns,
768 "privacy.fingerprintingProtection"_ns,
769 "privacy.fingerprintingProtection.pbmode"_ns,
770 "privacy.fingerprintingProtection.overrides"_ns,
771};
772
773static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
774 AutoTArray<RefPtr<BrowsingContextGroup>, 5> bcGroups;
775 BrowsingContextGroup::GetAllGroups(bcGroups);
776 for (auto& bcGroup : bcGroups) {
777 AutoTArray<DocGroup*, 5> docGroups;
778 bcGroup->GetDocGroups(docGroups);
779 for (auto* docGroup : docGroups) {
780 for (Document* doc : *docGroup) {
781 if (doc->RecomputeResistFingerprinting()) {
782 if (auto* pc = doc->GetPresContext()) {
783 pc->MediaFeatureValuesChanged(
784 {MediaFeatureChangeReason::PreferenceChange},
785 MediaFeatureChangePropagation::JustThisDocument);
786 }
787 }
788 }
789 }
790 }
791}
792
793// static
794nsresult nsContentUtils::Init() {
795 if (sInitialized) {
796 NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 796)
;
797
798 return NS_OK;
799 }
800
801 nsHTMLTags::AddRefTable();
802
803 sXPConnect = nsXPConnect::XPConnect();
804 // We hold a strong ref to sXPConnect to ensure that it does not go away until
805 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
806 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
807 // various stuff already being torn down by then. Note that this means that
808 // we are effectively making sure that if we leak nsLayoutStatics then we also
809 // leak nsXPConnect.
810 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
811
812 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
813 if (!sSecurityManager) return NS_ERROR_FAILURE;
814 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
815
816 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
817 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSystemPrincipal"
")"); do { *((volatile int*)__null) = 817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
818
819 RefPtr<NullPrincipal> nullPrincipal =
820 NullPrincipal::CreateWithoutOriginAttributes();
821 if (!nullPrincipal) {
822 return NS_ERROR_FAILURE;
823 }
824
825 nullPrincipal.forget(&sNullSubjectPrincipal);
826
827 RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal =
828 BasePrincipal::CreateContentPrincipal(
829 "about:fingerprintingprotection"_ns);
830 if (!fingerprintingProtectionPrincipal) {
831 return NS_ERROR_FAILURE;
832 }
833
834 fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal);
835
836 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
837
838 if (!sEventListenerManagersHash) {
839 static const PLDHashTableOps hash_table_ops = {
840 PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub,
841 PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry,
842 EventListenerManagerHashInitEntry};
843
844 sEventListenerManagersHash =
845 new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
846
847 RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
848 }
849
850 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
851
852#ifndef RELEASE_OR_BETA
853 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
854#endif
855
856 Element::InitCCCallbacks();
857
858 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
859 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService" ")"
); do { *((volatile int*)__null) = 859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
860
861 if (XRE_IsParentProcess()) {
862 AsyncPrecreateStringBundles();
863
864#if defined(MOZ_WIDGET_ANDROID)
865 // On Android, at-shutdown ping submission isn't reliable
866 // (( because, on Android, we usually get killed, not shut down )).
867 // To have a chance at submitting the ping, aim for idle after startup.
868 nsresult rv = NS_DispatchToCurrentThreadQueue(
869 NS_NewRunnableFunction(
870 "AndroidUseCounterPingSubmitter",
871 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
872 EventQueuePriority::Idle);
873 // This is mostly best-effort, so if it goes awry, just log.
874 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 874)
;
875#endif // defined(MOZ_WIDGET_ANDROID)
876
877 RunOnShutdown(
878 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
879 ShutdownPhase::AppShutdownConfirmed);
880 }
881
882 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
883 uio->Init();
884 uio.forget(&sUserInteractionObserver);
885
886 for (const auto& pref : kRfpPrefs) {
887 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
888 }
889
890 sInitialized = true;
891
892 return NS_OK;
893}
894
895bool nsContentUtils::InitJSBytecodeMimeType() {
896 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 896); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 896; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
897 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType"
")"); do { *((volatile int*)__null) = 897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
898 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType"
")"); do { *((volatile int*)__null) = 898; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
899
900 JS::BuildIdCharVector jsBuildId;
901 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
902 return false;
903 }
904
905 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
906 sJSScriptBytecodeMimeType =
907 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
908 sJSModuleBytecodeMimeType =
909 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
910 return true;
911}
912
913void nsContentUtils::GetShiftText(nsAString& text) {
914 if (!sShiftText) InitializeModifierStrings();
915 text.Assign(*sShiftText);
916}
917
918void nsContentUtils::GetControlText(nsAString& text) {
919 if (!sControlText) InitializeModifierStrings();
920 text.Assign(*sControlText);
921}
922
923void nsContentUtils::GetCommandOrWinText(nsAString& text) {
924 if (!sCommandOrWinText) {
925 InitializeModifierStrings();
926 }
927 text.Assign(*sCommandOrWinText);
928}
929
930void nsContentUtils::GetAltText(nsAString& text) {
931 if (!sAltText) InitializeModifierStrings();
932 text.Assign(*sAltText);
933}
934
935void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
936 if (!sModifierSeparator) InitializeModifierStrings();
937 text.Assign(*sModifierSeparator);
938}
939
940void nsContentUtils::InitializeModifierStrings() {
941 // load the display strings for the keyboard accelerators
942 nsCOMPtr<nsIStringBundleService> bundleService =
943 mozilla::components::StringBundle::Service();
944 nsCOMPtr<nsIStringBundle> bundle;
945 DebugOnly<nsresult> rv = NS_OK;
946 if (bundleService) {
947 rv = bundleService->CreateBundle(
948 "chrome://global-platform/locale/platformKeys.properties",
949 getter_AddRefs(bundle));
950 }
951
952 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 954); MOZ_PretendNoReturn(); } } while (0)
953 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 954); MOZ_PretendNoReturn(); } } while (0)
954 "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 954); MOZ_PretendNoReturn(); } } while (0)
;
955 nsAutoString shiftModifier;
956 nsAutoString commandOrWinModifier;
957 nsAutoString altModifier;
958 nsAutoString controlModifier;
959 nsAutoString modifierSeparator;
960 if (bundle) {
961 // macs use symbols for each modifier key, so fetch each from the bundle,
962 // which also covers i18n
963 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
964 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
965 bundle->GetStringFromName("VK_ALT", altModifier);
966 bundle->GetStringFromName("VK_CONTROL", controlModifier);
967 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
968 }
969 // if any of these don't exist, we get an empty string
970 sShiftText = new nsString(shiftModifier);
971 sCommandOrWinText = new nsString(commandOrWinModifier);
972 sAltText = new nsString(altModifier);
973 sControlText = new nsString(controlModifier);
974 sModifierSeparator = new nsString(modifierSeparator);
975}
976
977mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
978 EventMessage aEventMessage) {
979 switch (aEventMessage) {
980#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
981 case message_: \
982 return struct_;
983#include "mozilla/EventNameList.h"
984#undef MESSAGE_TO_EVENT
985 default:
986 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ *((volatile int*)__null) = 986; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
987 return eBasicEventClass;
988 }
989}
990
991bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
992 bool doesNotReturnData = false;
993 nsresult rv = NS_URIChainHasFlags(
994 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
995 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
996}
997
998/* static */
999nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
1000 switch (aEventMessage) {
1001#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1002 case message_: \
1003 return nsGkAtoms::on##name_;
1004#include "mozilla/EventNameList.h"
1005#undef MESSAGE_TO_EVENT
1006 default:
1007 return nullptr;
1008 }
1009}
1010
1011bool nsContentUtils::InitializeEventTable() {
1012 NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!")do { if (!(!sAtomEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "EventTable already initialized!", "!sAtomEventTable", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1012); MOZ_PretendNoReturn(); } } while (0)
;
1013 NS_ASSERTION(!sStringEventTable, "EventTable already initialized!")do { if (!(!sStringEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "EventTable already initialized!", "!sStringEventTable", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1013); MOZ_PretendNoReturn(); } } while (0)
;
1014
1015 static const EventNameMapping eventArray[] = {
1016#define EVENT(name_, _message, _type, _class) \
1017 {nsGkAtoms::on##name_, _type, _message, _class},
1018#define WINDOW_ONLY_EVENT EVENT
1019#define DOCUMENT_ONLY_EVENTEVENT EVENT
1020#define NON_IDL_EVENT EVENT
1021#include "mozilla/EventNameList.h"
1022#undef WINDOW_ONLY_EVENT
1023#undef NON_IDL_EVENT
1024#undef EVENT
1025 {nullptr}};
1026
1027 sAtomEventTable =
1028 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray));
1029 sStringEventTable =
1030 new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray));
1031 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1032
1033 // Subtract one from the length because of the trailing null
1034 for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) {
1035 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.h" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1036; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1036 "Double-defining event name; fix your EventNameList.h")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.h" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1036; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1037 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1038 sStringEventTable->InsertOrUpdate(
1039 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1040 eventArray[i]);
1041 }
1042
1043 return true;
1044}
1045
1046void nsContentUtils::InitializeTouchEventTable() {
1047 static bool sEventTableInitialized = false;
1048 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1049 sEventTableInitialized = true;
1050 static const EventNameMapping touchEventArray[] = {
1051#define EVENT(name_, _message, _type, _class)
1052#define TOUCH_EVENT(name_, _message, _type, _class) \
1053 {nsGkAtoms::on##name_, _type, _message, _class},
1054#include "mozilla/EventNameList.h"
1055#undef TOUCH_EVENT
1056#undef EVENT
1057 {nullptr}};
1058 // Subtract one from the length because of the trailing null
1059 for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) {
1060 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1061 touchEventArray[i]);
1062 sStringEventTable->InsertOrUpdate(
1063 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1064 touchEventArray[i]);
1065 }
1066 }
1067}
1068
1069static bool Is8bit(const nsAString& aString) {
1070 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1071
1072 for (nsAString::const_char_iterator start = aString.BeginReading(),
1073 end = aString.EndReading();
1074 start != end; ++start) {
1075 if (*start & EIGHT_BIT) {
1076 return false;
1077 }
1078 }
1079
1080 return true;
1081}
1082
1083nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1084 nsAString& aAsciiBase64String) {
1085 if (!Is8bit(aBinaryData)) {
1086 aAsciiBase64String.Truncate();
1087 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1088 }
1089
1090 return Base64Encode(aBinaryData, aAsciiBase64String);
1091}
1092
1093nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1094 nsAString& aBinaryData) {
1095 if (!Is8bit(aAsciiBase64String)) {
1096 aBinaryData.Truncate();
1097 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1098 }
1099
1100 const char16_t* start = aAsciiBase64String.BeginReading();
1101 const char16_t* cur = start;
1102 const char16_t* end = aAsciiBase64String.EndReading();
1103 bool hasWhitespace = false;
1104
1105 while (cur < end) {
1106 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1107 hasWhitespace = true;
1108 break;
1109 }
1110 cur++;
1111 }
1112
1113 nsresult rv;
1114
1115 if (hasWhitespace) {
1116 nsString trimmedString;
1117
1118 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1119 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1120 }
1121
1122 trimmedString.Append(start, cur - start);
1123
1124 while (cur < end) {
1125 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1126 trimmedString.Append(*cur);
1127 }
1128 cur++;
1129 }
1130 rv = Base64Decode(trimmedString, aBinaryData);
1131 } else {
1132 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1133 }
1134
1135 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1136 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1137 }
1138 return rv;
1139}
1140
1141bool nsContentUtils::IsAutocompleteEnabled(
1142 mozilla::dom::HTMLInputElement* aInput) {
1143 MOZ_ASSERT(aInput, "aInput should not be null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInput)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aInput))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aInput" " (" "aInput should not be null!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInput" ") ("
"aInput should not be null!" ")"); do { *((volatile int*)__null
) = 1143; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1144
1145 nsAutoString autocomplete;
1146 aInput->GetAutocomplete(autocomplete);
1147
1148 if (autocomplete.IsEmpty()) {
1149 auto* form = aInput->GetForm();
1150 if (!form) {
1151 return true;
1152 }
1153
1154 form->GetAutocomplete(autocomplete);
1155 }
1156
1157 return !autocomplete.EqualsLiteral("off");
1158}
1159
1160nsContentUtils::AutocompleteAttrState
1161nsContentUtils::SerializeAutocompleteAttribute(
1162 const nsAttrValue* aAttr, nsAString& aResult,
1163 AutocompleteAttrState aCachedState) {
1164 if (!aAttr ||
1165 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1166 return aCachedState;
1167 }
1168
1169 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1170 uint32_t atomCount = aAttr->GetAtomCount();
1171 for (uint32_t i = 0; i < atomCount; i++) {
1172 if (i != 0) {
1173 aResult.Append(' ');
1174 }
1175 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1176 }
1177 nsContentUtils::ASCIIToLower(aResult);
1178 return aCachedState;
1179 }
1180
1181 aResult.Truncate();
1182
1183 mozilla::dom::AutocompleteInfo info;
1184 AutocompleteAttrState state =
1185 InternalSerializeAutocompleteAttribute(aAttr, info);
1186 if (state == eAutocompleteAttrState_Valid) {
1187 // Concatenate the info fields.
1188 aResult = info.mSection;
1189
1190 if (!info.mAddressType.IsEmpty()) {
1191 if (!aResult.IsEmpty()) {
1192 aResult += ' ';
1193 }
1194 aResult += info.mAddressType;
1195 }
1196
1197 if (!info.mContactType.IsEmpty()) {
1198 if (!aResult.IsEmpty()) {
1199 aResult += ' ';
1200 }
1201 aResult += info.mContactType;
1202 }
1203
1204 if (!info.mFieldName.IsEmpty()) {
1205 if (!aResult.IsEmpty()) {
1206 aResult += ' ';
1207 }
1208 aResult += info.mFieldName;
1209 }
1210
1211 // The autocomplete attribute value "webauthn" is interpreted as both a
1212 // field name and a credential type. The corresponding IDL-exposed autofill
1213 // value is "webauthn", not "webauthn webauthn".
1214 if (!info.mCredentialType.IsEmpty() &&
1215 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1216 info.mCredentialType.Equals(aResult))) {
1217 if (!aResult.IsEmpty()) {
1218 aResult += ' ';
1219 }
1220 aResult += info.mCredentialType;
1221 }
1222 }
1223
1224 return state;
1225}
1226
1227nsContentUtils::AutocompleteAttrState
1228nsContentUtils::SerializeAutocompleteAttribute(
1229 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1230 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1231 if (!aAttr ||
1232 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1233 return aCachedState;
1234 }
1235
1236 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1237 aGrantAllValidValue);
1238}
1239
1240/**
1241 * Helper to validate the @autocomplete tokens.
1242 *
1243 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1244 */
1245nsContentUtils::AutocompleteAttrState
1246nsContentUtils::InternalSerializeAutocompleteAttribute(
1247 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1248 bool aGrantAllValidValue) {
1249 // No autocomplete attribute so we are done
1250 if (!aAttrVal) {
1251 return eAutocompleteAttrState_Invalid;
1252 }
1253
1254 uint32_t numTokens = aAttrVal->GetAtomCount();
1255 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1256 return eAutocompleteAttrState_Invalid;
1257 }
1258
1259 uint32_t index = numTokens - 1;
1260 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1261 AutocompleteCategory category;
1262 nsAttrValue enumValue;
1263 nsAutoString credentialTypeStr;
1264
1265 bool result = enumValue.ParseEnumValue(
1266 tokenString, kAutocompleteCredentialTypeTable, false);
1267 if (result) {
1268 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1269 return eAutocompleteAttrState_Invalid;
1270 }
1271 enumValue.ToString(credentialTypeStr);
1272 ASCIIToLower(credentialTypeStr);
1273 // category is Credential and the indexth token is "webauthn"
1274 if (index == 0) {
1275 aInfo.mFieldName.Assign(credentialTypeStr);
1276 aInfo.mCredentialType.Assign(credentialTypeStr);
1277 return eAutocompleteAttrState_Valid;
1278 }
1279
1280 --index;
1281 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1282
1283 // Only the Normal and Contact categories are allowed with webauthn
1284 // - disallow Credential
1285 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1286 false)) {
1287 return eAutocompleteAttrState_Invalid;
1288 }
1289 // - disallow Off and Automatic
1290 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1291 false)) {
1292 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1293 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1294 return eAutocompleteAttrState_Invalid;
1295 }
1296 }
1297
1298 // Proceed to process the remaining tokens as if "webauthn" was not present.
1299 // We need to decrement numTokens to enforce the correct per-category limits
1300 // on the maximum number of tokens.
1301 --numTokens;
1302 }
1303
1304 bool unsupported = false;
1305 if (!aGrantAllValidValue) {
1306 unsupported = enumValue.ParseEnumValue(
1307 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1308 if (unsupported) {
1309 return eAutocompleteAttrState_Invalid;
1310 }
1311 }
1312
1313 nsAutoString fieldNameStr;
1314 result =
1315 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1316
1317 if (result) {
1318 // Off/Automatic/Normal categories.
1319 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1320 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1321 if (numTokens > 1) {
1322 return eAutocompleteAttrState_Invalid;
1323 }
1324 enumValue.ToString(fieldNameStr);
1325 ASCIIToLower(fieldNameStr);
1326 aInfo.mFieldName.Assign(fieldNameStr);
1327 aInfo.mCredentialType.Assign(credentialTypeStr);
1328 aInfo.mCanAutomaticallyPersist =
1329 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1330 return eAutocompleteAttrState_Valid;
1331 }
1332
1333 // Only allow on/off if form autofill @autocomplete values aren't enabled
1334 // and it doesn't grant all valid values.
1335 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1336 !aGrantAllValidValue) {
1337 return eAutocompleteAttrState_Invalid;
1338 }
1339
1340 // Normal category
1341 if (numTokens > 3) {
1342 return eAutocompleteAttrState_Invalid;
1343 }
1344 category = eAutocompleteCategory_NORMAL;
1345 } else { // Check if the last token is of the contact category instead.
1346 // Only allow on/off if form autofill @autocomplete values aren't enabled
1347 // and it doesn't grant all valid values.
1348 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1349 !aGrantAllValidValue) {
1350 return eAutocompleteAttrState_Invalid;
1351 }
1352
1353 result = enumValue.ParseEnumValue(
1354 tokenString, kAutocompleteContactFieldNameTable, false);
1355 if (!result || numTokens > 4) {
1356 return eAutocompleteAttrState_Invalid;
1357 }
1358
1359 category = eAutocompleteCategory_CONTACT;
1360 }
1361
1362 enumValue.ToString(fieldNameStr);
1363 ASCIIToLower(fieldNameStr);
1364
1365 aInfo.mFieldName.Assign(fieldNameStr);
1366 aInfo.mCredentialType.Assign(credentialTypeStr);
1367 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1368 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1369
1370 // We are done if this was the only token.
1371 if (numTokens == 1) {
1372 return eAutocompleteAttrState_Valid;
1373 }
1374
1375 --index;
1376 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1377
1378 if (category == eAutocompleteCategory_CONTACT) {
1379 if (!aGrantAllValidValue) {
1380 unsupported = enumValue.ParseEnumValue(
1381 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1382 if (unsupported) {
1383 return eAutocompleteAttrState_Invalid;
1384 }
1385 }
1386
1387 nsAttrValue contactFieldHint;
1388 result = contactFieldHint.ParseEnumValue(
1389 tokenString, kAutocompleteContactFieldHintTable, false);
1390 if (result) {
1391 nsAutoString contactFieldHintString;
1392 contactFieldHint.ToString(contactFieldHintString);
1393 ASCIIToLower(contactFieldHintString);
1394 aInfo.mContactType.Assign(contactFieldHintString);
1395 if (index == 0) {
1396 return eAutocompleteAttrState_Valid;
1397 }
1398 --index;
1399 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1400 }
1401 }
1402
1403 // Check for billing/shipping tokens
1404 nsAttrValue fieldHint;
1405 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1406 false)) {
1407 nsString fieldHintString;
1408 fieldHint.ToString(fieldHintString);
1409 ASCIIToLower(fieldHintString);
1410 aInfo.mAddressType.Assign(fieldHintString);
1411 if (index == 0) {
1412 return eAutocompleteAttrState_Valid;
1413 }
1414 --index;
1415 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1416 }
1417
1418 // Check for section-* token
1419 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1420 if (section.LowerCaseEqualsASCII("section-")) {
1421 ASCIIToLower(tokenString);
1422 aInfo.mSection.Assign(tokenString);
1423 if (index == 0) {
1424 return eAutocompleteAttrState_Valid;
1425 }
1426 }
1427
1428 // Clear the fields as the autocomplete attribute is invalid.
1429 aInfo.mSection.Truncate();
1430 aInfo.mAddressType.Truncate();
1431 aInfo.mContactType.Truncate();
1432 aInfo.mFieldName.Truncate();
1433 aInfo.mCredentialType.Truncate();
1434
1435 return eAutocompleteAttrState_Invalid;
1436}
1437
1438// Parse an integer according to HTML spec
1439template <class CharT>
1440int32_t nsContentUtils::ParseHTMLIntegerImpl(
1441 const CharT* aStart, const CharT* aEnd,
1442 ParseHTMLIntegerResultFlags* aResult) {
1443 int result = eParseHTMLInteger_NoFlags;
1444
1445 const CharT* iter = aStart;
1446
1447 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1448 result |= eParseHTMLInteger_NonStandard;
1449 ++iter;
1450 }
1451
1452 if (iter == aEnd) {
1453 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1454 *aResult = (ParseHTMLIntegerResultFlags)result;
1455 return 0;
1456 }
1457
1458 int sign = 1;
1459 if (*iter == CharT('-')) {
1460 sign = -1;
1461 result |= eParseHTMLInteger_Negative;
1462 ++iter;
1463 } else if (*iter == CharT('+')) {
1464 result |= eParseHTMLInteger_NonStandard;
1465 ++iter;
1466 }
1467
1468 bool foundValue = false;
1469 CheckedInt32 value = 0;
1470
1471 // Check for leading zeros first.
1472 uint64_t leadingZeros = 0;
1473 while (iter != aEnd) {
1474 if (*iter != CharT('0')) {
1475 break;
1476 }
1477
1478 ++leadingZeros;
1479 foundValue = true;
1480 ++iter;
1481 }
1482
1483 while (iter != aEnd) {
1484 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1485 value = (value * 10) + (*iter - CharT('0')) * sign;
1486 ++iter;
1487 if (!value.isValid()) {
1488 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1489 break;
1490 }
1491 foundValue = true;
1492 } else {
1493 break;
1494 }
1495 }
1496
1497 if (!foundValue) {
1498 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1499 }
1500
1501 if (value.isValid() &&
1502 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1503 (sign == -1 && value == 0))) {
1504 result |= eParseHTMLInteger_NonStandard;
1505 }
1506
1507 if (iter != aEnd) {
1508 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1509 }
1510
1511 *aResult = (ParseHTMLIntegerResultFlags)result;
1512 return value.isValid() ? value.value() : 0;
1513}
1514
1515// Parse an integer according to HTML spec
1516int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1517 const char16_t* aEnd,
1518 ParseHTMLIntegerResultFlags* aResult) {
1519 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1520}
1521
1522int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1523 ParseHTMLIntegerResultFlags* aResult) {
1524 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1525}
1526
1527#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
1528 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
1529 ++(iter); \
1530 } \
1531 if ((iter) == (end_iter)) { \
1532 return (end_res); \
1533 }
1534
1535#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
1536 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
1537 *(iter) != '=') { \
1538 ++(iter); \
1539 }
1540
1541bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
1542 nsAtom* aName, nsAString& aValue) {
1543 aValue.Truncate();
1544
1545 const char16_t* start = aSource.get();
1546 const char16_t* end = start + aSource.Length();
1547 const char16_t* iter;
1548
1549 while (start != end) {
1550 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1551 iter = start;
1552 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
1553
1554 if (start == iter) {
1555 return false;
1556 }
1557
1558 // Remember the attr name.
1559 const nsDependentSubstring& attrName = Substring(start, iter);
1560
1561 // Now check whether this is a valid name="value" pair.
1562 start = iter;
1563 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1564 if (*start != '=') {
1565 // No '=', so this is not a name="value" pair. We don't know
1566 // what it is, and we have no way to handle it.
1567 return false;
1568 }
1569
1570 // Have to skip the value.
1571 ++start;
1572 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1573 char16_t q = *start;
1574 if (q != kQuote && q != kApostrophe) {
1575 // Not a valid quoted value, so bail.
1576 return false;
1577 }
1578
1579 ++start; // Point to the first char of the value.
1580 iter = start;
1581
1582 while (iter != end && *iter != q) {
1583 ++iter;
1584 }
1585
1586 if (iter == end) {
1587 // Oops, unterminated quoted string.
1588 return false;
1589 }
1590
1591 // At this point attrName holds the name of the "attribute" and
1592 // the value is between start and iter.
1593
1594 if (aName->Equals(attrName)) {
1595 // We'll accumulate as many characters as possible (until we hit either
1596 // the end of the string or the beginning of an entity). Chunks will be
1597 // delimited by start and chunkEnd.
1598 const char16_t* chunkEnd = start;
1599 while (chunkEnd != iter) {
1600 if (*chunkEnd == kLessThan) {
1601 aValue.Truncate();
1602
1603 return false;
1604 }
1605
1606 if (*chunkEnd == kAmpersand) {
1607 aValue.Append(start, chunkEnd - start);
1608
1609 const char16_t* afterEntity = nullptr;
1610 char16_t result[2];
1611 uint32_t count = MOZ_XMLTranslateEntity(
1612 reinterpret_cast<const char*>(chunkEnd),
1613 reinterpret_cast<const char*>(iter),
1614 reinterpret_cast<const char**>(&afterEntity), result);
1615 if (count == 0) {
1616 aValue.Truncate();
1617
1618 return false;
1619 }
1620
1621 aValue.Append(result, count);
1622
1623 // Advance to after the entity and begin a new chunk.
1624 start = chunkEnd = afterEntity;
1625 } else {
1626 ++chunkEnd;
1627 }
1628 }
1629
1630 // Append remainder.
1631 aValue.Append(start, iter - start);
1632
1633 return true;
1634 }
1635
1636 // Resume scanning after the end of the attribute value (past the quote
1637 // char).
1638 start = iter + 1;
1639 }
1640
1641 return false;
1642}
1643
1644bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
1645 // Create MIME type as "text/" + given input
1646 nsAutoString mimeType(u"text/");
1647 mimeType.Append(aName);
1648
1649 return IsJavascriptMIMEType(mimeType);
1650}
1651
1652void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
1653 nsString& aParams) {
1654 aType.Truncate();
1655 aParams.Truncate();
1656 int32_t semiIndex = aValue.FindChar(char16_t(';'));
1657 if (-1 != semiIndex) {
1658 aType = Substring(aValue, 0, semiIndex);
1659 aParams =
1660 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
1661 aParams.StripWhitespace();
1662 } else {
1663 aType = aValue;
1664 }
1665 aType.StripWhitespace();
1666}
1667
1668/**
1669 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
1670 * directive) and converts it to the set of flags used internally.
1671 *
1672 * @param aSandboxAttr the sandbox attribute
1673 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
1674 * null)
1675 */
1676uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
1677 const nsAttrValue* aSandboxAttr) {
1678 if (!aSandboxAttr) {
1679 return SANDBOXED_NONE;
1680 }
1681
1682 uint32_t out = SANDBOX_ALL_FLAGS;
1683
1684#define SANDBOX_KEYWORD(string, atom, flags) \
1685 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
1686 out &= ~(flags); \
1687 }
1688#include "IframeSandboxKeywordList.h"
1689#undef SANDBOX_KEYWORD
1690
1691 return out;
1692}
1693
1694/**
1695 * A helper function that checks if a string matches a valid sandbox flag.
1696 *
1697 * @param aFlag the potential sandbox flag.
1698 * @return true if the flag is a sandbox flag.
1699 */
1700bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
1701#define SANDBOX_KEYWORD(string, atom, flags) \
1702 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
1703 return true; \
1704 }
1705#include "IframeSandboxKeywordList.h"
1706#undef SANDBOX_KEYWORD
1707 return false;
1708}
1709
1710/**
1711 * A helper function that returns a string attribute corresponding to the
1712 * sandbox flags.
1713 *
1714 * @param aFlags the sandbox flags
1715 * @param aString the attribute corresponding to the flags (null if aFlags
1716 * is zero)
1717 */
1718void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
1719 if (!aFlags) {
1720 SetDOMStringToNull(aString);
1721 return;
1722 }
1723
1724 aString.Truncate();
1725
1726#define SANDBOX_KEYWORD(string, atom, flags) \
1727 if (!(aFlags & (flags))) { \
1728 if (!aString.IsEmpty()) { \
1729 aString.AppendLiteral(u" "); \
1730 } \
1731 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
1732 }
1733#include "IframeSandboxKeywordList.h"
1734#undef SANDBOX_KEYWORD
1735}
1736
1737nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
1738 if (!sBidiKeyboard) {
1739 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
1740 }
1741 return sBidiKeyboard;
1742}
1743
1744/**
1745 * This is used to determine whether a character is in one of the classes
1746 * which CSS says should be part of the first-letter. Currently, that is
1747 * all punctuation classes (P*). Note that this is a change from CSS2
1748 * which excluded Pc and Pd.
1749 *
1750 * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
1751 * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
1752 * general category [UAX44]) [...]"
1753 */
1754
1755// static
1756bool nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar) {
1757 switch (mozilla::unicode::GetGeneralCategory(aChar)) {
1758 case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
1759 case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */
1760 case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */
1761 case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */
1762 case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
1763 case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */
1764 case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */
1765 return true;
1766 default:
1767 return false;
1768 }
1769}
1770
1771// static
1772bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
1773 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1774
1775 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
1776}
1777
1778// static
1779bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
1780 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1781
1782 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
1783 cat == nsUGenCategory::kSymbol;
1784}
1785
1786// static
1787bool nsContentUtils::IsHyphen(uint32_t aChar) {
1788 // Characters treated as hyphens for the purpose of "emergency" breaking
1789 // when the content would otherwise overflow.
1790 return aChar == uint32_t('-') || // HYPHEN-MINUS
1791 aChar == 0x2010 || // HYPHEN
1792 aChar == 0x2012 || // FIGURE DASH
1793 aChar == 0x2013 || // EN DASH
1794 aChar == 0x058A; // ARMENIAN HYPHEN
1795}
1796
1797/* static */
1798bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
1799 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
1800 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
1801 aChar == char16_t(0x0020);
1802}
1803
1804/* static */
1805bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
1806 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
1807}
1808
1809/* static */
1810bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
1811 return aContent->IsAnyOfHTMLElements(
1812 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
1813 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
1814 nsGkAtoms::dl, // XXX why not dt and dd?
1815 nsGkAtoms::fieldset,
1816 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
1817 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
1818 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
1819 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
1820 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
1821 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
1822 nsGkAtoms::ul, nsGkAtoms::xmp);
1823}
1824
1825// static
1826int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
1827 nsAString::const_iterator iter, end;
1828 aValue.BeginReading(iter);
1829 aValue.EndReading(end);
1830
1831 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
1832 ++iter;
1833 }
1834
1835 if (iter == end) {
1836 return 0;
1837 }
1838
1839 bool relative = false;
1840 bool negate = false;
1841 if (*iter == char16_t('-')) {
1842 relative = true;
1843 negate = true;
1844 ++iter;
1845 } else if (*iter == char16_t('+')) {
1846 relative = true;
1847 ++iter;
1848 }
1849
1850 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
1851 return 0;
1852 }
1853
1854 // We don't have to worry about overflow, since we can bail out as soon as
1855 // we're bigger than 7.
1856 int32_t value = 0;
1857 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
1858 value = 10 * value + (*iter - char16_t('0'));
1859 if (value >= 7) {
1860 break;
1861 }
1862 ++iter;
1863 }
1864
1865 if (relative) {
1866 if (negate) {
1867 value = 3 - value;
1868 } else {
1869 value = 3 + value;
1870 }
1871 }
1872
1873 return std::clamp(value, 1, 7);
1874}
1875
1876/* static */
1877void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
1878 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1878); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1878; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1879 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 1879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1880 *aURI = nullptr;
1881
1882 if (aDocument->GetController().isSome()) {
1883 return;
1884 }
1885
1886 Element* docElement = aDocument->GetRootElement();
1887 if (!docElement) {
1888 return;
1889 }
1890
1891 nsAutoString manifestSpec;
1892 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
1893
1894 // Manifest URIs can't have fragment identifiers.
1895 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
1896 return;
1897 }
1898
1899 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
1900 aDocument->GetDocBaseURI());
1901}
1902
1903/* static */
1904bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
1905
1906/* static */
1907bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
1908 return false;
1909}
1910// Static
1911bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
1912 if (!aURI) {
1913 return false;
1914 }
1915
1916 if (!aURI->SchemeIs("about")) {
1917 return false;
1918 }
1919
1920 nsAutoCString name;
1921 nsresult rv = NS_GetAboutModuleName(aURI, name);
1922 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1922); return false; } } while (false)
;
1923
1924 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
1925 name.EqualsLiteral("blocked");
1926}
1927
1928// static
1929void nsContentUtils::Shutdown() {
1930 sInitialized = false;
1931
1932 nsHTMLTags::ReleaseTable();
1933
1934 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
1935 sTriedToGetContentPolicy = false;
1936 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
1937 bundle = nullptr;
1938 }
1939
1940 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
1941 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
1942 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
1943 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
1944 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
1945 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
1946 NS_IF_RELEASE(sFingerprintingProtectionPrincipal)do { if (sFingerprintingProtectionPrincipal) { (sFingerprintingProtectionPrincipal
)->Release(); (sFingerprintingProtectionPrincipal) = 0; } }
while (0)
;
1947
1948 sBidiKeyboard = nullptr;
1949
1950 delete sAtomEventTable;
1951 sAtomEventTable = nullptr;
1952 delete sStringEventTable;
1953 sStringEventTable = nullptr;
1954 delete sUserDefinedEvents;
1955 sUserDefinedEvents = nullptr;
1956
1957 if (sEventListenerManagersHash) {
1958 NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0,do { if (!(sEventListenerManagersHash->EntryCount() == 0))
{ NS_DebugBreak(NS_DEBUG_ASSERTION, "Event listener manager hash not empty at shutdown!"
, "sEventListenerManagersHash->EntryCount() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1959); MOZ_PretendNoReturn(); } } while (0)
1959 "Event listener manager hash not empty at shutdown!")do { if (!(sEventListenerManagersHash->EntryCount() == 0))
{ NS_DebugBreak(NS_DEBUG_ASSERTION, "Event listener manager hash not empty at shutdown!"
, "sEventListenerManagersHash->EntryCount() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1959); MOZ_PretendNoReturn(); } } while (0)
;
1960
1961 // See comment above.
1962
1963 // However, we have to handle this table differently. If it still
1964 // has entries, we want to leak it too, so that we can keep it alive
1965 // in case any elements are destroyed. Because if they are, we need
1966 // their event listener managers to be destroyed too, or otherwise
1967 // it could leave dangling references in DOMClassInfo's preserved
1968 // wrapper table.
1969
1970 if (sEventListenerManagersHash->EntryCount() == 0) {
1971 delete sEventListenerManagersHash;
1972 sEventListenerManagersHash = nullptr;
1973 }
1974 }
1975
1976 if (sDOMArenaHashtable) {
1977 MOZ_ASSERT(sDOMArenaHashtable->Count() == 0)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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0"
")"); do { *((volatile int*)__null) = 1977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1978 MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 1978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1979 delete sDOMArenaHashtable;
1980 sDOMArenaHashtable = nullptr;
1981 }
1982
1983 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1984); MOZ_PretendNoReturn(); } } while (0)
1984 "How'd this happen?")do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners->
Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?"
, "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 1984); MOZ_PretendNoReturn(); } } while (0)
;
1985 delete sBlockedScriptRunners;
1986 sBlockedScriptRunners = nullptr;
1987
1988 delete sShiftText;
1989 sShiftText = nullptr;
1990 delete sControlText;
1991 sControlText = nullptr;
1992 delete sCommandOrWinText;
1993 sCommandOrWinText = nullptr;
1994 delete sAltText;
1995 sAltText = nullptr;
1996 delete sModifierSeparator;
1997 sModifierSeparator = nullptr;
1998
1999 delete sJSScriptBytecodeMimeType;
2000 sJSScriptBytecodeMimeType = nullptr;
2001
2002 delete sJSModuleBytecodeMimeType;
2003 sJSModuleBytecodeMimeType = nullptr;
2004
2005 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2006
2007 if (sUserInteractionObserver) {
2008 sUserInteractionObserver->Shutdown();
2009 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2010 }
2011
2012 for (const auto& pref : kRfpPrefs) {
2013 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2014 }
2015
2016 TextControlState::Shutdown();
2017}
2018
2019/**
2020 * Checks whether two nodes come from the same origin. aTrustedNode is
2021 * considered 'safe' in that a user can operate on it.
2022 */
2023// static
2024nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2025 const nsINode* unTrustedNode) {
2026 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { *((volatile int*)__null) = 2026; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2027 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",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "unTrustedNode"
")"); do { *((volatile int*)__null) = 2027; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2028
2029 /*
2030 * Get hold of each node's principal
2031 */
2032
2033 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2034 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2035
2036 if (trustedPrincipal == unTrustedPrincipal) {
2037 return NS_OK;
2038 }
2039
2040 bool equal;
2041 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2042 // a separate method for that, with callers using one or the other?
2043 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2044 !equal) {
2045 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2046 }
2047
2048 return NS_OK;
2049}
2050
2051// static
2052bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2053 nsIPrincipal* aPrincipal) {
2054 bool subsumes;
2055 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2056 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2056); return false; } } while (false)
;
2057
2058 if (subsumes) {
2059 return true;
2060 }
2061
2062 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2063 // is chrome.
2064 return IsCallerChrome();
2065}
2066
2067// static
2068bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2069 nsIPrincipal* subject = SubjectPrincipal();
2070 if (subject->IsSystemPrincipal()) {
2071 return true;
2072 }
2073
2074 if (aNode->ChromeOnlyAccess()) {
2075 return false;
2076 }
2077
2078 return CanCallerAccess(subject, aNode->NodePrincipal());
2079}
2080
2081// static
2082bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2083 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2084 NS_ENSURE_TRUE(scriptObject, false)do { if ((__builtin_expect(!!(!(scriptObject)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptObject" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2084); return false; } } while (false)
;
2085
2086 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2087}
2088
2089// static
2090bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2091 const nsAtom* aPerm) {
2092 // Chrome gets access by default.
2093 if (aPrincipal.IsSystemPrincipal()) {
2094 return true;
2095 }
2096
2097 // Otherwise, only allow if caller is an addon with the permission.
2098 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2099}
2100
2101// static
2102bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2103 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2104}
2105
2106// static
2107nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2108 nsIContent* aContent, const nsAString& aAttrValue,
2109 nsIPrincipal* aSubjectPrincipal) {
2110 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2111
2112 // If the subject principal is the same as the content principal, or no
2113 // explicit subject principal was provided, we don't need to do any further
2114 // checks. Just return the content principal.
2115 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2116 return contentPrin;
2117 }
2118
2119 // Only use the subject principal if the URL string we are going to end up
2120 // fetching is under the control of that principal, which is never the case
2121 // for relative URLs.
2122 if (aAttrValue.IsEmpty() ||
2123 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2124 return contentPrin;
2125 }
2126
2127 // Only use the subject principal as the attr triggering principal if it
2128 // should override the CSP of the node's principal.
2129 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2130 return aSubjectPrincipal;
2131 }
2132
2133 return contentPrin;
2134}
2135
2136// static
2137bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2138 nsAutoCString scheme;
2139 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2140 // If we can't extract a scheme, it's not an absolute URL.
2141 return false;
2142 }
2143
2144 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2145 // so no need to check with the IO service.
2146 if (net_IsAbsoluteURL(aURL)) {
2147 return true;
2148 }
2149
2150 nsresult rv = NS_OK;
2151 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2152 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2152); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2153 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2154 return false;
2155 }
2156
2157 uint32_t flags;
2158 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2159 return flags & nsIProtocolHandler::URI_NORELATIVE;
2160 }
2161
2162 return false;
2163}
2164
2165// static
2166bool nsContentUtils::InProlog(nsINode* aNode) {
2167 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") ("
"missing node to nsContentUtils::InProlog" ")"); do { *((volatile
int*)__null) = 2167; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2168
2169 nsINode* parent = aNode->GetParentNode();
2170 if (!parent || !parent->IsDocument()) {
2171 return false;
2172 }
2173
2174 const Document* doc = parent->AsDocument();
2175 const nsIContent* root = doc->GetRootElement();
2176 if (!root) {
2177 return true;
2178 }
2179 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2180 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2181 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2182 return *indexOfNode < *indexOfRoot;
2183 }
2184 // XXX Keep the odd traditional behavior for now.
2185 return indexOfNode.isNothing() && indexOfRoot.isSome();
2186}
2187
2188bool nsContentUtils::IsCallerChrome() {
2189 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2189; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2190 return SubjectPrincipal() == sSystemPrincipal;
2191}
2192
2193#ifdef FUZZING
2194bool nsContentUtils::IsFuzzingEnabled() {
2195 return StaticPrefs::fuzzing_enabled();
2196}
2197#endif
2198
2199/* static */
2200bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2201 JSContext* aCx, JSObject*) {
2202 return ThreadsafeIsSystemCaller(aCx) ||
2203 StaticPrefs::dom_element_transform_getters_enabled();
2204}
2205
2206// Older Should RFP Functions ----------------------------------
2207
2208/* static */
2209bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2210 RFPTarget aTarget) {
2211 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2212}
2213
2214/* static */
2215bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2216 RFPTarget aTarget) {
2217 if (!aGlobalObject) {
2218 return ShouldResistFingerprinting("Null Object", aTarget);
2219 }
2220 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2221}
2222
2223// Newer Should RFP Functions ----------------------------------
2224// Utilities ---------------------------------------------------
2225
2226inline void LogDomainAndPrefList(const char* urlType,
2227 const char* exemptedDomainsPrefName,
2228 nsAutoCString& url, bool isExemptDomain) {
2229 nsAutoCString list;
2230 Preferences::GetCString(exemptedDomainsPrefName, list);
2231 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)
2232 ("%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)
2233 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)
2234 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)
;
2235}
2236
2237inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2238 nsILoadInfo* aLoadInfo) {
2239 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2240 nsresult rv =
2241 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2242 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2243 // The TRRLoadInfo in particular does not implement this method
2244 // In that instance. We will return false and let other code decide if
2245 // we shouldRFP for this connection
2246 return nullptr;
2247 }
2248 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2248)
) {
2249 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)
2250 ("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)
2251 "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)
;
2252 return nullptr;
2253 }
2254
2255 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cookieJarSettings"
")"); do { *((volatile int*)__null) = 2255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2256 return cookieJarSettings.forget();
2257}
2258
2259bool ETPSaysShouldNotResistFingerprinting(nsIChannel* aChannel,
2260 nsILoadInfo* aLoadInfo) {
2261 // A positive return from this function should always be obeyed.
2262 // A negative return means we should keep checking things.
2263
2264 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2265 // We do not want this check to apply to RFP, only to FPP
2266 // There is one problematic combination of prefs; however:
2267 // If RFP is enabled in PBMode only and FPP is enabled globally
2268 // (so, in non-PBM mode) - we need to know if we're in PBMode or not.
2269 // But that's kind of expensive and we'd like to avoid it if we
2270 // don't have to, so special-case that scenario
2271 if (StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly() &&
2272 !StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2273 StaticPrefs::privacy_resistFingerprinting_pbmode_DoNotUseDirectly()) {
2274 if (isPBM) {
2275 // In PBM (where RFP is enabled) do not exempt based on the ETP toggle
2276 return false;
2277 }
2278 } else if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() ||
2279 (isPBM &&
2280 StaticPrefs::
2281 privacy_resistFingerprinting_pbmode_DoNotUseDirectly())) {
2282 // In RFP, never use the ETP toggle to exempt.
2283 // We can safely return false here even if we are not in PBM mode
2284 // and RFP_pbmode is enabled because we will later see that and
2285 // return false from the ShouldRFP function entirely.
2286 return false;
2287 }
2288
2289 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2290 GetCookieJarSettings(aLoadInfo);
2291 if (!cookieJarSettings) {
2292 return false;
2293 }
2294
2295 return ContentBlockingAllowList::Check(cookieJarSettings);
2296}
2297
2298inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2299 nsILoadInfo* aLoadInfo) {
2300 // A positive return from this function should always be obeyed.
2301 // A negative return means we should keep checking things.
2302
2303 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2304 GetCookieJarSettings(aLoadInfo);
2305 if (!cookieJarSettings) {
2306 return false;
2307 }
2308 return cookieJarSettings->GetShouldResistFingerprinting();
2309}
2310
2311inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2312 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2313 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2314 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2315}
2316
2317inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2318 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2319 aPrincipal->SchemeIs("view-source") ||
2320 aPrincipal->SchemeIs("moz-extension")) {
2321 return true;
2322 }
2323
2324 if (!aPrincipal->SchemeIs("about")) {
2325 return false;
2326 }
2327
2328 bool isContentAccessibleAboutURI;
2329 Unused << aPrincipal->IsContentAccessibleAboutURI(
2330 &isContentAccessibleAboutURI);
2331 return !isContentAccessibleAboutURI;
2332}
2333
2334const char* kExemptedDomainsPrefName =
2335 "privacy.resistFingerprinting.exemptedDomains";
2336
2337inline bool PartionKeyIsAlsoExempted(
2338 const mozilla::OriginAttributes& aOriginAttributes) {
2339 // If we've gotten here we have (probably) passed the CookieJarSettings
2340 // check that would tell us that if we _are_ a subdocument, then we are on
2341 // an exempted top-level domain and we should see if we ourselves are
2342 // exempted. But we may have gotten here because we directly called the
2343 // _dangerous function and we haven't done that check, but we _were_
2344 // instatiated from a state where we could have been partitioned.
2345 // So perform this last-ditch check for that scenario.
2346 // We arbitrarily use https as the scheme, but it doesn't matter.
2347 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2348 nsCOMPtr<nsIURI> uri;
2349 if (StaticPrefs::privacy_firstparty_isolate() &&
2350 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2351 rv = NS_NewURI(getter_AddRefs(uri),
2352 u"https://"_ns + aOriginAttributes.mFirstPartyDomain);
2353 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2354 rv = NS_NewURI(getter_AddRefs(uri),
2355 u"https://"_ns + aOriginAttributes.mPartitionKey);
2356 }
2357
2358 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2359 bool isExemptPartitionKey =
2360 nsContentUtils::IsURIInPrefList(uri, kExemptedDomainsPrefName);
2361 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2362 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2363 nsAutoCString url;
2364 uri->GetHost(url);
2365 LogDomainAndPrefList("Partition Key", kExemptedDomainsPrefName, url,
2366 isExemptPartitionKey);
2367 }
2368 return isExemptPartitionKey;
2369 }
2370 return true;
2371}
2372
2373// Functions ---------------------------------------------------
2374
2375/* static */
2376bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2377 RFPTarget aTarget) {
2378 // See comment in header file for information about usage
2379 // We hardcode PBM to true to be the more restrictive option.
2380 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2381}
2382
2383namespace {
2384
2385// This function is only called within this file for Positive Return Checks
2386bool ShouldResistFingerprinting_(const char* aJustification,
2387 bool aIsPrivateMode, RFPTarget aTarget) {
2388 // See comment in header file for information about usage
2389 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2390}
2391
2392} // namespace
2393
2394/* static */
2395bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2396 nsIGlobalObject* aGlobalObject,
2397 RFPTarget aTarget) {
2398 if (aCallerType == CallerType::System) {
2399 return false;
2400 }
2401 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2402}
2403
2404bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2405 RFPTarget aTarget) {
2406 if (!aDocShell) {
2407 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)
2408 ("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)
2409 "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)
;
2410 return ShouldResistFingerprinting("Null Object", aTarget);
2411 }
2412 Document* doc = aDocShell->GetDocument();
2413 if (!doc) {
2414 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 doc"); } } while (0)
2415 ("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 doc"); } } while (0)
2416 "with NULL doc"))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 doc"); } } while (0)
;
2417 return ShouldResistFingerprinting("Null Object", aTarget);
2418 }
2419 return doc->ShouldResistFingerprinting(aTarget);
2420}
2421
2422/* static */
2423bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2424 RFPTarget aTarget) {
2425 if (!aChannel) {
2426 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)
2427 ("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)
2428 "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)
;
2429 return ShouldResistFingerprinting("Null Object", aTarget);
2430 }
2431
2432 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
2433 if (!loadInfo) {
2434 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)
2435 ("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)
2436 "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)
;
2437 return ShouldResistFingerprinting("Null Object", aTarget);
2438 }
2439
2440 // With this check, we can ensure that the prefs and target say yes, so only
2441 // an exemption would cause us to return false.
2442 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2443 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2444 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)
2445 ("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)
2446 " 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)
2447 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)
;
2448 return false;
2449 }
2450
2451 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
2452 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)
2453 ("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)
2454 " 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)
;
2455 return false;
2456 }
2457
2458 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
2459 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)
2460 ("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)
2461 " 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)
;
2462 return true;
2463 }
2464
2465 // Document types have no loading principal. Subdocument types do have a
2466 // loading principal, but it is the loading principal of the parent
2467 // document; not the subdocument.
2468 auto contentType = loadInfo->GetExternalContentPolicyType();
2469 // Case 1: Document or Subdocument load
2470 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
2471 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2472 nsCOMPtr<nsIURI> channelURI;
2473 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2474 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)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2475 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)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2476 "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)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2477 "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)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2478 // this check is to ensure that we do not crash in non-debug builds.
2479 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2480 return true;
2481 }
2482
2483#if 0
2484 if (loadInfo->GetExternalContentPolicyType() == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2485 nsCOMPtr<nsIURI> channelURI;
2486 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2487 nsAutoCString channelSpec;
2488 channelURI->GetSpec(channelSpec);
2489
2490 if (!loadInfo->GetLoadingPrincipal()) {
2491 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, "Sub Document Type. FinalChannelURI is %s, Loading Principal is NULL\n"
, channelSpec.get()); } } while (0)
2492 ("Sub Document Type. FinalChannelURI is %s, Loading Principal is NULL\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 is NULL\n"
, channelSpec.get()); } } while (0)
2493 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 is NULL\n"
, channelSpec.get()); } } while (0)
;
2494
2495 } else {
2496 nsAutoCString loadingPrincipalSpec;
2497 loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec);
2498
2499 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, "Sub Document Type. FinalChannelURI is %s, Loading Principal Origin is %s\n"
, channelSpec.get(), loadingPrincipalSpec.get()); } } while (
0)
2500 ("Sub Document Type. FinalChannelURI is %s, Loading Principal Origin is %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 Origin is %s\n"
, channelSpec.get(), loadingPrincipalSpec.get()); } } while (
0)
2501 channelSpec.get(), loadingPrincipalSpec.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 Origin is %s\n"
, channelSpec.get(), loadingPrincipalSpec.get()); } } while (
0)
;
2502 }
2503 }
2504
2505#endif
2506
2507 return ShouldResistFingerprinting_dangerous(
2508 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
2509 }
2510
2511 // Case 2: Subresource Load
2512 // Because this code is only used for subresource loads, this
2513 // will check the parent's principal
2514 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
2515
2516 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2517 !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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2518 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2519 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2520 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
2521 aTarget);
2522}
2523
2524/* static */
2525bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2526 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
2527 const char* aJustification, RFPTarget aTarget) {
2528 // With this check, we can ensure that the prefs and target say yes, so only
2529 // an exemption would cause us to return false.
2530 bool isPBM = aOriginAttributes.IsPrivateBrowsing();
2531 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2532 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)
2533 ("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)
2534 " 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)
2535 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)
;
2536 return false;
2537 }
2538
2539 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)
2540 ("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)
2541 " 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)
2542 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)
;
2543
2544 if (!StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2545 !StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly()) {
2546 // If neither of the 'regular' RFP prefs are set, then one (or both)
2547 // of the PBM-Only prefs are set (or we would have failed the
2548 // Positive return check.) Therefore, if we are not in PBM, return false
2549 if (!aOriginAttributes.IsPrivateBrowsing()) {
2550 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) OA PBM Check said false"
); } } while (0)
2551 ("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) OA PBM Check said false"
); } } while (0)
2552 " OriginAttributes) OA PBM Check 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_dangerous(nsIURI*," " OriginAttributes) OA PBM Check said false"
); } } while (0)
;
2553 return false;
2554 }
2555 }
2556
2557 // Exclude internal schemes and web extensions
2558 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
2559 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)
2560 ("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)
2561 " 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)
;
2562 return false;
2563 }
2564
2565 bool isExemptDomain = false;
2566 nsAutoCString list;
2567 Preferences::GetCString(kExemptedDomainsPrefName, list);
2568 ToLowerCase(list);
2569 isExemptDomain = IsURIInList(aURI, list);
2570
2571 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2572 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2573 nsAutoCString url;
2574 aURI->GetHost(url);
2575 LogDomainAndPrefList("URI", kExemptedDomainsPrefName, url, isExemptDomain);
2576 }
2577
2578 if (isExemptDomain) {
2579 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
2580 }
2581
2582 return !isExemptDomain;
2583}
2584
2585/* static */
2586bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2587 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
2588 if (!aPrincipal) {
2589 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)
2590 ("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)
2591 "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)
;
2592 return ShouldResistFingerprinting("Null object", aTarget);
2593 }
2594
2595 auto originAttributes =
2596 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
2597 // With this check, we can ensure that the prefs and target say yes, so only
2598 // an exemption would cause us to return false.
2599 bool isPBM = originAttributes.IsPrivateBrowsing();
2600 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2601 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)
2602 ("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)
2603 "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)
2604 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)
;
2605 return false;
2606 }
2607
2608 if (aPrincipal->IsSystemPrincipal()) {
2609 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)
2610 ("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)
2611 "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)
;
2612 return false;
2613 }
2614
2615 // Exclude internal schemes and web extensions
2616 if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) {
2617 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)
2618 ("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)
2619 " 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)
;
2620 return false;
2621 }
2622
2623 // Web extension principals are also excluded
2624 if (BasePrincipal::Cast(aPrincipal)->AddonPolicy()) {
2625 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)
2626 ("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)
2627 " 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)
;
2628 return false;
2629 }
2630
2631 bool isExemptDomain = false;
2632 aPrincipal->IsURIInPrefList(kExemptedDomainsPrefName, &isExemptDomain);
2633
2634 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2635 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2636 nsAutoCString origin;
2637 aPrincipal->GetOrigin(origin);
2638 LogDomainAndPrefList("URI", kExemptedDomainsPrefName, origin,
2639 isExemptDomain);
2640 }
2641
2642 if (isExemptDomain) {
2643 isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes);
2644 }
2645
2646 return !isExemptDomain;
2647}
2648
2649// --------------------------------------------------------------------
2650
2651/* static */
2652void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
2653 int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
2654 int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
2655 bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
2656 int32_t* aOutputHeight) {
2657 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth"
")"); do { *((volatile int*)__null) = 2657; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2658 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",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputHeight"
")"); do { *((volatile int*)__null) = 2658; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2659
2660 int32_t availContentWidth = 0;
2661 int32_t availContentHeight = 0;
2662
2663 availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(),
2664 aScreenWidth - aChromeWidth);
2665#ifdef MOZ_WIDGET_GTK1
2666 // In the GTK window, it will not report outside system decorations
2667 // when we get available window size, see Bug 581863. So, we leave a
2668 // 40 pixels space for them when calculating the available content
2669 // height. It is not necessary for the width since the content width
2670 // is usually pretty much the same as the chrome width.
2671 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
2672 (-40 + aScreenHeight) - aChromeHeight);
2673#else
2674 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
2675 aScreenHeight - aChromeHeight);
2676#endif
2677
2678 // Ideally, we'd like to round window size to 1000x1000, but the
2679 // screen space could be too small to accommodate this size in some
2680 // cases. If it happens, we would round the window size to the nearest
2681 // 200x100.
2682 availContentWidth = availContentWidth - (availContentWidth % 200);
2683 availContentHeight = availContentHeight - (availContentHeight % 100);
2684
2685 // If aIsOuter is true, we are setting the outer window. So we
2686 // have to consider the chrome UI.
2687 int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
2688 int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
2689 int32_t resultWidth = 0, resultHeight = 0;
2690
2691 // if the original size is greater than the maximum available size, we set
2692 // it to the maximum size. And if the original value is less than the
2693 // minimum rounded size, we set it to the minimum 200x100.
2694 if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
2695 resultWidth = availContentWidth + chromeOffsetWidth;
2696 } else if (aInputWidth < (200 + chromeOffsetWidth)) {
2697 resultWidth = 200 + chromeOffsetWidth;
2698 } else {
2699 // Otherwise, we round the window to the nearest upper rounded 200x100.
2700 resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 +
2701 chromeOffsetWidth;
2702 }
2703
2704 if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
2705 resultHeight = availContentHeight + chromeOffsetHeight;
2706 } else if (aInputHeight < (100 + chromeOffsetHeight)) {
2707 resultHeight = 100 + chromeOffsetHeight;
2708 } else {
2709 resultHeight =
2710 NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 +
2711 chromeOffsetHeight;
2712 }
2713
2714 *aOutputWidth = resultWidth;
2715 *aOutputHeight = resultHeight;
2716}
2717
2718bool nsContentUtils::ThreadsafeIsCallerChrome() {
2719 return NS_IsMainThread() ? IsCallerChrome()
2720 : IsCurrentThreadRunningChromeWorker();
2721}
2722
2723bool nsContentUtils::IsCallerUAWidget() {
2724 JSContext* cx = GetCurrentJSContext();
2725 if (!cx) {
2726 return false;
2727 }
2728
2729 JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
2730 if (!realm) {
2731 return false;
2732 }
2733
2734 return xpc::IsUAWidgetScope(realm);
2735}
2736
2737bool nsContentUtils::IsSystemCaller(JSContext* aCx) {
2738 // Note that SubjectPrincipal() assumes we are in a compartment here.
2739 return SubjectPrincipal(aCx) == sSystemPrincipal;
2740}
2741
2742bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
2743 CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
2744 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ccjscx->Context() == aCx"
")"); do { *((volatile int*)__null) = 2744; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2745
2746 return ccjscx->IsSystemCaller();
2747}
2748
2749// static
2750bool nsContentUtils::LookupBindingMember(
2751 JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
2752 JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
2753 return true;
2754}
2755
2756nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode(
2757 nsINode* aChild) {
2758 if (aChild->IsDocument()) {
2759 for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc;
2760 bc = bc->GetParent()) {
2761 if (bc->GetEmbedderElement()) {
2762 return bc->GetEmbedderElement();
2763 }
2764 }
2765 return nullptr;
2766 }
2767
2768 nsINode* parent = aChild->GetParentNode();
2769 if (parent && parent->IsContent() && aChild->IsContent()) {
2770 parent = aChild->AsContent()->GetFlattenedTreeParent();
2771 }
2772
2773 return parent;
2774}
2775
2776bool nsContentUtils::ContentIsHostIncludingDescendantOf(
2777 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2778 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2778; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2779 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2779); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2779; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2780
2781 do {
2782 if (aPossibleDescendant == aPossibleAncestor) return true;
2783 if (aPossibleDescendant->IsDocumentFragment()) {
2784 aPossibleDescendant =
2785 aPossibleDescendant->AsDocumentFragment()->GetHost();
2786 } else {
2787 aPossibleDescendant = aPossibleDescendant->GetParentNode();
2788 }
2789 } while (aPossibleDescendant);
2790
2791 return false;
2792}
2793
2794// static
2795bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
2796 nsINode* aPossibleAncestor) {
2797 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2797; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2798 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2798; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2799
2800 do {
2801 if (aPossibleDescendant == aPossibleAncestor) {
2802 return true;
2803 }
2804
2805 aPossibleDescendant =
2806 GetNearestInProcessCrossDocParentNode(aPossibleDescendant);
2807 } while (aPossibleDescendant);
2808
2809 return false;
2810}
2811
2812// static
2813bool nsContentUtils::ContentIsFlattenedTreeDescendantOf(
2814 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2815 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2815; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2816 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2816; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2817
2818 do {
2819 if (aPossibleDescendant == aPossibleAncestor) {
2820 return true;
2821 }
2822 aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
2823 } while (aPossibleDescendant);
2824
2825 return false;
2826}
2827
2828// static
2829bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(
2830 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2831 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2831; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2832 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2832; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2833
2834 do {
2835 if (aPossibleDescendant == aPossibleAncestor) {
2836 return true;
2837 }
2838 aPossibleDescendant =
2839 aPossibleDescendant->GetFlattenedTreeParentNodeForStyle();
2840 } while (aPossibleDescendant);
2841
2842 return false;
2843}
2844
2845// static
2846nsINode* nsContentUtils::Retarget(nsINode* aTargetA, nsINode* aTargetB) {
2847 while (true && aTargetA) {
2848 // If A's root is not a shadow root...
2849 nsINode* root = aTargetA->SubtreeRoot();
2850 if (!root->IsShadowRoot()) {
2851 // ...then return A.
2852 return aTargetA;
2853 }
2854
2855 // or A's root is a shadow-including inclusive ancestor of B...
2856 if (aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
2857 // ...then return A.
2858 return aTargetA;
2859 }
2860
2861 aTargetA = ShadowRoot::FromNode(root)->GetHost();
2862 }
2863
2864 return nullptr;
2865}
2866
2867// static
2868Element* nsContentUtils::GetAnElementForTiming(Element* aTarget,
2869 const Document* aDocument,
2870 nsIGlobalObject* aGlobal) {
2871 if (!aTarget->IsInComposedDoc()) {
2872 return nullptr;
2873 }
2874
2875 if (!aDocument) {
2876 nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal);
2877 if (!inner) {
2878 return nullptr;
2879 }
2880 aDocument = inner->GetExtantDoc();
2881 }
2882
2883 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 2883; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2884
2885 if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument ||
2886 !aDocument->IsCurrentActiveDocument()) {
2887 return nullptr;
2888 }
2889
2890 return aTarget;
2891}
2892
2893// static
2894nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode,
2895 nsTArray<nsINode*>& aArray) {
2896 while (aNode) {
2897 aArray.AppendElement(aNode);
2898 aNode = aNode->GetParentNode();
2899 }
2900 return NS_OK;
2901}
2902
2903// static
2904template <typename GetParentFunc>
2905nsresult static GetInclusiveAncestorsAndOffsetsHelper(
2906 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2907 nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc) {
2908 NS_ENSURE_ARG_POINTER(aNode)do { if ((__builtin_expect(!!(!(aNode)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNode" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2908); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2909
2910 if (!aNode->IsContent()) {
2911 return NS_ERROR_FAILURE;
2912 }
2913 nsIContent* content = aNode->AsContent();
2914
2915 if (!aAncestorNodes.IsEmpty()) {
2916 NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2916)
;
2917 aAncestorNodes.Clear();
2918 }
2919
2920 if (!aAncestorOffsets.IsEmpty()) {
2921 NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2921)
;
2922 aAncestorOffsets.Clear();
2923 }
2924
2925 // insert the node itself
2926 aAncestorNodes.AppendElement(content);
2927 aAncestorOffsets.AppendElement(Some(aOffset));
2928
2929 // insert all the ancestors
2930 nsIContent* child = content;
2931 nsIContent* parent = aGetParentFunc(child);
2932 while (parent) {
2933 aAncestorNodes.AppendElement(parent->AsContent());
2934 aAncestorOffsets.AppendElement(parent->ComputeIndexOf(child));
2935 child = parent;
2936 parent = aGetParentFunc(child);
2937 }
2938
2939 return NS_OK;
2940}
2941
2942nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
2943 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2944 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
2945 return GetInclusiveAncestorsAndOffsetsHelper(
2946 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
2947 [](nsIContent* aContent) { return aContent->GetParent(); });
2948}
2949
2950nsresult nsContentUtils::GetShadowIncludingAncestorsAndOffsets(
2951 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2952 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
2953 return GetInclusiveAncestorsAndOffsetsHelper(
2954 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
2955 [](nsIContent* aContent) -> nsIContent* {
2956 return nsIContent::FromNodeOrNull(
2957 aContent->GetParentOrShadowHostNode());
2958 });
2959}
2960
2961template <typename Node, typename GetParentFunc>
2962static Node* GetCommonAncestorInternal(Node* aNode1, Node* aNode2,
2963 GetParentFunc aGetParentFunc) {
2964 MOZ_ASSERT(aNode1 != aNode2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode1 != aNode2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNode1 != aNode2))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aNode1 != aNode2"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 2964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1 != aNode2"
")"); do { *((volatile int*)__null) = 2964; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2965
2966 // Build the chain of parents
2967 AutoTArray<Node*, 30> parents1, parents2;
2968 do {
2969 parents1.AppendElement(aNode1);
2970 aNode1 = aGetParentFunc(aNode1);
2971 } while (aNode1);
2972 do {
2973 parents2.AppendElement(aNode2);
2974 aNode2 = aGetParentFunc(aNode2);
2975 } while (aNode2);
2976
2977 // Find where the parent chain differs
2978 uint32_t pos1 = parents1.Length();
2979 uint32_t pos2 = parents2.Length();
2980 Node** data1 = parents1.Elements();
2981 Node** data2 = parents2.Elements();
2982 Node* parent = nullptr;
2983 uint32_t len;
2984 for (len = std::min(pos1, pos2); len > 0; --len) {
2985 Node* child1 = data1[--pos1];
2986 Node* child2 = data2[--pos2];
2987 if (child1 != child2) {
2988 break;
2989 }
2990 parent = child1;
2991 }
2992
2993 return parent;
2994}
2995
2996/* static */
2997nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
2998 nsINode* aNode2) {
2999 return GetCommonAncestorInternal(
3000 aNode1, aNode2, [](nsINode* aNode) { return aNode->GetParentNode(); });
3001}
3002
3003/* static */
3004nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3005 nsINode* aNode1, nsINode* aNode2) {
3006 if (aNode1 == aNode2) {
3007 return aNode1;
3008 }
3009
3010 return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
3011 return aNode->GetParentOrShadowHostNode();
3012 });
3013}
3014
3015/* static */
3016nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3017 nsIContent* aContent1, nsIContent* aContent2) {
3018 return GetCommonAncestorInternal(
3019 aContent1, aContent2,
3020 [](nsIContent* aContent) { return aContent->GetFlattenedTreeParent(); });
3021}
3022
3023/* static */
3024nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3025 nsIContent* aContent1, nsIContent* aContent2) {
3026 if (aContent1 == aContent2) {
3027 return aContent1;
3028 }
3029
3030 return GetCommonAncestorInternal(
3031 aContent1, aContent2, [](nsIContent* aContent) {
3032 return aContent->GetFlattenedTreeParentNodeForSelection();
3033 });
3034}
3035
3036/* static */
3037Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3038 Element* aElement1, Element* aElement2) {
3039 return GetCommonAncestorInternal(aElement1, aElement2, [](Element* aElement) {
3040 return aElement->GetFlattenedTreeParentElementForStyle();
3041 });
3042}
3043
3044/* static */
3045bool nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
3046 Maybe<uint32_t>* aNode1Index,
3047 Maybe<uint32_t>* aNode2Index) {
3048 // Note, CompareDocumentPosition takes the latter params in different order.
3049 return (aNode2->CompareDocumentPosition(*aNode1, aNode2Index, aNode1Index) &
3050 (Node_Binding::DOCUMENT_POSITION_PRECEDING |
3051 Node_Binding::DOCUMENT_POSITION_DISCONNECTED)) ==
3052 Node_Binding::DOCUMENT_POSITION_PRECEDING;
3053}
3054
3055/* static */
3056Maybe<int32_t> nsContentUtils::ComparePoints(const nsINode* aParent1,
3057 uint32_t aOffset1,
3058 const nsINode* aParent2,
3059 uint32_t aOffset2,
3060 NodeIndexCache* aIndexCache) {
3061 bool disconnected{false};
3062
3063 const int32_t order = ComparePoints_Deprecated(
3064 aParent1, aOffset1, aParent2, aOffset2, &disconnected, aIndexCache);
3065 if (disconnected) {
3066 return Nothing();
3067 }
3068
3069 return Some(order);
3070}
3071
3072/* static */
3073int32_t nsContentUtils::ComparePoints_Deprecated(
3074 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
3075 uint32_t aOffset2, bool* aDisconnected, NodeIndexCache* aIndexCache) {
3076 if (aParent1 == aParent2) {
3077 return aOffset1 < aOffset2 ? -1 : aOffset1 > aOffset2 ? 1 : 0;
3078 }
3079
3080 AutoTArray<const nsINode*, 32> parents1, parents2;
3081 const nsINode* node1 = aParent1;
3082 const nsINode* node2 = aParent2;
3083 do {
3084 parents1.AppendElement(node1);
3085 node1 = node1->GetParentOrShadowHostNode();
3086 } while (node1);
3087 do {
3088 parents2.AppendElement(node2);
3089 node2 = node2->GetParentOrShadowHostNode();
3090 } while (node2);
3091
3092 uint32_t pos1 = parents1.Length() - 1;
3093 uint32_t pos2 = parents2.Length() - 1;
3094
3095 bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
3096 if (aDisconnected) {
3097 *aDisconnected = disconnected;
3098 }
3099 if (disconnected) {
3100 NS_ASSERTION(aDisconnected, "unexpected disconnected nodes")do { if (!(aDisconnected)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "unexpected disconnected nodes", "aDisconnected", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3100); MOZ_PretendNoReturn(); } } while (0)
;
3101 return 1;
3102 }
3103
3104 // Find where the parent chains differ
3105 const nsINode* parent = parents1.ElementAt(pos1);
3106 uint32_t len;
3107 for (len = std::min(pos1, pos2); len > 0; --len) {
3108 const nsINode* child1 = parents1.ElementAt(--pos1);
3109 const nsINode* child2 = parents2.ElementAt(--pos2);
3110 if (child1 != child2) {
3111 if (MOZ_UNLIKELY(child1->IsShadowRoot())(__builtin_expect(!!(child1->IsShadowRoot()), 0))) {
3112 // Shadow roots come before light DOM per
3113 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3114 MOZ_ASSERT(!child2->IsShadowRoot(), "Two shadow roots?")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()"
" (" "Two shadow roots?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { *((volatile int*)__null
) = 3114; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3115 return -1;
3116 }
3117 if (MOZ_UNLIKELY(child2->IsShadowRoot())(__builtin_expect(!!(child2->IsShadowRoot()), 0))) {
3118 return 1;
3119 }
3120 Maybe<uint32_t> child1Index;
3121 Maybe<uint32_t> child2Index;
3122 if (aIndexCache) {
3123 aIndexCache->ComputeIndicesOf(parent, child1, child2, child1Index,
3124 child2Index);
3125 } else {
3126 child1Index = parent->ComputeIndexOf(child1);
3127 child2Index = parent->ComputeIndexOf(child2);
3128 }
3129 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3130 return *child1Index < *child2Index ? -1 : 1;
3131 }
3132 // XXX Keep the odd traditional behavior for now.
3133 return child1Index.isNothing() && child2Index.isSome() ? -1 : 1;
3134 }
3135 parent = child1;
3136 }
3137
3138 // The parent chains never differed, so one of the nodes is an ancestor of
3139 // the other
3140
3141 NS_ASSERTION(!pos1 || !pos2,do { if (!(!pos1 || !pos2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "should have run out of parent chain for one of the nodes",
"!pos1 || !pos2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3142); MOZ_PretendNoReturn(); } } while (0)
3142 "should have run out of parent chain for one of the nodes")do { if (!(!pos1 || !pos2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "should have run out of parent chain for one of the nodes",
"!pos1 || !pos2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3142); MOZ_PretendNoReturn(); } } while (0)
;
3143
3144 if (!pos1) {
3145 const nsINode* child2 = parents2.ElementAt(--pos2);
3146 const Maybe<uint32_t> child2Index =
3147 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child2)
3148 : parent->ComputeIndexOf(child2);
3149 if (MOZ_UNLIKELY(NS_WARN_IF(child2Index.isNothing()))(__builtin_expect(!!(NS_warn_if_impl(child2Index.isNothing(),
"child2Index.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3149)), 0))
) {
3150 return 1;
3151 }
3152 return aOffset1 <= *child2Index ? -1 : 1;
3153 }
3154
3155 const nsINode* child1 = parents1.ElementAt(--pos1);
3156 const Maybe<uint32_t> child1Index =
3157 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child1)
3158 : parent->ComputeIndexOf(child1);
3159 if (MOZ_UNLIKELY(NS_WARN_IF(child1Index.isNothing()))(__builtin_expect(!!(NS_warn_if_impl(child1Index.isNothing(),
"child1Index.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3159)), 0))
) {
3160 return -1;
3161 }
3162 return *child1Index < aOffset2 ? -1 : 1;
3163}
3164
3165/* static */
3166BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
3167 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
3168 return GetCommonAncestorInternal(
3169 aBrowserParent1, aBrowserParent2, [](BrowserParent* aBrowserParent) {
3170 return aBrowserParent->GetBrowserBridgeParent()
3171 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
3172 : nullptr;
3173 });
3174}
3175
3176/* static */
3177Element* nsContentUtils::GetTargetElement(Document* aDocument,
3178 const nsAString& aAnchorName) {
3179 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 3179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3180
3181 if (aAnchorName.IsEmpty()) {
3182 return nullptr;
3183 }
3184 // 1. If there is an element in the document tree that has an ID equal to
3185 // fragment, then return the first such element in tree order.
3186 if (Element* el = aDocument->GetElementById(aAnchorName)) {
3187 return el;
3188 }
3189
3190 // 2. If there is an a element in the document tree that has a name
3191 // attribute whose value is equal to fragment, then return the first such
3192 // element in tree order.
3193 //
3194 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
3195 if (aDocument->IsHTMLDocument()) {
3196 nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName);
3197 // Loop through the named nodes looking for the first anchor
3198 uint32_t length = list->Length();
3199 for (uint32_t i = 0; i < length; i++) {
3200 nsIContent* node = list->Item(i);
3201 if (node->IsHTMLElement(nsGkAtoms::a)) {
3202 return node->AsElement();
3203 }
3204 }
3205 } else {
3206 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
3207 // Get the list of anchor elements
3208 nsCOMPtr<nsINodeList> list =
3209 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
3210 // Loop through the anchors looking for the first one with the given name.
3211 for (uint32_t i = 0; true; i++) {
3212 nsIContent* node = list->Item(i);
3213 if (!node) { // End of list
3214 break;
3215 }
3216
3217 // Compare the name attribute
3218 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
3219 aAnchorName, eCaseMatters)) {
3220 return node->AsElement();
3221 }
3222 }
3223 }
3224
3225 // 3. Return null.
3226 return nullptr;
3227}
3228
3229/* static */
3230template <typename FPT, typename FRT, typename SPT, typename SRT>
3231Maybe<int32_t> nsContentUtils::ComparePoints(
3232 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3233 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary) {
3234 if (!aFirstBoundary.IsSet() || !aSecondBoundary.IsSet()) {
3235 return Nothing{};
3236 }
3237
3238 bool disconnected{false};
3239 const int32_t order =
3240 ComparePoints_Deprecated(aFirstBoundary, aSecondBoundary, &disconnected);
3241
3242 if (disconnected) {
3243 return Nothing{};
3244 }
3245
3246 return Some(order);
3247}
3248
3249/* static */
3250template <typename FPT, typename FRT, typename SPT, typename SRT>
3251int32_t nsContentUtils::ComparePoints_Deprecated(
3252 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3253 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary, bool* aDisconnected) {
3254 if (NS_WARN_IF(!aFirstBoundary.IsSet())NS_warn_if_impl(!aFirstBoundary.IsSet(), "!aFirstBoundary.IsSet()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3254)
||
3255 NS_WARN_IF(!aSecondBoundary.IsSet())NS_warn_if_impl(!aSecondBoundary.IsSet(), "!aSecondBoundary.IsSet()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3255)
) {
3256 return -1;
3257 }
3258 // XXX Re-implement this without calling `Offset()` as far as possible,
3259 // and the other overload should be an alias of this.
3260 return ComparePoints_Deprecated(
3261 aFirstBoundary.Container(),
3262 *aFirstBoundary.Offset(
3263 RangeBoundaryBase<FPT, FRT>::OffsetFilter::kValidOrInvalidOffsets),
3264 aSecondBoundary.Container(),
3265 *aSecondBoundary.Offset(
3266 RangeBoundaryBase<SPT, SRT>::OffsetFilter::kValidOrInvalidOffsets),
3267 aDisconnected);
3268}
3269
3270inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
3271 char16_t ch;
3272 while ((ch = *aSet)) {
3273 if (aChar == char16_t(ch)) {
3274 return true;
3275 }
3276 ++aSet;
3277 }
3278 return false;
3279}
3280
3281/**
3282 * This method strips leading/trailing chars, in given set, from string.
3283 */
3284
3285// static
3286const nsDependentSubstring nsContentUtils::TrimCharsInSet(
3287 const char* aSet, const nsAString& aValue) {
3288 nsAString::const_iterator valueCurrent, valueEnd;
3289
3290 aValue.BeginReading(valueCurrent);
3291 aValue.EndReading(valueEnd);
3292
3293 // Skip characters in the beginning
3294 while (valueCurrent != valueEnd) {
3295 if (!IsCharInSet(aSet, *valueCurrent)) {
3296 break;
3297 }
3298 ++valueCurrent;
3299 }
3300
3301 if (valueCurrent != valueEnd) {
3302 for (;;) {
3303 --valueEnd;
3304 if (!IsCharInSet(aSet, *valueEnd)) {
3305 break;
3306 }
3307 }
3308 ++valueEnd; // Step beyond the last character we want in the value.
3309 }
3310
3311 // valueEnd should point to the char after the last to copy
3312 return Substring(valueCurrent, valueEnd);
3313}
3314
3315/**
3316 * This method strips leading and trailing whitespace from a string.
3317 */
3318
3319// static
3320template <bool IsWhitespace(char16_t)>
3321const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
3322 bool aTrimTrailing) {
3323 nsAString::const_iterator start, end;
3324
3325 aStr.BeginReading(start);
3326 aStr.EndReading(end);
3327
3328 // Skip whitespace characters in the beginning
3329 while (start != end && IsWhitespace(*start)) {
3330 ++start;
3331 }
3332
3333 if (aTrimTrailing) {
3334 // Skip whitespace characters in the end.
3335 while (end != start) {
3336 --end;
3337
3338 if (!IsWhitespace(*end)) {
3339 // Step back to the last non-whitespace character.
3340 ++end;
3341
3342 break;
3343 }
3344 }
3345 }
3346
3347 // Return a substring for the string w/o leading and/or trailing
3348 // whitespace
3349
3350 return Substring(start, end);
3351}
3352
3353// Declaring the templates we are going to use avoid linking issues without
3354// inlining the method. Considering there is not so much spaces checking
3355// methods we can consider this to be better than inlining.
3356template const nsDependentSubstring
3357nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
3358template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3359 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
3360template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3361 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
3362
3363static inline void KeyAppendSep(nsACString& aKey) {
3364 if (!aKey.IsEmpty()) {
3365 aKey.Append('>');
3366 }
3367}
3368
3369static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
3370 KeyAppendSep(aKey);
3371
3372 // Could escape separator here if collisions happen. > is not a legal char
3373 // for a name or type attribute, so we should be safe avoiding that extra
3374 // work.
3375
3376 AppendUTF16toUTF8(aString, aKey);
3377}
3378
3379static inline void KeyAppendString(const nsACString& aString,
3380 nsACString& aKey) {
3381 KeyAppendSep(aKey);
3382
3383 // Could escape separator here if collisions happen. > is not a legal char
3384 // for a name or type attribute, so we should be safe avoiding that extra
3385 // work.
3386
3387 aKey.Append(aString);
3388}
3389
3390static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
3391 KeyAppendSep(aKey);
3392
3393 aKey.AppendInt(aInt);
3394}
3395
3396static inline bool IsAutocompleteOff(const nsIContent* aContent) {
3397 return aContent->IsElement() &&
3398 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
3399 nsGkAtoms::autocomplete, u"off"_ns,
3400 eIgnoreCase);
3401}
3402
3403/*static*/
3404void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
3405 nsACString& aKey) {
3406 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 3406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3407
3408 aKey.Truncate();
3409
3410 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
3411
3412 // Don't capture state for anonymous content
3413 if (aContent->IsInNativeAnonymousSubtree()) {
3414 return;
3415 }
3416
3417 if (IsAutocompleteOff(aContent)) {
3418 return;
3419 }
3420
3421 RefPtr<Document> doc = aContent->GetUncomposedDoc();
3422
3423 KeyAppendInt(partID, aKey); // first append a partID
3424 bool generatedUniqueKey = false;
3425
3426 if (doc && doc->IsHTMLOrXHTML()) {
3427 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
3428
3429 // If we have a form control and can calculate form information, use that
3430 // as the key - it is more reliable than just recording position in the
3431 // DOM.
3432 // XXXbz Is it, really? We have bugs on this, I think...
3433 // Important to have a unique key, and tag/type/name may not be.
3434 //
3435 // The format of the key depends on whether the control has a form,
3436 // and whether the element was parser inserted:
3437 //
3438 // [Has Form, Parser Inserted]:
3439 // fp>type>FormNum>IndOfControlInForm>FormName>name
3440 //
3441 // [No Form, Parser Inserted]:
3442 // dp>type>ControlNum>name
3443 //
3444 // [Has Form, Not Parser Inserted]:
3445 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
3446 //
3447 // [No Form, Not Parser Inserted]:
3448 // dn>type>IndOfControlInDoc>name
3449 //
3450 // XXX We don't need to use index if name is there
3451 // XXXbz We don't? Why not? I don't follow.
3452 //
3453 if (const auto* control = nsIFormControl::FromNode(aContent)) {
3454 // Get the control number if this was a parser inserted element from the
3455 // network.
3456 int32_t controlNumber =
3457 control->GetParserInsertedControlNumberForStateKey();
3458 bool parserInserted = controlNumber != -1;
3459
3460 RefPtr<nsContentList> htmlForms;
3461 RefPtr<nsContentList> htmlFormControls;
3462 if (!parserInserted) {
3463 // Getting these lists is expensive, as we need to keep them up to date
3464 // as the document loads, so we avoid it if we don't need them.
3465 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
3466 getter_AddRefs(htmlFormControls));
3467 }
3468
3469 // Append the control type
3470 KeyAppendInt(int32_t(control->ControlType()), aKey);
3471
3472 // If in a form, add form name / index of form / index in form
3473 HTMLFormElement* formElement = control->GetForm();
3474 if (formElement) {
3475 if (IsAutocompleteOff(formElement)) {
3476 aKey.Truncate();
3477 return;
3478 }
3479
3480 // Append the form number, if this is a parser inserted control, or
3481 // the index of the form in the document otherwise.
3482 bool appendedForm = false;
3483 if (parserInserted) {
3484 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3486); 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 { *((volatile int*)__null) = 3486; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3485 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3486); 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 { *((volatile int*)__null) = 3486; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3486 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3486); 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 { *((volatile int*)__null) = 3486; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3487 KeyAppendString("fp"_ns, aKey);
3488 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
3489 appendedForm = true;
3490 } else {
3491 KeyAppendString("fn"_ns, aKey);
3492 int32_t index = htmlForms->IndexOf(formElement, false);
3493 if (index <= -1) {
3494 //
3495 // XXX HACK this uses some state that was dumped into the document
3496 // specifically to fix bug 138892. What we are trying to do is
3497 // *guess* which form this control's state is found in, with the
3498 // highly likely guess that the highest form parsed so far is the
3499 // one. This code should not be on trunk, only branch.
3500 //
3501 index = htmlDoc->GetNumFormsSynchronous() - 1;
3502 }
3503 if (index > -1) {
3504 KeyAppendInt(index, aKey);
3505 appendedForm = true;
3506 }
3507 }
3508
3509 if (appendedForm) {
3510 // Append the index of the control in the form
3511 int32_t index = formElement->IndexOfContent(aContent);
3512
3513 if (index > -1) {
3514 KeyAppendInt(index, aKey);
3515 generatedUniqueKey = true;
3516 }
3517 }
3518
3519 // Append the form name
3520 nsAutoString formName;
3521 formElement->GetAttr(nsGkAtoms::name, formName);
3522 KeyAppendString(formName, aKey);
3523 } else {
3524 // Not in a form. Append the control number, if this is a parser
3525 // inserted control, or the index of the control in the document
3526 // otherwise.
3527 if (parserInserted) {
3528 KeyAppendString("dp"_ns, aKey);
3529 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
3530 aKey);
3531 generatedUniqueKey = true;
3532 } else {
3533 KeyAppendString("dn"_ns, aKey);
3534 int32_t index = htmlFormControls->IndexOf(aContent, true);
3535 if (index > -1) {
3536 KeyAppendInt(index, aKey);
3537 generatedUniqueKey = true;
3538 }
3539 }
3540
3541 // Append the control name
3542 nsAutoString name;
3543 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
3544 KeyAppendString(name, aKey);
3545 }
3546 }
3547 }
3548
3549 if (!generatedUniqueKey) {
3550 // Either we didn't have a form control or we aren't in an HTML document so
3551 // we can't figure out form info. Append the tag name if it's an element
3552 // to avoid restoring state for one type of element on another type.
3553 if (aContent->IsElement()) {
3554 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
3555 aKey);
3556 } else {
3557 // Append a character that is not "d" or "f" to disambiguate from
3558 // the case when we were a form control in an HTML document.
3559 KeyAppendString("o"_ns, aKey);
3560 }
3561
3562 // Now start at aContent and append the indices of it and all its ancestors
3563 // in their containers. That should at least pin down its position in the
3564 // DOM...
3565 nsINode* parent = aContent->GetParentNode();
3566 nsINode* content = aContent;
3567 while (parent) {
3568 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
3569 content = parent;
3570 parent = content->GetParentNode();
3571 }
3572 }
3573}
3574
3575// static
3576nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
3577 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3577; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3578
3579 // As opposed to SubjectPrincipal(), we do in fact assume that
3580 // we're in a realm here; anyone who calls this function in
3581 // situations where that's not the case is doing it wrong.
3582 JS::Realm* realm = js::GetContextRealm(aCx);
3583 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { *((volatile int*)__null) = 3583; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3584
3585 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3586 return nsJSPrincipals::get(principals);
3587}
3588
3589// static
3590nsIPrincipal* nsContentUtils::SubjectPrincipal() {
3591 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 3591; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3592 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3592; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3593 JSContext* cx = GetCurrentJSContext();
3594 if (!cx) {
3595 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3597); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3597; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3596 "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3597); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3597; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3597 "forbidden")do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3597); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3597; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
3598 }
3599
3600 JS::Realm* realm = js::GetContextRealm(cx);
3601
3602 // When an AutoJSAPI is instantiated, we are in a null realm until the
3603 // first JSAutoRealm, which is kind of a purgatory as far as permissions
3604 // go. It would be nice to just hard-abort if somebody does a security check
3605 // in this purgatory zone, but that would be too fragile, since it could be
3606 // triggered by random IsCallerChrome() checks 20-levels deep.
3607 //
3608 // So we want to return _something_ here - and definitely not the System
3609 // Principal, since that would make an AutoJSAPI a very dangerous thing to
3610 // instantiate.
3611 //
3612 // The natural thing to return is a null principal. Ideally, we'd return a
3613 // different null principal each time, to avoid any unexpected interactions
3614 // when the principal accidentally gets inherited somewhere. But
3615 // SubjectPrincipal doesn't return strong references, so there's no way to
3616 // sanely manage the lifetime of multiple null principals.
3617 //
3618 // So we use a singleton null principal. To avoid it being accidentally
3619 // inherited and becoming a "real" subject or object principal, we do a
3620 // release-mode assert during realm creation against using this principal on
3621 // an actual global.
3622 if (!realm) {
3623 return sNullSubjectPrincipal;
3624 }
3625
3626 return SubjectPrincipal(cx);
3627}
3628
3629// static
3630nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
3631#ifdef DEBUG1
3632 JS::AssertObjectBelongsToCurrentThread(aObj);
3633#endif
3634
3635 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3635); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { *((volatile int*)__null) = 3635; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3636
3637 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
3638 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3639 return nsJSPrincipals::get(principals);
3640}
3641
3642// static
3643nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
3644 const nsAString& aSpec,
3645 Document* aDocument,
3646 nsIURI* aBaseURI) {
3647 if (aDocument) {
3648 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
3649 aBaseURI);
3650 }
3651 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
3652}
3653
3654// static
3655bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
3656 const uint32_t len = aAtom->GetLength();
3657 if (!len) {
3658 return false;
3659 }
3660 const char16_t* name = aAtom->GetUTF16String();
3661 uint32_t i = 0;
3662 while (i < len) {
3663 if (name[i] == aChar) {
3664 return true;
3665 }
3666 i++;
3667 }
3668 return false;
3669}
3670
3671// static
3672bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
3673 // A valid custom element name is a sequence of characters name which
3674 // must match the PotentialCustomElementName production:
3675 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
3676 const char16_t* name = aName->GetUTF16String();
3677 uint32_t len = aName->GetLength();
3678 bool hasDash = false;
3679
3680 if (!len || name[0] < 'a' || name[0] > 'z') {
3681 return false;
3682 }
3683
3684 uint32_t i = 1;
3685 while (i < len) {
3686 if (i + 1 < len && NS_IS_SURROGATE_PAIR(name[i], name[i + 1])(((uint32_t(name[i]) & 0xFFFFFC00) == 0xD800) && (
(uint32_t(name[i + 1]) & 0xFFFFFC00) == 0xDC00))
) {
3687 // Merged two 16-bit surrogate pairs into code point.
3688 char32_t code = SURROGATE_TO_UCS4(name[i], name[i + 1])(((uint32_t(name[i]) & 0x03FF) << 10) + (uint32_t(name
[i + 1]) & 0x03FF) + uint32_t(0x00010000))
;
3689
3690 if (code < 0x10000 || code > 0xEFFFF) {
3691 return false;
3692 }
3693
3694 i += 2;
3695 } else {
3696 if (name[i] == '-') {
3697 hasDash = true;
3698 }
3699
3700 if (name[i] != '-' && name[i] != '.' && name[i] != '_' &&
3701 name[i] != 0xB7 && (name[i] < '0' || name[i] > '9') &&
3702 (name[i] < 'a' || name[i] > 'z') &&
3703 (name[i] < 0xC0 || name[i] > 0xD6) &&
3704 (name[i] < 0xF8 || name[i] > 0x37D) &&
3705 (name[i] < 0x37F || name[i] > 0x1FFF) &&
3706 (name[i] < 0x200C || name[i] > 0x200D) &&
3707 (name[i] < 0x203F || name[i] > 0x2040) &&
3708 (name[i] < 0x2070 || name[i] > 0x218F) &&
3709 (name[i] < 0x2C00 || name[i] > 0x2FEF) &&
3710 (name[i] < 0x3001 || name[i] > 0xD7FF) &&
3711 (name[i] < 0xF900 || name[i] > 0xFDCF) &&
3712 (name[i] < 0xFDF0 || name[i] > 0xFFFD)) {
3713 return false;
3714 }
3715
3716 i++;
3717 }
3718 }
3719
3720 return hasDash;
3721}
3722
3723// static
3724bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
3725 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
3726 if (aNameSpaceID == kNameSpaceID_XUL8) {
3727 return true;
3728 }
3729
3730 bool hasDash = IsNameWithDash(aName);
3731 if (!hasDash) {
3732 return false;
3733 }
3734
3735 // The custom element name must not be one of the following values:
3736 // annotation-xml
3737 // color-profile
3738 // font-face
3739 // font-face-src
3740 // font-face-uri
3741 // font-face-format
3742 // font-face-name
3743 // missing-glyph
3744 return aName != nsGkAtoms::annotation_xml_ &&
3745 aName != nsGkAtoms::colorProfile && aName != nsGkAtoms::font_face &&
3746 aName != nsGkAtoms::font_face_src &&
3747 aName != nsGkAtoms::font_face_uri &&
3748 aName != nsGkAtoms::font_face_format &&
3749 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
3750}
3751
3752// static
3753nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
3754 bool aNamespaceAware,
3755 const char16_t** aColon) {
3756 const char* colon = nullptr;
3757 const char16_t* begin = aQualifiedName.BeginReading();
3758 const char16_t* end = aQualifiedName.EndReading();
3759
3760 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
3761 reinterpret_cast<const char*>(end),
3762 aNamespaceAware, &colon);
3763
3764 if (!result) {
3765 if (aColon) {
3766 *aColon = reinterpret_cast<const char16_t*>(colon);
3767 }
3768
3769 return NS_OK;
3770 }
3771
3772 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
3773}
3774
3775// static
3776nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
3777 const nsString& aQName, int32_t* aNamespace,
3778 nsAtom** aLocalName) {
3779 const char16_t* colon;
3780 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
3781 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3781); return rv; } } while (false)
;
3782
3783 if (colon) {
3784 const char16_t* end;
3785 aQName.EndReading(end);
3786 nsAutoString nameSpace;
3787 rv = aNamespaceResolver->LookupNamespaceURIInternal(
3788 Substring(aQName.get(), colon), nameSpace);
3789 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3789); return rv; } } while (false)
;
3790
3791 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
3792 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
3793 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
3794
3795 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
3796 } else {
3797 *aNamespace = kNameSpaceID_None;
3798 *aLocalName = NS_AtomizeMainThread(aQName).take();
3799 }
3800 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3800); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3801 return NS_OK;
3802}
3803
3804// static
3805nsresult nsContentUtils::GetNodeInfoFromQName(
3806 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
3807 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
3808 mozilla::dom::NodeInfo** aNodeInfo) {
3809 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
3810 const char16_t* colon;
3811 nsresult rv = nsContentUtils::CheckQName(qName, true, &colon);
3812 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3812); return rv; } } while (false)
;
3813
3814 int32_t nsID;
3815 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
3816 if (colon) {
3817 const char16_t* end;
3818 qName.EndReading(end);
3819
3820 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
3821
3822 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix, nsID,
3823 aNodeType, aNodeInfo);
3824 } else {
3825 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
3826 aNodeInfo);
3827 }
3828 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3828); return rv; } } while (false)
;
3829
3830 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
3831 (*aNodeInfo)->GetPrefixAtom(),
3832 (*aNodeInfo)->NamespaceID())
3833 ? NS_OK
3834 : NS_ERROR_DOM_NAMESPACE_ERR;
3835}
3836
3837// static
3838void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
3839 nsAtom** aPrefix, nsAtom** aLocalName,
3840 int32_t* aNameSpaceID) {
3841 /**
3842 * Expat can send the following:
3843 * localName
3844 * namespaceURI<separator>localName
3845 * namespaceURI<separator>localName<separator>prefix
3846 *
3847 * and we use 0xFFFF for the <separator>.
3848 *
3849 */
3850
3851 const char16_t* uriEnd = nullptr;
3852 const char16_t* nameEnd = nullptr;
3853 const char16_t* pos;
3854 for (pos = aExpatName; *pos; ++pos) {
3855 if (*pos == 0xFFFF) {
3856 if (uriEnd) {
3857 nameEnd = pos;
3858 } else {
3859 uriEnd = pos;
3860 }
3861 }
3862 }
3863
3864 const char16_t* nameStart;
3865 if (uriEnd) {
3866 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
3867 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
3868
3869 nameStart = (uriEnd + 1);
3870 if (nameEnd) {
3871 const char16_t* prefixStart = nameEnd + 1;
3872 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
3873 } else {
3874 nameEnd = pos;
3875 *aPrefix = nullptr;
3876 }
3877 } else {
3878 *aNameSpaceID = kNameSpaceID_None;
3879 nameStart = aExpatName;
3880 nameEnd = pos;
3881 *aPrefix = nullptr;
3882 }
3883 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
3884}
3885
3886// static
3887PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
3888 Document* doc = aContent->GetComposedDoc();
3889 if (!doc) {
3890 return nullptr;
3891 }
3892 return doc->GetPresShell();
3893}
3894
3895// static
3896nsPresContext* nsContentUtils::GetContextForContent(
3897 const nsIContent* aContent) {
3898 PresShell* presShell = GetPresShellForContent(aContent);
3899 if (!presShell) {
3900 return nullptr;
3901 }
3902 return presShell->GetPresContext();
3903}
3904
3905// static
3906bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
3907 if (!aLoadGroup) {
3908 return false;
3909 }
3910 // See duplicated code in Document::Reset/ResetToURI
3911 bool isPrivate = false;
3912 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3913 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3914 if (callbacks) {
3915 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
3916 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
3917 }
3918 return isPrivate;
3919}
3920
3921// FIXME(emilio): This is (effectively) almost but not quite the same as
3922// Document::ShouldLoadImages(), which one is right?
3923bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
3924 if (!aDocument) {
3925 return false;
3926 }
3927 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
3928 aDocument->IsStaticDocument()) {
3929 return false;
3930 }
3931 nsCOMPtr<nsPIDOMWindowInner> win =
3932 do_QueryInterface(aDocument->GetScopeObject());
3933 return !win || !win->GetDocShell();
3934}
3935
3936imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
3937 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3937); return nullptr; } } while (false)
;
3938
3939 if (!aDoc) {
3940 return imgLoader::NormalLoader();
3941 }
3942 const bool isPrivate = aDoc->IsInPrivateBrowsing();
3943 return isPrivate ? imgLoader::PrivateBrowsingLoader()
3944 : imgLoader::NormalLoader();
3945}
3946
3947// static
3948imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
3949 Document* aContext) {
3950 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
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3950); return nullptr; } } while (false)
;
3951
3952 if (!aChannel) {
3953 return imgLoader::NormalLoader();
3954 }
3955 return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader()
3956 : imgLoader::NormalLoader();
3957}
3958
3959// static
3960int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
3961 switch (aMode) {
3962 case CORS_ANONYMOUS:
3963 return imgILoader::LOAD_CORS_ANONYMOUS;
3964 case CORS_USE_CREDENTIALS:
3965 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
3966 default:
3967 return 0;
3968 }
3969}
3970
3971// static
3972nsresult nsContentUtils::LoadImage(
3973 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
3974 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
3975 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
3976 int32_t aLoadFlags, const nsAString& initiatorType,
3977 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
3978 bool aUseUrgentStartForChannel, bool aLinkPreload,
3979 uint64_t aEarlyHintPreloaderId,
3980 mozilla::dom::FetchPriority aFetchPriority) {
3981 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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI" ")"); do { *((volatile int*)__null) = 3981
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3982 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") ("
"Must have a context" ")"); do { *((volatile int*)__null) = 3982
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3983 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { *((volatile int*)__null
) = 3983; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3984 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { *((volatile int*)__null
) = 3984; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3985 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") ("
"Null out param" ")"); do { *((volatile int*)__null) = 3985;
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3986
3987 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
3988 if (!imgLoader) {
3989 // nothing we can do here
3990 return NS_ERROR_FAILURE;
3991 }
3992
3993 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
3994
3995 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
3996
3997 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3998); MOZ_PretendNoReturn(); } } while (0)
3998 "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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3998); MOZ_PretendNoReturn(); } } while (0)
;
3999
4000 // XXXbz using "documentURI" for the initialDocumentURI is not quite
4001 // right, but the best we can do here...
4002 return imgLoader->LoadImage(aURI, /* uri to load */
4003 documentURI, /* initialDocumentURI */
4004 aReferrerInfo, /* referrerInfo */
4005 aLoadingPrincipal, /* loading principal */
4006 aRequestContextID, /* request context ID */
4007 loadGroup, /* loadgroup */
4008 aObserver, /* imgINotificationObserver */
4009 aContext, /* loading context */
4010 aLoadingDocument, /* uniquification key */
4011 aLoadFlags, /* load flags */
4012 nullptr, /* cache key */
4013 aContentPolicyType, /* content policy type */
4014 initiatorType, /* the load initiator */
4015 aUseUrgentStartForChannel, /* urgent-start flag */
4016 aLinkPreload, /* <link preload> initiator */
4017 aEarlyHintPreloaderId, aFetchPriority, aRequest);
4018}
4019
4020// static
4021already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
4022 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
4023 if (aRequest) {
4024 *aRequest = nullptr;
4025 }
4026
4027 NS_ENSURE_TRUE(aContent, nullptr)do { if ((__builtin_expect(!!(!(aContent)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContent" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4027); return nullptr; } } while (false)
;
4028
4029 nsCOMPtr<imgIRequest> imgRequest;
4030 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4031 getter_AddRefs(imgRequest));
4032 if (!imgRequest) {
4033 return nullptr;
4034 }
4035
4036 nsCOMPtr<imgIContainer> imgContainer;
4037 imgRequest->GetImage(getter_AddRefs(imgContainer));
4038
4039 if (!imgContainer) {
4040 return nullptr;
4041 }
4042
4043 if (aRequest) {
4044 // If the consumer wants the request, verify it has actually loaded
4045 // successfully.
4046 uint32_t imgStatus;
4047 imgRequest->GetImageStatus(&imgStatus);
4048 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
4049 !(imgStatus & imgIRequest::STATUS_ERROR)) {
4050 imgRequest.swap(*aRequest);
4051 }
4052 }
4053
4054 return imgContainer.forget();
4055}
4056
4057static bool IsLinkWithURI(const nsIContent& aContent) {
4058 const auto* element = Element::FromNode(aContent);
4059 if (!element || !element->IsLink()) {
4060 return false;
4061 }
4062 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
4063 return !!absURI;
4064}
4065
4066static bool HasImageRequest(nsIContent& aContent) {
4067 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
4068 if (!imageContent) {
4069 return false;
4070 }
4071
4072 nsCOMPtr<imgIRequest> imgRequest;
4073 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4074 getter_AddRefs(imgRequest));
4075
4076 // XXXbz It may be draggable even if the request resulted in an error. Why?
4077 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
4078 return !!imgRequest;
4079}
4080
4081static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
4082 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
4083 if (el->Draggable()) {
4084 return Some(true);
4085 }
4086
4087 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
4088 nsGkAtoms::_false, eIgnoreCase)) {
4089 return Some(false);
4090 }
4091 }
4092 if (aContent.IsSVGElement()) {
4093 return Some(false);
4094 }
4095 return Nothing();
4096}
4097
4098// static
4099bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
4100 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4100; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4101
4102 if (auto draggable = DraggableOverride(*aContent)) {
4103 return *draggable;
4104 }
4105
4106 // special handling for content area image and link dragging
4107 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
4108}
4109
4110// static
4111bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
4112 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4112; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4113 return HasImageRequest(*aContent) &&
4114 DraggableOverride(*aContent).valueOr(true);
4115}
4116
4117// static
4118bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
4119 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4119; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4120 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
4121}
4122
4123// static
4124nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
4125 nsAtom* aName,
4126 mozilla::dom::NodeInfo** aResult) {
4127 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
4128
4129 *aResult = niMgr
4130 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
4131 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
4132 .take();
4133 return NS_OK;
4134}
4135
4136static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
4137 uint32_t aPerm, bool aExactHostMatch) {
4138 if (!aPrincipal) {
4139 // We always deny (i.e. don't allow) the permission if we don't have a
4140 // principal.
4141 return aPerm != nsIPermissionManager::ALLOW_ACTION;
4142 }
4143
4144 nsCOMPtr<nsIPermissionManager> permMgr =
4145 components::PermissionManager::Service();
4146 NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4146); return false; } } while (false)
;
4147
4148 uint32_t perm;
4149 nsresult rv;
4150 if (aExactHostMatch) {
4151 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
4152 } else {
4153 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4154 }
4155 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4155); return false; } } while (false)
;
4156
4157 return perm == aPerm;
4158}
4159
4160bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
4161 const nsACString& aType) {
4162 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4163 false);
4164}
4165
4166bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
4167 const nsACString& aType) {
4168 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4169 false);
4170}
4171
4172bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
4173 const nsACString& aType) {
4174 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4175 true);
4176}
4177
4178bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
4179 const nsACString& aType) {
4180 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4181 true);
4182}
4183
4184bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
4185 const nsACString& aType) {
4186 if (!aPrincipal) {
4187 return false;
4188 }
4189
4190 nsCOMPtr<nsIPermissionManager> permMgr =
4191 components::PermissionManager::Service();
4192 NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4192); return false; } } while (false)
;
4193
4194 uint32_t perm;
4195 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4196 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4196); return false; } } while (false)
;
4197
4198 return perm != nsIPermissionManager::UNKNOWN_ACTION;
4199}
4200
4201static const char* gEventNames[] = {"event"};
4202static const char* gSVGEventNames[] = {"evt"};
4203// for b/w compat, the first name to onerror is still 'event', even though it
4204// is actually the error message
4205static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
4206 "error"};
4207
4208// static
4209void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
4210 bool aIsForWindow, uint32_t* aArgCount,
4211 const char*** aArgArray) {
4212#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
4213 *aArgCount = sizeof(names) / sizeof(names[0]); \
4214 *aArgArray = names;
4215
4216 // JSEventHandler is what does the arg magic for onerror, and it does
4217 // not seem to take the namespace into account. So we let onerror in all
4218 // namespaces get the 3 arg names.
4219 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
4220 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
4221 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
4222 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
4223 } else {
4224 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
4225 }
4226}
4227
4228// Note: The list of content bundles in nsStringBundle.cpp should be updated
4229// whenever entries are added or removed from this list.
4230static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = {
4231 // Must line up with the enum values in |PropertiesFile| enum.
4232 "chrome://global/locale/css.properties",
4233 "chrome://global/locale/xul.properties",
4234 "chrome://global/locale/layout_errors.properties",
4235 "chrome://global/locale/layout/HtmlForm.properties",
4236 "chrome://global/locale/printing.properties",
4237 "chrome://global/locale/dom/dom.properties",
4238 "chrome://global/locale/layout/htmlparser.properties",
4239 "chrome://global/locale/svg/svg.properties",
4240 "chrome://branding/locale/brand.properties",
4241 "chrome://global/locale/commonDialogs.properties",
4242 "chrome://global/locale/mathml/mathml.properties",
4243 "chrome://global/locale/security/security.properties",
4244 "chrome://necko/locale/necko.properties",
4245 "resource://gre/res/locale/layout/HtmlForm.properties",
4246 "resource://gre/res/locale/dom/dom.properties"};
4247
4248/* static */
4249nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
4250 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4251); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4251; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4251 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4251); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4251; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4252 if (!sStringBundles[aFile]) {
4253 if (!sStringBundleService) {
4254 nsresult rv =
4255 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
4256 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4256); return rv; } } while (false)
;
4257 }
4258 RefPtr<nsIStringBundle> bundle;
4259 MOZ_TRY(sStringBundleService->CreateBundle(gPropertiesFiles[aFile],do { auto mozTryTempResult_ = ::mozilla::ToResult(sStringBundleService
->CreateBundle(gPropertiesFiles[aFile], getter_AddRefs(bundle
))); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))
) { return mozTryTempResult_.propagateErr(); } } while (0)
4260 getter_AddRefs(bundle)))do { auto mozTryTempResult_ = ::mozilla::ToResult(sStringBundleService
->CreateBundle(gPropertiesFiles[aFile], getter_AddRefs(bundle
))); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))
) { return mozTryTempResult_.propagateErr(); } } while (0)
;
4261 sStringBundles[aFile] = bundle.forget();
4262 }
4263 return NS_OK;
4264}
4265
4266/* static */
4267void nsContentUtils::AsyncPrecreateStringBundles() {
4268 // We only ever want to pre-create bundles in the parent process.
4269 //
4270 // All nsContentUtils bundles are shared between the parent and child
4271 // precesses, and the shared memory regions that back them *must* be created
4272 // in the parent, and then sent to all children.
4273 //
4274 // If we attempt to create a bundle in the child before its memory region is
4275 // available, we need to create a temporary non-shared bundle, and later
4276 // replace that with the shared memory copy. So attempting to pre-load in the
4277 // child is wasteful and unnecessary.
4278 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4279
4280 for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT;
4281 ++bundleIndex) {
4282 nsresult rv = NS_DispatchToCurrentThreadQueue(
4283 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
4284 [bundleIndex]() {
4285 PropertiesFile file =
4286 static_cast<PropertiesFile>(bundleIndex);
4287 EnsureStringBundle(file);
4288 nsIStringBundle* bundle = sStringBundles[file];
4289 bundle->AsyncPreload();
4290 }),
4291 EventQueuePriority::Idle);
4292 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4292)
;
4293 }
4294}
4295
4296/* static */
4297bool nsContentUtils::SpoofLocaleEnglish() {
4298 // 0 - will prompt
4299 // 1 - don't spoof
4300 // 2 - spoof
4301 return StaticPrefs::privacy_spoof_english() == 2;
4302}
4303
4304/* static */
4305bool nsContentUtils::SpoofLocaleEnglish(const Document* aDocument) {
4306 return SpoofLocaleEnglish() && (!aDocument || !aDocument->AllowsL10n());
4307}
4308
4309static nsContentUtils::PropertiesFile GetMaybeSpoofedPropertiesFile(
4310 nsContentUtils::PropertiesFile aFile, const char* aKey,
4311 Document* aDocument) {
4312 // When we spoof English, use en-US properties in strings that are accessible
4313 // by content.
4314 bool spoofLocale = nsContentUtils::SpoofLocaleEnglish(aDocument);
4315 if (spoofLocale) {
4316 switch (aFile) {
4317 case nsContentUtils::eFORMS_PROPERTIES:
4318 return nsContentUtils::eFORMS_PROPERTIES_en_US;
4319 case nsContentUtils::eDOM_PROPERTIES:
4320 return nsContentUtils::eDOM_PROPERTIES_en_US;
4321 default:
4322 break;
4323 }
4324 }
4325 return aFile;
4326}
4327
4328/* static */
4329nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
4330 const char* aKey,
4331 Document* aDocument,
4332 nsAString& aResult) {
4333 return GetLocalizedString(
4334 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
4335}
4336
4337/* static */
4338nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
4339 const char* aKey,
4340 nsAString& aResult) {
4341 return FormatLocalizedString(aFile, aKey, {}, aResult);
4342}
4343
4344/* static */
4345nsresult nsContentUtils::FormatMaybeLocalizedString(
4346 PropertiesFile aFile, const char* aKey, Document* aDocument,
4347 const nsTArray<nsString>& aParams, nsAString& aResult) {
4348 return FormatLocalizedString(
4349 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
4350 aResult);
4351}
4352
4353class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
4354 public:
4355 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
4356 nsContentUtils::PropertiesFile aFile,
4357 const char* aKey,
4358 const nsTArray<nsString>& aParams,
4359 nsAString& aLocalizedString)
4360 : WorkerMainThreadRunnable(aWorkerPrivate,
4361 "FormatLocalizedStringRunnable"_ns),
4362 mFile(aFile),
4363 mKey(aKey),
4364 mParams(aParams),
4365 mLocalizedString(aLocalizedString) {
4366 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWorkerPrivate"
")"); do { *((volatile int*)__null) = 4366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4367 aWorkerPrivate->AssertIsOnWorkerThread();
4368 }
4369
4370 bool MainThreadRun() override {
4371 AssertIsOnMainThread();
4372
4373 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
4374 mLocalizedString);
4375 Unused << NS_WARN_IF(NS_FAILED(mResult))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mResult
)), 0))), "NS_FAILED(mResult)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4375)
;
4376 return true;
4377 }
4378
4379 nsresult GetResult() const { return mResult; }
4380
4381 private:
4382 const nsContentUtils::PropertiesFile mFile;
4383 const char* mKey;
4384 const nsTArray<nsString>& mParams;
4385 nsresult mResult = NS_ERROR_FAILURE;
4386 nsAString& mLocalizedString;
4387};
4388
4389/* static */
4390nsresult nsContentUtils::FormatLocalizedString(
4391 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
4392 nsAString& aResult) {
4393 if (!NS_IsMainThread()) {
4394 // nsIStringBundle is thread-safe but its creation is not, and in particular
4395 // we don't create and store nsIStringBundle objects in a thread-safe way.
4396 //
4397 // TODO(emilio): Maybe if we already have the right bundle created we could
4398 // just call into it, but we should make sure that Shutdown() doesn't get
4399 // called on the main thread when that happens which is a bit tricky to
4400 // prove?
4401 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
4402 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4402)
) {
4403 return NS_ERROR_UNEXPECTED;
4404 }
4405
4406 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
4407 workerPrivate, aFile, aKey, aParams, aResult);
4408
4409 runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors());
4410 return runnable->GetResult();
4411 }
4412
4413 MOZ_TRY(EnsureStringBundle(aFile))do { auto mozTryTempResult_ = ::mozilla::ToResult(EnsureStringBundle
(aFile)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
;
4414 nsIStringBundle* bundle = sStringBundles[aFile];
4415 if (aParams.IsEmpty()) {
4416 return bundle->GetStringFromName(aKey, aResult);
4417 }
4418 return bundle->FormatStringFromName(aKey, aParams, aResult);
4419}
4420
4421/* static */
4422void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
4423 const nsACString& aCategory,
4424 bool aFromPrivateWindow,
4425 bool aFromChromeContext,
4426 uint32_t aErrorFlags) {
4427 nsCOMPtr<nsIScriptError> scriptError =
4428 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
4429 if (scriptError) {
4430 nsCOMPtr<nsIConsoleService> console =
4431 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
4432 if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
4433 aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
4434 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
4435 console->LogMessage(scriptError);
4436 }
4437 }
4438}
4439
4440/* static */
4441nsresult nsContentUtils::ReportToConsole(
4442 uint32_t aErrorFlags, const nsACString& aCategory,
4443 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
4444 const nsTArray<nsString>& aParams, const SourceLocation& aLoc) {
4445 nsresult rv;
4446 nsAutoString errorText;
4447 if (!aParams.IsEmpty()) {
4448 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
4449 } else {
4450 rv = GetLocalizedString(aFile, aMessageName, errorText);
4451 }
4452 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4452); return rv; } } while (false)
;
4453 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
4454 aDocument, aLoc);
4455}
4456
4457/* static */
4458void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
4459 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
4460 nsContentUtils::eDOM_PROPERTIES, "EmptyGetElementByIdParam");
4461}
4462
4463/* static */
4464nsresult nsContentUtils::ReportToConsoleNonLocalized(
4465 const nsAString& aErrorText, uint32_t aErrorFlags,
4466 const nsACString& aCategory, const Document* aDocument,
4467 const SourceLocation& aLoc) {
4468 uint64_t innerWindowID = aDocument ? aDocument->InnerWindowID() : 0;
4469 if (aLoc || !aDocument || !aDocument->GetDocumentURI()) {
4470 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
4471 innerWindowID, aLoc);
4472 }
4473 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
4474 innerWindowID,
4475 SourceLocation(aDocument->GetDocumentURI()));
4476}
4477
4478/* static */
4479nsresult nsContentUtils::ReportToConsoleByWindowID(
4480 const nsAString& aErrorText, uint32_t aErrorFlags,
4481 const nsACString& aCategory, uint64_t aInnerWindowID,
4482 const SourceLocation& aLocation) {
4483 nsresult rv;
4484 if (!sConsoleService) { // only need to bother null-checking here
4485 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4486 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4486); return rv; } } while (false)
;
4487 }
4488
4489 nsCOMPtr<nsIScriptError> errorObject =
4490 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
4491 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4491); return rv; } } while (false)
;
4492
4493 if (aLocation.mResource.is<nsCOMPtr<nsIURI>>()) {
4494 nsIURI* uri = aLocation.mResource.as<nsCOMPtr<nsIURI>>();
4495 rv = errorObject->InitWithSourceURI(aErrorText, uri, aLocation.mLine,
4496 aLocation.mColumn, aErrorFlags,
4497 aCategory, aInnerWindowID);
4498 } else {
4499 rv = errorObject->InitWithWindowID(
4500 aErrorText, aLocation.mResource.as<nsCString>(), aLocation.mLine,
4501 aLocation.mColumn, aErrorFlags, aCategory, aInnerWindowID);
4502 }
4503 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4503); return rv; } } while (false)
;
4504
4505 return sConsoleService->LogMessage(errorObject);
4506}
4507
4508void nsContentUtils::LogMessageToConsole(const char* aMsg) {
4509 if (!sConsoleService) { // only need to bother null-checking here
4510 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4511 if (!sConsoleService) {
4512 return;
4513 }
4514 }
4515 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
4516}
4517
4518bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
4519 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
4520}
4521
4522bool nsContentUtils::IsAddonDoc(const Document* aDocument) {
4523 return aDocument &&
4524 aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal();
4525}
4526
4527bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
4528 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
4529 return bc->GetParent();
4530 }
4531 return false;
4532}
4533
4534static bool IsJSONType(const nsACString& aContentType) {
4535 return aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
4536 aContentType.EqualsLiteral(APPLICATION_JSON"application/json");
4537}
4538
4539static bool IsNonPlainTextType(const nsACString& aContentType) {
4540 // MIME type suffixes which should not be plain text.
4541 static constexpr std::string_view kNonPlainTextTypes[] = {
4542 "html",
4543 "xml",
4544 "xsl",
4545 "calendar",
4546 "x-calendar",
4547 "x-vcalendar",
4548 "vcalendar",
4549 "vcard",
4550 "x-vcard",
4551 "directory",
4552 "ldif",
4553 "qif",
4554 "x-qif",
4555 "x-csv",
4556 "x-vcf",
4557 "rtf",
4558 "comma-separated-values",
4559 "csv",
4560 "tab-separated-values",
4561 "tsv",
4562 "ofx",
4563 "vnd.sun.j2me.app-descriptor",
4564 "x-ms-iqy",
4565 "x-ms-odc",
4566 "x-ms-rqy",
4567 "x-ms-contact"};
4568
4569 // Trim off the "text/" prefix for comparison.
4570 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)"
")"); do { *((volatile int*)__null) = 4570; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4571 std::string_view suffix = aContentType;
4572 suffix.remove_prefix(5);
4573
4574 for (std::string_view type : kNonPlainTextTypes) {
4575 if (type == suffix) {
4576 return true;
4577 }
4578 }
4579 return false;
4580}
4581
4582bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
4583 // All `text/*`, any JSON type and any JavaScript type are considered "plain
4584 // text" types for the purposes of how to render them as a document.
4585 return (StringBeginsWith(aContentType, "text/"_ns) &&
4586 !IsNonPlainTextType(aContentType)) ||
4587 IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType);
4588}
4589
4590bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
4591 // NOTE: This must be a subset of the list in IsPlainTextType().
4592 return IsJSONType(aContentType) ||
4593 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
4594 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
4595}
4596
4597bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
4598 return aDocument && aDocument->IsInChromeDocShell();
4599}
4600
4601// static
4602nsIContentPolicy* nsContentUtils::GetContentPolicy() {
4603 if (!sTriedToGetContentPolicy) {
4604 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
4605 // It's OK to not have a content policy service
4606 sTriedToGetContentPolicy = true;
4607 }
4608
4609 return sContentPolicyService;
4610}
4611
4612// static
4613bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
4614 const char16_t* name = aName->GetUTF16String();
4615 if (name[0] != 'o' || name[1] != 'n') {
4616 return false;
4617 }
4618
4619 EventNameMapping mapping;
4620 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
4621}
4622
4623// static
4624EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
4625 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { *((volatile
int*)__null) = 4625; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4626 if (aName) {
4627 EventNameMapping mapping;
4628 if (sAtomEventTable->Get(aName, &mapping)) {
4629 return mapping.mMessage;
4630 }
4631 }
4632
4633 return eUnidentifiedEvent;
4634}
4635
4636// static
4637mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
4638 EventNameMapping mapping;
4639 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
4640
4641 return eBasicEventClass;
4642}
4643
4644nsAtom* nsContentUtils::GetEventMessageAndAtom(
4645 const nsAString& aName, mozilla::EventClassID aEventClassID,
4646 EventMessage* aEventMessage) {
4647 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4647; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4648 EventNameMapping mapping;
4649 if (sStringEventTable->Get(aName, &mapping)) {
4650 *aEventMessage = mapping.mEventClassID == aEventClassID
4651 ? mapping.mMessage
4652 : eUnidentifiedEvent;
4653 return mapping.mAtom;
4654 }
4655
4656 // If we have cached lots of user defined event names, clear some of them.
4657 if (sUserDefinedEvents->Length() > 127) {
4658 while (sUserDefinedEvents->Length() > 64) {
4659 nsAtom* first = sUserDefinedEvents->ElementAt(0);
4660 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
4661 sUserDefinedEvents->RemoveElementAt(0);
4662 }
4663 }
4664
4665 *aEventMessage = eUnidentifiedEvent;
4666 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
4667 sUserDefinedEvents->AppendElement(atom);
4668 mapping.mAtom = atom;
4669 mapping.mMessage = eUnidentifiedEvent;
4670 mapping.mType = EventNameType_None;
4671 mapping.mEventClassID = eBasicEventClass;
4672 sStringEventTable->InsertOrUpdate(aName, mapping);
4673 return mapping.mAtom;
4674}
4675
4676// static
4677EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
4678 const nsAString& aName, nsAtom** aOnName) {
4679 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4679; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4680
4681 // Check sStringEventTable for a matching entry. This will only fail for
4682 // user-defined event types.
4683 EventNameMapping mapping;
4684 if (sStringEventTable->Get(aName, &mapping)) {
4685 RefPtr<nsAtom> atom = mapping.mAtom;
4686 atom.forget(aOnName);
4687 return mapping.mMessage;
4688 }
4689
4690 // sStringEventTable did not contain an entry for this event type string.
4691 // Call GetEventMessageAndAtom, which will create an event type atom and
4692 // cache it in sStringEventTable for future calls.
4693 EventMessage msg = eUnidentifiedEvent;
4694 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
4695 atom.forget(aOnName);
4696 return msg;
4697}
4698
4699static already_AddRefed<Event> GetEventWithTarget(
4700 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4701 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4702 Trusted aTrusted, ErrorResult& aErrorResult) {
4703 RefPtr<Event> event =
4704 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
4705 if (aErrorResult.Failed()) {
4706 return nullptr;
4707 }
4708
4709 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
4710 event->SetTrusted(aTrusted == Trusted::eYes);
4711
4712 event->SetTarget(aTarget);
4713
4714 return event.forget();
4715}
4716
4717// static
4718nsresult nsContentUtils::DispatchTrustedEvent(
4719 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4720 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4721 bool* aDefaultAction) {
4722 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4724; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4723 !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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4724; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4724 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4724; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4725 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4726 aComposed, Trusted::eYes, aDefaultAction);
4727}
4728
4729// static
4730nsresult nsContentUtils::DispatchUntrustedEvent(
4731 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4732 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
4733 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4734 Composed::eDefault, Trusted::eNo, aDefaultAction);
4735}
4736
4737// static
4738nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4739 const nsAString& aEventName,
4740 CanBubble aCanBubble,
4741 Cancelable aCancelable,
4742 Composed aComposed, Trusted aTrusted,
4743 bool* aDefaultAction,
4744 ChromeOnlyDispatch aOnlyChromeDispatch) {
4745 if (!aDoc || !aTarget) {
4746 return NS_ERROR_INVALID_ARG;
4747 }
4748
4749 ErrorResult err;
4750 RefPtr<Event> event =
4751 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4752 aComposed, aTrusted, err);
4753 if (err.Failed()) {
4754 return err.StealNSResult();
4755 }
4756 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
4757 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4758
4759 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
4760 if (aDefaultAction) {
4761 *aDefaultAction = doDefault;
4762 }
4763 return err.StealNSResult();
4764}
4765
4766// static
4767nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4768 WidgetEvent& aEvent,
4769 EventMessage aEventMessage,
4770 CanBubble aCanBubble,
4771 Cancelable aCancelable, Trusted aTrusted,
4772 bool* aDefaultAction,
4773 ChromeOnlyDispatch aOnlyChromeDispatch) {
4774 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4775; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4775 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4775; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4776
4777 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
4778 aEvent.SetDefaultComposed();
4779 aEvent.SetDefaultComposedInNativeAnonymousContent();
4780
4781 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
4782 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
4783 aEvent.mFlags.mOnlyChromeDispatch =
4784 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4785
4786 aEvent.mTarget = aTarget;
4787
4788 nsEventStatus status = nsEventStatus_eIgnore;
4789 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
4790 nullptr, &status);
4791 if (aDefaultAction) {
4792 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
4793 }
4794 return rv;
4795}
4796
4797// static
4798nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
4799 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
4800 mozilla::EditorInputType::eUnknown, nullptr,
4801 InputEventOptions());
4802}
4803
4804// static
4805nsresult nsContentUtils::DispatchInputEvent(
4806 Element* aEventTargetElement, EventMessage aEventMessage,
4807 EditorInputType aEditorInputType, EditorBase* aEditorBase,
4808 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
4809 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4810 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4811
4812 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4812)
) {
4813 return NS_ERROR_INVALID_ARG;
4814 }
4815
4816 // If this is called from editor, the instance should be set to aEditorBase.
4817 // Otherwise, we need to look for an editor for aEventTargetElement.
4818 // However, we don't need to do it for HTMLEditor since nobody shouldn't
4819 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
4820 // itself.
4821 bool useInputEvent = false;
4822 if (aEditorBase) {
4823 useInputEvent = true;
4824 } else if (HTMLTextAreaElement* textAreaElement =
4825 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
4826 aEditorBase = textAreaElement->GetTextEditorWithoutCreation();
4827 useInputEvent = true;
4828 } else if (HTMLInputElement* inputElement =
4829 HTMLInputElement::FromNode(aEventTargetElement)) {
4830 if (inputElement->IsInputEventTarget()) {
4831 aEditorBase = inputElement->GetTextEditorWithoutCreation();
4832 useInputEvent = true;
4833 }
4834 }
4835#ifdef DEBUG1
4836 else {
4837 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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4838 "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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4839 }
4840#endif // #ifdef DEBUG
4841
4842 if (!useInputEvent) {
4843 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { *((volatile int*)__null) = 4843; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4844 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { *((volatile int*)__null) = 4844; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4845 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4845; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4846 // Dispatch "input" event with Event instance.
4847 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
4848 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
4849 widgetEvent.mFlags.mCancelable = false;
4850 widgetEvent.mFlags.mComposed = true;
4851 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
4852 widgetEvent, aEventStatus);
4853 }
4854
4855 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4856 !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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4857 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4858 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4859 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4860
4861 nsCOMPtr<nsIWidget> widget;
4862 if (aEditorBase) {
4863 widget = aEditorBase->GetWidget();
4864 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4864)
) {
4865 return NS_ERROR_FAILURE;
4866 }
4867 } else {
4868 Document* document = aEventTargetElement->OwnerDoc();
4869 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4869)
) {
4870 return NS_ERROR_FAILURE;
4871 }
4872 // If we're running xpcshell tests, we fail to get presShell here.
4873 // Even in such case, we need to dispatch "input" event without widget.
4874 PresShell* presShell = document->GetPresShell();
4875 if (presShell) {
4876 nsPresContext* presContext = presShell->GetPresContext();
4877 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4877)
) {
4878 return NS_ERROR_FAILURE;
4879 }
4880 widget = presContext->GetRootWidget();
4881 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4881)
) {
4882 return NS_ERROR_FAILURE;
4883 }
4884 }
4885 }
4886
4887 // Dispatch "input" event with InputEvent instance.
4888 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
4889
4890 inputEvent.mFlags.mCancelable =
4891 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
4892 IsCancelableBeforeInputEvent(aEditorInputType);
4893 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { *((volatile int*)__null) = 4893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4894
4895 // If there is an editor, set isComposing to true when it has composition.
4896 // Note that EditorBase::IsIMEComposing() may return false even when we
4897 // need to set it to true.
4898 // Otherwise, i.e., editor hasn't been created for the element yet,
4899 // we should set isComposing to false since the element can never has
4900 // composition without editor.
4901 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
4902
4903 if (!aEditorBase || aEditorBase->IsTextEditor()) {
4904 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
4905 inputEvent.mData = std::move(aOptions.mData);
4906 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4907; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4907 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4907; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4908 }
4909#ifdef DEBUG1
4910 else {
4911 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 4911; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4912 }
4913#endif // #ifdef DEBUG
4914 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4916; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4915 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4916; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4916 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4916; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4917 } else {
4918 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { *((volatile int*)__null) = 4918; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4919 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
4920 inputEvent.mData = std::move(aOptions.mData);
4921 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4922; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4922 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4922; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4923 } else {
4924 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 4924; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4925 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
4926 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
4927 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 4928; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4928 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 4928; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4929 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 4930; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4930 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 4930; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4931 }
4932#ifdef DEBUG1
4933 else {
4934 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 4935; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4935 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 4935; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4936 }
4937#endif // #ifdef DEBUG
4938 }
4939 if (aEventMessage == eEditorBeforeInput &&
4940 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
4941 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
4942 }
4943#ifdef DEBUG1
4944 else {
4945 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4946); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 4946; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4946 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4946); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 4946; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4947 }
4948#endif // #ifdef DEBUG
4949 }
4950
4951 inputEvent.mInputType = aEditorInputType;
4952
4953 // If we cannot dispatch an event right now, we cannot make it cancelable.
4954 if (!nsContentUtils::IsSafeToRunScript()) {
4955 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4957); MOZ_PretendNoReturn(); } } while (0)
4956 !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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4957); MOZ_PretendNoReturn(); } } while (0)
4957 "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4957); MOZ_PretendNoReturn(); } } while (0)
;
4958 inputEvent.mFlags.mCancelable = false;
4959 }
4960 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
4961 inputEvent, aEventStatus);
4962}
4963
4964nsresult nsContentUtils::DispatchChromeEvent(
4965 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4966 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
4967 if (!aDoc || !aTarget) {
4968 return NS_ERROR_INVALID_ARG;
4969 }
4970
4971 if (!aDoc->GetWindow()) {
4972 return NS_ERROR_INVALID_ARG;
4973 }
4974
4975 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
4976 if (!piTarget) {
4977 return NS_ERROR_INVALID_ARG;
4978 }
4979
4980 ErrorResult err;
4981 RefPtr<Event> event =
4982 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4983 Composed::eDefault, Trusted::eYes, err);
4984 if (err.Failed()) {
4985 return err.StealNSResult();
4986 }
4987
4988 bool defaultActionEnabled =
4989 piTarget->DispatchEvent(*event, CallerType::System, err);
4990 if (aDefaultAction) {
4991 *aDefaultAction = defaultActionEnabled;
4992 }
4993 return err.StealNSResult();
4994}
4995
4996void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
4997 CallerType aCallerType) {
4998 RefPtr<Element> target = &aFrameElement;
4999 bool defaultAction = true;
5000 if (aCanRaise) {
5001 DispatchEventOnlyToChrome(target->OwnerDoc(), target,
5002 u"framefocusrequested"_ns, CanBubble::eYes,
5003 Cancelable::eYes, &defaultAction);
5004 }
5005 if (!defaultAction) {
5006 return;
5007 }
5008
5009 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
5010 if (!fm) {
5011 return;
5012 }
5013
5014 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
5015 if (aCanRaise) {
5016 flags |= nsIFocusManager::FLAG_RAISE;
5017 }
5018
5019 if (aCallerType == CallerType::NonSystem) {
5020 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
5021 }
5022
5023 fm->SetFocus(target, flags);
5024}
5025
5026nsresult nsContentUtils::DispatchEventOnlyToChrome(
5027 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
5028 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
5029 bool* aDefaultAction) {
5030 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
5031 aComposed, Trusted::eYes, aDefaultAction,
5032 ChromeOnlyDispatch::eYes);
5033}
5034
5035/* static */
5036Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5037 const nsAtom* aId) {
5038 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
5039 if (aId == cur->GetID()) {
5040 return cur->AsElement();
5041 }
5042 }
5043
5044 return nullptr;
5045}
5046
5047/* static */
5048Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5049 const nsAString& aId) {
5050 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { *((volatile int
*)__null) = 5050; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5051
5052 // ID attrs are generally stored as atoms, so just atomize this up front
5053 RefPtr<nsAtom> id(NS_Atomize(aId));
5054 if (!id) {
5055 // OOM, so just bail
5056 return nullptr;
5057 }
5058
5059 return MatchElementId(aContent, id);
5060}
5061
5062/* static */
5063void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
5064 nsCOMPtr<nsIObserverService> observerService =
5065 mozilla::services::GetObserverService();
5066 if (observerService) {
5067 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
5068 false);
5069 }
5070}
5071
5072/* static */
5073void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
5074 nsCOMPtr<nsIObserverService> observerService =
5075 mozilla::services::GetObserverService();
5076 if (observerService) {
5077 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
5078 }
5079}
5080
5081/* static */
5082bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
5083 int32_t aNameSpaceID, nsAtom* aName) {
5084 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
5085 return aContent->IsElement() &&
5086 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
5087 eCaseMatters) ==
5088 AttrArray::ATTR_VALUE_NO_MATCH;
5089}
5090
5091/* static */
5092bool nsContentUtils::WantMutationEvents(nsINode* aNode, uint32_t aType,
5093 nsINode* aTargetForSubtreeModified) {
5094 Document* doc = aNode->OwnerDoc();
5095 if (!doc->MutationEventsEnabled()) {
5096 return false;
5097 }
5098
5099 if (!doc->FireMutationEvents()) {
5100 return false;
5101 }
5102
5103 // global object will be null for documents that don't have windows.
5104 nsPIDOMWindowInner* window = doc->GetInnerWindow();
5105 // This relies on EventListenerManager::AddEventListener, which sets
5106 // all mutation bits when there is a listener for DOMSubtreeModified event.
5107 if (window && !window->HasMutationListeners(aType)) {
5108 return false;
5109 }
5110
5111 if (aNode->ChromeOnlyAccess() || aNode->IsInShadowTree()) {
5112 return false;
5113 }
5114
5115 doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
5116
5117 // If we have a window, we can check it for mutation listeners now.
5118 if (aNode->IsInUncomposedDoc()) {
5119 nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
5120 if (piTarget) {
5121 EventListenerManager* manager = piTarget->GetExistingListenerManager();
5122 if (manager && manager->HasMutationListeners()) {
5123 return true;
5124 }
5125 }
5126 }
5127
5128 // If we have a window, we know a mutation listener is registered, but it
5129 // might not be in our chain. If we don't have a window, we might have a
5130 // mutation listener. Check quickly to see.
5131 while (aNode) {
5132 EventListenerManager* manager = aNode->GetExistingListenerManager();
5133 if (manager && manager->HasMutationListeners()) {
5134 return true;
5135 }
5136
5137 aNode = aNode->GetParentNode();
5138 }
5139
5140 return false;
5141}
5142
5143/* static */
5144bool nsContentUtils::HasMutationListeners(Document* aDocument, uint32_t aType) {
5145 nsPIDOMWindowInner* window =
5146 aDocument ? aDocument->GetInnerWindow() : nullptr;
5147
5148 // This relies on EventListenerManager::AddEventListener, which sets
5149 // all mutation bits when there is a listener for DOMSubtreeModified event.
5150 return !window || window->HasMutationListeners(aType);
5151}
5152
5153void nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent) {
5154 MOZ_ASSERT(aChild, "Missing child")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChild" " (" "Missing child"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") ("
"Missing child" ")"); do { *((volatile int*)__null) = 5154; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5155 MOZ_ASSERT(aChild->GetParentNode() == aParent, "Wrong parent")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetParentNode() == aParent)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(aChild->GetParentNode() == aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChild->GetParentNode() == aParent"
" (" "Wrong parent" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode() == aParent"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5155
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5156 MOZ_ASSERT(aChild->OwnerDoc() == aParent->OwnerDoc(), "Wrong owner-doc")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->OwnerDoc() == aParent->OwnerDoc())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->OwnerDoc() == aParent->OwnerDoc()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->OwnerDoc() == aParent->OwnerDoc()"
" (" "Wrong owner-doc" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->OwnerDoc() == aParent->OwnerDoc()"
") (" "Wrong owner-doc" ")"); do { *((volatile int*)__null) =
5156; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5157
5158 // Having an explicit check here since it's an easy mistake to fall into,
5159 // and there might be existing code with problems. We'd rather be safe
5160 // than fire DOMNodeRemoved in all corner cases. We also rely on it for
5161 // nsAutoScriptBlockerSuppressNodeRemoved.
5162 if (!IsSafeToRunScript()) {
5163 // This checks that IsSafeToRunScript is true since we don't want to fire
5164 // events when that is false. We can't rely on EventDispatcher to assert
5165 // this in this situation since most of the time there are no mutation
5166 // event listeners, in which case we won't even attempt to dispatch events.
5167 // However this also allows for two exceptions. First off, we don't assert
5168 // if the mutation happens to native anonymous content since we never fire
5169 // mutation events on such content anyway.
5170 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
5171 // that is a know case when we'd normally fire a mutation event, but can't
5172 // make that safe and so we suppress it at this time. Ideally this should
5173 // go away eventually.
5174 if (!aChild->IsInNativeAnonymousSubtree() &&
5175 !sDOMNodeRemovedSuppressCount) {
5176 NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire DOMNodeRemoved event, but it's not safe"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5176); MOZ_PretendNoReturn(); } while (0)
;
5177 WarnScriptWasIgnored(aChild->OwnerDoc());
5178 }
5179 return;
5180 }
5181
5182 {
5183 Document* doc = aParent->OwnerDoc();
5184 if (MOZ_UNLIKELY(doc->DevToolsWatchingDOMMutations())(__builtin_expect(!!(doc->DevToolsWatchingDOMMutations()),
0))
&&
5185 aChild->IsInComposedDoc() && !aChild->ChromeOnlyAccess()) {
5186 DispatchChromeEvent(doc, aChild, u"devtoolschildremoved"_ns,
5187 CanBubble::eNo, Cancelable::eNo);
5188 }
5189 }
5190
5191 if (WantMutationEvents(aChild, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04, aParent)) {
5192 InternalMutationEvent mutation(true, eLegacyNodeRemoved);
5193 mutation.mRelatedNode = aParent;
5194
5195 mozAutoSubtreeModified subtree(aParent->OwnerDoc(), aParent);
5196 EventDispatcher::Dispatch(aChild, nullptr, &mutation);
5197 }
5198}
5199
5200void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() {
5201 if (!sEventListenerManagersHash) {
5202 return;
5203 }
5204
5205 for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
5206 auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
5207 nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
5208 if (n && n->IsInComposedDoc() &&
5209 nsCCUncollectableMarker::InGeneration(
5210 n->OwnerDoc()->GetMarkedCCGeneration())) {
5211 entry->mListenerManager->MarkForCC();
5212 }
5213 }
5214}
5215
5216/* static */
5217void nsContentUtils::TraverseListenerManager(
5218 nsINode* aNode, nsCycleCollectionTraversalCallback& cb) {
5219 if (!sEventListenerManagersHash) {
5220 // We're already shut down, just return.
5221 return;
5222 }
5223
5224 auto entry = static_cast<EventListenerManagerMapEntry*>(
5225 sEventListenerManagersHash->Search(aNode));
5226 if (entry) {
5227 CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
5228 "[via hash] mListenerManager");
5229 }
5230}
5231
5232EventListenerManager* nsContentUtils::GetListenerManagerForNode(
5233 nsINode* aNode) {
5234 if (!sEventListenerManagersHash) {
5235 // We're already shut down, don't bother creating an event listener
5236 // manager.
5237
5238 return nullptr;
5239 }
5240
5241 auto entry = static_cast<EventListenerManagerMapEntry*>(
5242 sEventListenerManagersHash->Add(aNode, fallible));
5243
5244 if (!entry) {
5245 return nullptr;
5246 }
5247
5248 if (!entry->mListenerManager) {
5249 entry->mListenerManager = new EventListenerManager(aNode);
5250
5251 aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
5252 }
5253
5254 return entry->mListenerManager;
5255}
5256
5257EventListenerManager* nsContentUtils::GetExistingListenerManagerForNode(
5258 const nsINode* aNode) {
5259 if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
5260 return nullptr;
5261 }
5262
5263 if (!sEventListenerManagersHash) {
5264 // We're already shut down, don't bother creating an event listener
5265 // manager.
5266
5267 return nullptr;
5268 }
5269
5270 auto entry = static_cast<EventListenerManagerMapEntry*>(
5271 sEventListenerManagersHash->Search(aNode));
5272 if (entry) {
5273 return entry->mListenerManager;
5274 }
5275
5276 return nullptr;
5277}
5278
5279void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
5280 DOMArena* aDOMArena) {
5281 MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5281; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5282 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5282; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5283 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)"
")"); do { *((volatile int*)__null) = 5283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5284 if (!sDOMArenaHashtable) {
5285 sDOMArenaHashtable =
5286 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
5287 }
5288 aNode->SetFlags(NODE_KEEPS_DOMARENA);
5289 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
5290}
5291
5292already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
5293 const nsINode* aNode) {
5294 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5294; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5295 MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5296 RefPtr<DOMArena> arena;
5297 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
5298 return arena.forget();
5299}
5300
5301/* static */
5302void nsContentUtils::RemoveListenerManager(nsINode* aNode) {
5303 if (sEventListenerManagersHash) {
5304 auto entry = static_cast<EventListenerManagerMapEntry*>(
5305 sEventListenerManagersHash->Search(aNode));
5306 if (entry) {
5307 RefPtr<EventListenerManager> listenerManager;
5308 listenerManager.swap(entry->mListenerManager);
5309 // Remove the entry and *then* do operations that could cause further
5310 // modification of sEventListenerManagersHash. See bug 334177.
5311 sEventListenerManagersHash->RawRemove(entry);
5312 if (listenerManager) {
5313 listenerManager->Disconnect();
5314 }
5315 }
5316 }
5317}
5318
5319/* static */
5320bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
5321 int32_t aNamespaceID) {
5322 if (aNamespaceID == kNameSpaceID_Unknown-1) {
5323 return false;
5324 }
5325
5326 if (!aPrefix) {
5327 // If the prefix is null, then either the QName must be xmlns or the
5328 // namespace must not be XMLNS.
5329 return (aLocalName == nsGkAtoms::xmlns) ==
5330 (aNamespaceID == kNameSpaceID_XMLNS1);
5331 }
5332
5333 // If the prefix is non-null then the namespace must not be null.
5334 if (aNamespaceID == kNameSpaceID_None) {
5335 return false;
5336 }
5337
5338 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
5339 // but the localname must not be xmlns.
5340 if (aNamespaceID == kNameSpaceID_XMLNS1) {
5341 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
5342 }
5343
5344 // If the namespace is not the XMLNS namespace then the prefix must not be
5345 // xmlns.
5346 // If the namespace is the XML namespace then the prefix can be anything.
5347 // If the namespace is not the XML namespace then the prefix must not be xml.
5348 return aPrefix != nsGkAtoms::xmlns &&
5349 (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml);
5350}
5351
5352already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment(
5353 nsINode* aContextNode, const nsAString& aFragment,
5354 bool aPreventScriptExecution, ErrorResult& aRv) {
5355 if (!aContextNode) {
5356 aRv.Throw(NS_ERROR_INVALID_ARG);
5357 return nullptr;
5358 }
5359
5360 // If we don't have a document here, we can't get the right security context
5361 // for compiling event handlers... so just bail out.
5362 RefPtr<Document> document = aContextNode->OwnerDoc();
5363 bool isHTML = document->IsHTMLDocument();
5364
5365 if (isHTML) {
5366 RefPtr<DocumentFragment> frag = new (document->NodeInfoManager())
5367 DocumentFragment(document->NodeInfoManager());
5368
5369 Element* element = aContextNode->GetAsElementOrParentElement();
5370 if (element && !element->IsHTMLElement(nsGkAtoms::html)) {
5371 aRv = ParseFragmentHTML(
5372 aFragment, frag, element->NodeInfo()->NameAtom(),
5373 element->GetNameSpaceID(),
5374 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
5375 aPreventScriptExecution);
5376 } else {
5377 aRv = ParseFragmentHTML(
5378 aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3,
5379 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
5380 aPreventScriptExecution);
5381 }
5382
5383 return frag.forget();
5384 }
5385
5386 AutoTArray<nsString, 32> tagStack;
5387 nsAutoString uriStr, nameStr;
5388 for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) {
5389 nsString& tagName = *tagStack.AppendElement();
5390 // It mostly doesn't actually matter what tag name we use here: XML doesn't
5391 // have parsing that depends on the open tag stack, apart from namespace
5392 // declarations. So this whole tagStack bit is just there to get the right
5393 // namespace declarations to the XML parser. That said, the parser _is_
5394 // going to create elements with the tag names we provide here, so we need
5395 // to make sure they are not names that can trigger custom element
5396 // constructors. Just make up a name that is never going to be a valid
5397 // custom element name.
5398 //
5399 // The principled way to do this would probably be to add a new FromParser
5400 // value and make sure we use it when creating the context elements, then
5401 // make sure we teach all FromParser consumers (and in particular the custom
5402 // element code) about it as needed. But right now the XML parser never
5403 // actually uses FromParser values other than NOT_FROM_PARSER, and changing
5404 // that is pretty complicated.
5405 tagName.AssignLiteral("notacustomelement");
5406
5407 // see if we need to add xmlns declarations
5408 uint32_t count = element->GetAttrCount();
5409 bool setDefaultNamespace = false;
5410 if (count > 0) {
5411 uint32_t index;
5412
5413 for (index = 0; index < count; index++) {
5414 const BorrowedAttrInfo info = element->GetAttrInfoAt(index);
5415 const nsAttrName* name = info.mName;
5416 if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) {
5417 info.mValue->ToString(uriStr);
5418
5419 // really want something like nsXMLContentSerializer::SerializeAttr
5420 tagName.AppendLiteral(" xmlns"); // space important
5421 if (name->GetPrefix()) {
5422 tagName.Append(char16_t(':'));
5423 name->LocalName()->ToString(nameStr);
5424 tagName.Append(nameStr);
5425 } else {
5426 setDefaultNamespace = true;
5427 }
5428 tagName.AppendLiteral(R"(=")");
5429 tagName.Append(uriStr);
5430 tagName.Append('"');
5431 }
5432 }
5433 }
5434
5435 if (!setDefaultNamespace) {
5436 mozilla::dom::NodeInfo* info = element->NodeInfo();
5437 if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) {
5438 // We have no namespace prefix, but have a namespace ID. Push
5439 // default namespace attr in, so that our kids will be in our
5440 // namespace.
5441 info->GetNamespaceURI(uriStr);
5442 tagName.AppendLiteral(R"( xmlns=")");
5443 tagName.Append(uriStr);
5444 tagName.Append('"');
5445 }
5446 }
5447 }
5448
5449 RefPtr<DocumentFragment> frag;
5450 aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution,
5451 -1, getter_AddRefs(frag));
5452 return frag.forget();
5453}
5454
5455/* static */
5456void nsContentUtils::DropFragmentParsers() {
5457 NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release
(); (sHTMLFragmentParser) = 0; } } while (0)
;
5458 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
5459 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
5460}
5461
5462/* static */
5463void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); }
5464
5465/* Helper function to compuate Sanitization Flags for ParseFramentHTML/XML */
5466uint32_t computeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) {
5467 uint32_t sanitizationFlags = 0;
5468 if (aPrincipal->IsSystemPrincipal()) {
5469 if (aFlags < 0) {
5470 // if this is a chrome-privileged document and no explicit flags
5471 // were passed, then use this sanitization flags.
5472 sanitizationFlags = nsIParserUtils::SanitizerAllowStyle |
5473 nsIParserUtils::SanitizerAllowComments |
5474 nsIParserUtils::SanitizerDropForms |
5475 nsIParserUtils::SanitizerLogRemovals;
5476 } else {
5477 // if the caller explicitly passes flags, then we use those
5478 // flags but additionally drop forms.
5479 sanitizationFlags = aFlags | nsIParserUtils::SanitizerDropForms;
5480 }
5481 } else if (aFlags >= 0) {
5482 // aFlags by default is -1 and is only ever non equal to -1 if the
5483 // caller of ParseFragmentHTML/ParseFragmentXML is
5484 // ParserUtils::ParseFragment(). Only in that case we should use
5485 // the sanitization flags passed within aFlags.
5486 sanitizationFlags = aFlags;
5487 }
5488 return sanitizationFlags;
5489}
5490
5491/* static */
5492void nsContentUtils::SetHTMLUnsafe(FragmentOrElement* aTarget,
5493 Element* aContext,
5494 const TrustedHTMLOrString& aSource,
5495 bool aIsShadowRoot, ErrorResult& aError) {
5496 constexpr nsLiteralString elementSink = u"Element setHTMLUnsafe"_ns;
5497 constexpr nsLiteralString shadowRootSink = u"ShadowRoot setHTMLUnsafe"_ns;
5498 Maybe<nsAutoString> compliantStringHolder;
5499 const nsAString* compliantString =
5500 TrustedTypeUtils::GetTrustedTypesCompliantString(
5501 aSource, aIsShadowRoot ? shadowRootSink : elementSink,
5502 kTrustedTypesOnlySinkGroup, *aContext, compliantStringHolder, aError);
5503 if (aError.Failed()) {
5504 return;
5505 }
5506
5507 RefPtr<DocumentFragment> fragment;
5508 {
5509 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { *(
(volatile int*)__null) = 5510; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
5510 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { *(
(volatile int*)__null) = 5510; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
5511 mozilla::AutoRestore<bool> guard(sFragmentParsingActive);
5512 sFragmentParsingActive = true;
5513 if (!sHTMLFragmentParser) {
5514 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5515 // Now sHTMLFragmentParser owns the object
5516 }
5517
5518 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
5519 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
5520
5521 RefPtr<Document> doc = aTarget->OwnerDoc();
5522 fragment = doc->CreateDocumentFragment();
5523
5524 nsresult rv = sHTMLFragmentParser->ParseFragment(
5525 *compliantString, fragment, contextLocalName, contextNameSpaceID,
5526 fragment->OwnerDoc()->GetCompatibilityMode() ==
5527 eCompatibility_NavQuirks,
5528 true, true);
5529 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5530 NS_WARNING("Failed to parse fragment for SetHTMLUnsafe")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse fragment for SetHTMLUnsafe"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5530)
;
5531 }
5532 }
5533
5534 aTarget->ReplaceChildren(fragment, IgnoreErrors());
5535}
5536
5537/* static */
5538nsresult nsContentUtils::ParseFragmentHTML(
5539 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
5540 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
5541 bool aPreventScriptExecution, int32_t aFlags) {
5542 if (nsContentUtils::sFragmentParsingActive) {
5543 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5543; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5544 return NS_ERROR_DOM_INVALID_STATE_ERR;
5545 }
5546 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5547 nsContentUtils::sFragmentParsingActive = true;
5548 if (!sHTMLFragmentParser) {
5549 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5550 // Now sHTMLFragmentParser owns the object
5551 }
5552
5553 nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal();
5554
5555#ifdef DEBUG1
5556 // aFlags should always be -1 unless the caller of ParseFragmentHTML
5557 // is ParserUtils::ParseFragment() which is the only caller that intends
5558 // sanitization. For all other callers we need to ensure to call
5559 // AuditParsingOfHTMLXMLFragments.
5560 if (aFlags < 0) {
5561 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
5562 aSourceBuffer);
5563 }
5564#endif
5565
5566 nsIContent* target = aTargetNode;
5567
5568 RefPtr<Document> doc = aTargetNode->OwnerDoc();
5569 RefPtr<DocumentFragment> fragment;
5570 // We sanitize if the fragment occurs in a system privileged
5571 // context, an about: page, or if there are explicit sanitization flags.
5572 // Please note that about:blank and about:srcdoc inherit the security
5573 // context from the embedding context and hence are not loaded using
5574 // an about: scheme principal.
5575 bool shouldSanitize = nodePrincipal->IsSystemPrincipal() ||
5576 nodePrincipal->SchemeIs("about") || aFlags >= 0;
5577 if (shouldSanitize) {
5578 if (!doc->IsLoadedAsData()) {
5579 doc = nsContentUtils::CreateInertHTMLDocument(doc);
5580 if (!doc) {
5581 return NS_ERROR_FAILURE;
5582 }
5583 }
5584 fragment =
5585 new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager());
5586 target = fragment;
5587 }
5588
5589 nsresult rv = sHTMLFragmentParser->ParseFragment(
5590 aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks,
5591 aPreventScriptExecution, false);
5592 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5592); return rv; } } while (false)
;
5593
5594 if (fragment) {
5595 uint32_t sanitizationFlags =
5596 computeSanitizationFlags(nodePrincipal, aFlags);
5597 // Don't fire mutation events for nodes removed by the sanitizer.
5598 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
5599 nsTreeSanitizer sanitizer(sanitizationFlags);
5600 sanitizer.Sanitize(fragment);
5601
5602 ErrorResult error;
5603 aTargetNode->AppendChild(*fragment, error);
5604 rv = error.StealNSResult();
5605 }
5606
5607 return rv;
5608}
5609
5610/* static */
5611nsresult nsContentUtils::ParseDocumentHTML(
5612 const nsAString& aSourceBuffer, Document* aTargetDocument,
5613 bool aScriptingEnabledForNoscriptParsing) {
5614 if (nsContentUtils::sFragmentParsingActive) {
5615 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5616 return NS_ERROR_DOM_INVALID_STATE_ERR;
5617 }
5618 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5619 nsContentUtils::sFragmentParsingActive = true;
5620 if (!sHTMLFragmentParser) {
5621 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5622 // Now sHTMLFragmentParser owns the object
5623 }
5624 nsresult rv = sHTMLFragmentParser->ParseDocument(
5625 aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing);
5626 return rv;
5627}
5628
5629/* static */
5630nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
5631 Document* aDocument,
5632 nsTArray<nsString>& aTagStack,
5633 bool aPreventScriptExecution,
5634 int32_t aFlags,
5635 DocumentFragment** aReturn) {
5636 if (nsContentUtils::sFragmentParsingActive) {
5637 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5637; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5638 return NS_ERROR_DOM_INVALID_STATE_ERR;
5639 }
5640 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5641 nsContentUtils::sFragmentParsingActive = true;
5642 if (!sXMLFragmentParser) {
5643 RefPtr<nsParser> parser = new nsParser();
5644 parser.forget(&sXMLFragmentParser);
5645 // sXMLFragmentParser now owns the parser
5646 }
5647 if (!sXMLFragmentSink) {
5648 NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
5649 // sXMLFragmentSink now owns the sink
5650 }
5651 nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
5652 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink"
") (" "Sink doesn't QI to nsIContentSink!" ")"); do { *((volatile
int*)__null) = 5652; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5653 sXMLFragmentParser->SetContentSink(contentsink);
5654
5655 RefPtr<Document> doc;
5656 nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal();
5657
5658#ifdef DEBUG1
5659 // aFlags should always be -1 unless the caller of ParseFragmentXML
5660 // is ParserUtils::ParseFragment() which is the only caller that intends
5661 // sanitization. For all other callers we need to ensure to call
5662 // AuditParsingOfHTMLXMLFragments.
5663 if (aFlags < 0) {
5664 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
5665 aSourceBuffer);
5666 }
5667#endif
5668
5669 // We sanitize if the fragment occurs in a system privileged
5670 // context, an about: page, or if there are explicit sanitization flags.
5671 // Please note that about:blank and about:srcdoc inherit the security
5672 // context from the embedding context and hence are not loaded using
5673 // an about: scheme principal.
5674 bool shouldSanitize = nodePrincipal->IsSystemPrincipal() ||
5675 nodePrincipal->SchemeIs("about") || aFlags >= 0;
5676 if (shouldSanitize && !aDocument->IsLoadedAsData()) {
5677 doc = nsContentUtils::CreateInertXMLDocument(aDocument);
5678 } else {
5679 doc = aDocument;
5680 }
5681
5682 sXMLFragmentSink->SetTargetDocument(doc);
5683 sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
5684
5685 nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack);
5686 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5687 // Drop the fragment parser and sink that might be in an inconsistent state
5688 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
5689 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
5690 return rv;
5691 }
5692
5693 rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
5694
5695 sXMLFragmentParser->Reset();
5696 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5696); return rv; } } while (false)
;
5697
5698 if (shouldSanitize) {
5699 uint32_t sanitizationFlags =
5700 computeSanitizationFlags(nodePrincipal, aFlags);
5701 // Don't fire mutation events for nodes removed by the sanitizer.
5702 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
5703 nsTreeSanitizer sanitizer(sanitizationFlags);
5704 sanitizer.Sanitize(*aReturn);
5705 }
5706
5707 return rv;
5708}
5709
5710/* static */
5711nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
5712 nsAString& aResultBuffer,
5713 uint32_t aFlags,
5714 uint32_t aWrapCol) {
5715 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
5716 if (!document) {
5717 return NS_ERROR_FAILURE;
5718 }
5719
5720 nsresult rv = nsContentUtils::ParseDocumentHTML(
5721 aSourceBuffer, document,
5722 !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
5723 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5723); return rv; } } while (false)
;
5724
5725 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain");
5726
5727 rv = encoder->Init(document, u"text/plain"_ns, aFlags);
5728 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5728); return rv; } } while (false)
;
5729
5730 encoder->SetWrapColumn(aWrapCol);
5731
5732 return encoder->EncodeToString(aResultBuffer);
5733}
5734
5735static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate,
5736 DocumentFlavor aFlavor) {
5737 if (aTemplate) {
5738 bool hasHad = true;
5739 nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
5740 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5740); return nullptr; } } while (false)
;
5741
5742 nsCOMPtr<Document> doc;
5743 nsresult rv = NS_NewDOMDocument(
5744 getter_AddRefs(doc), u""_ns, u""_ns, nullptr,
5745 aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(),
5746 aTemplate->NodePrincipal(), true, sgo, aFlavor);
5747 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5748 return nullptr;
5749 }
5750 return doc.forget();
5751 }
5752 nsCOMPtr<nsIURI> uri;
5753 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
5754 if (!uri) {
5755 return nullptr;
5756 }
5757
5758 RefPtr<NullPrincipal> nullPrincipal =
5759 NullPrincipal::CreateWithoutOriginAttributes();
5760 if (!nullPrincipal) {
5761 return nullptr;
5762 }
5763
5764 nsCOMPtr<Document> doc;
5765 nsresult rv =
5766 NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri,
5767 nullPrincipal, true, nullptr, aFlavor);
5768 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5769 return nullptr;
5770 }
5771 return doc.forget();
5772}
5773
5774/* static */
5775already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument(
5776 const Document* aTemplate) {
5777 return CreateInertDocument(aTemplate, DocumentFlavorXML);
5778}
5779
5780/* static */
5781already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
5782 const Document* aTemplate) {
5783 return CreateInertDocument(aTemplate, DocumentFlavorHTML);
5784}
5785
5786/* static */
5787nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent,
5788 const nsAString& aValue,
5789 bool aTryReuse) {
5790 // Fire DOMNodeRemoved mutation events before we do anything else.
5791 nsCOMPtr<nsIContent> owningContent;
5792
5793 // Batch possible DOMSubtreeModified events.
5794 mozAutoSubtreeModified subtree(nullptr, nullptr);
5795
5796 // Scope firing mutation events so that we don't carry any state that
5797 // might be stale
5798 {
5799 // We're relying on mozAutoSubtreeModified to keep a strong reference if
5800 // needed.
5801 Document* doc = aContent->OwnerDoc();
5802
5803 // Optimize the common case of there being no observers
5804 if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04)) {
5805 subtree.UpdateTarget(doc, nullptr);
5806 owningContent = aContent;
5807 nsCOMPtr<nsINode> child;
5808 bool skipFirst = aTryReuse;
5809 for (child = aContent->GetFirstChild();
5810 child && child->GetParentNode() == aContent;
5811 child = child->GetNextSibling()) {
5812 if (skipFirst && child->IsText()) {
5813 skipFirst = false;
5814 continue;
5815 }
5816 nsContentUtils::MaybeFireNodeRemoved(child, aContent);
5817 }
5818 }
5819 }
5820
5821 // Might as well stick a batch around this since we're performing several
5822 // mutations.
5823 mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true);
5824 nsAutoMutationBatch mb;
5825
5826 if (aTryReuse && !aValue.IsEmpty()) {
5827 // Let's remove nodes until we find a eTEXT.
5828 while (aContent->HasChildren()) {
5829 nsIContent* child = aContent->GetFirstChild();
5830 if (child->IsText()) {
5831 break;
5832 }
5833 aContent->RemoveChildNode(child, true);
5834 }
5835
5836 // If we have a node, it must be a eTEXT and we reuse it.
5837 if (aContent->HasChildren()) {
5838 nsIContent* child = aContent->GetFirstChild();
5839 nsresult rv = child->AsText()->SetText(aValue, true);
5840 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5840); return rv; } } while (false)
;
5841
5842 // All the following nodes, if they exist, must be deleted.
5843 while (nsIContent* lastChild = aContent->GetLastChild()) {
5844 if (lastChild == child) {
5845 break;
5846 }
5847 aContent->RemoveChildNode(lastChild, true);
5848 }
5849 }
5850
5851 if (aContent->HasChildren()) {
5852 return NS_OK;
5853 }
5854 } else {
5855 mb.Init(aContent, true, false);
5856 aContent->RemoveAllChildren(true);
5857 }
5858 mb.RemovalDone();
5859
5860 if (aValue.IsEmpty()) {
5861 return NS_OK;
5862 }
5863
5864 RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager())
5865 nsTextNode(aContent->NodeInfo()->NodeInfoManager());
5866
5867 textContent->SetText(aValue, true);
5868
5869 ErrorResult rv;
5870 aContent->AppendChildTo(textContent, true, rv);
5871 mb.NodesAdded();
5872 return rv.StealNSResult();
5873}
5874
5875static bool AppendNodeTextContentsRecurse(const nsINode* aNode,
5876 nsAString& aResult,
5877 const fallible_t& aFallible) {
5878 for (nsIContent* child = aNode->GetFirstChild(); child;
5879 child = child->GetNextSibling()) {
5880 if (child->IsElement()) {
5881 bool ok = AppendNodeTextContentsRecurse(child, aResult, aFallible);
5882 if (!ok) {
5883 return false;
5884 }
5885 } else if (Text* text = child->GetAsText()) {
5886 bool ok = text->AppendTextTo(aResult, aFallible);
5887 if (!ok) {
5888 return false;
5889 }
5890 }
5891 }
5892
5893 return true;
5894}
5895
5896/* static */
5897bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
5898 nsAString& aResult,
5899 const fallible_t& aFallible) {
5900 if (const Text* text = aNode->GetAsText()) {
5901 return text->AppendTextTo(aResult, aFallible);
5902 }
5903 if (aDeep) {
5904 return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
5905 }
5906
5907 for (nsIContent* child = aNode->GetFirstChild(); child;
5908 child = child->GetNextSibling()) {
5909 if (Text* text = child->GetAsText()) {
5910 bool ok = text->AppendTextTo(aResult, fallible);
5911 if (!ok) {
5912 return false;
5913 }
5914 }
5915 }
5916 return true;
5917}
5918
5919bool nsContentUtils::HasNonEmptyTextContent(
5920 nsINode* aNode, TextContentDiscoverMode aDiscoverMode) {
5921 for (nsIContent* child = aNode->GetFirstChild(); child;
5922 child = child->GetNextSibling()) {
5923 if (child->IsText() && child->TextLength() > 0) {
5924 return true;
5925 }
5926
5927 if (aDiscoverMode == eRecurseIntoChildren &&
5928 HasNonEmptyTextContent(child, aDiscoverMode)) {
5929 return true;
5930 }
5931 }
5932
5933 return false;
5934}
5935
5936/* static */
5937bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
5938 const nsINode* aOtherNode) {
5939 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") ("
"Must have a node to work with" ")"); do { *((volatile int*)
__null) = 5939; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5940 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode"
") (" "Must have a content to work with" ")"); do { *((volatile
int*)__null) = 5940; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5941
5942 const bool anon = aNode->IsInNativeAnonymousSubtree();
5943 if (anon != aOtherNode->IsInNativeAnonymousSubtree()) {
5944 return false;
5945 }
5946
5947 if (anon) {
5948 return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() ==
5949 aNode->GetClosestNativeAnonymousSubtreeRoot();
5950 }
5951
5952 // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
5953 // use to either. Maybe that's fine.
5954 return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow();
5955}
5956
5957/* static */
5958bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement,
5959 const Element* aStop) {
5960 const Element* element = aElement;
5961 while (element && element != aStop) {
5962 if (element->IsInteractiveHTMLContent()) {
5963 return true;
5964 }
5965 element = element->GetFlattenedTreeParentElement();
5966 }
5967 return false;
5968}
5969
5970/* static */
5971void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) {
5972 IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
5973}
5974
5975/* static */
5976bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) {
5977 nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
5978 NS_ENSURE_TRUE(baseURI, false)do { if ((__builtin_expect(!!(!(baseURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "baseURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5978); return false; } } while (false)
;
5979 return baseURI->SchemeIs(aScheme);
5980}
5981
5982bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
5983 return aPrincipal && aPrincipal->GetIsExpandedPrincipal();
5984}
5985
5986bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) {
5987 return (aPrincipal && aPrincipal->IsSystemPrincipal()) ||
5988 IsExpandedPrincipal(aPrincipal);
5989}
5990
5991nsIPrincipal* nsContentUtils::GetSystemPrincipal() {
5992 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5993 return sSystemPrincipal;
5994}
5995
5996bool nsContentUtils::CombineResourcePrincipals(
5997 nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) {
5998 if (!aExtraPrincipal) {
5999 return false;
6000 }
6001 if (!*aResourcePrincipal) {
6002 *aResourcePrincipal = aExtraPrincipal;
6003 return true;
6004 }
6005 if (*aResourcePrincipal == aExtraPrincipal) {
6006 return false;
6007 }
6008 bool subsumes;
6009 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
6010 (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
&&
6011 subsumes) {
6012 return false;
6013 }
6014 *aResourcePrincipal = sSystemPrincipal;
6015 return true;
6016}
6017
6018/* static */
6019void nsContentUtils::TriggerLink(nsIContent* aContent, nsIURI* aLinkURI,
6020 const nsString& aTargetSpec, bool aClick) {
6021 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") ("
"No link URI" ")"); do { *((volatile int*)__null) = 6021; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6022
6023 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
6024 return;
6025 }
6026
6027 nsCOMPtr<nsIDocShell> docShell = aContent->OwnerDoc()->GetDocShell();
6028 if (!docShell) {
6029 return;
6030 }
6031
6032 if (!aClick) {
6033 nsDocShell::Cast(docShell)->OnOverLink(aContent, aLinkURI, aTargetSpec);
6034 return;
6035 }
6036
6037 // Check that this page is allowed to load this URI.
6038 nsresult proceed = NS_OK;
6039
6040 if (sSecurityManager) {
6041 uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
6042 proceed = sSecurityManager->CheckLoadURIWithPrincipal(
6043 aContent->NodePrincipal(), aLinkURI, flag,
6044 aContent->OwnerDoc()->InnerWindowID());
6045 }
6046
6047 // Only pass off the click event if the script security manager says it's ok.
6048 // We need to rest aTargetSpec for forced downloads.
6049 if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) {
6050 // A link/area element with a download attribute is allowed to set
6051 // a pseudo Content-Disposition header.
6052 // For security reasons we only allow websites to declare same-origin
6053 // resources as downloadable. If this check fails we will just do the normal
6054 // thing (i.e. navigate to the resource).
6055 nsAutoString fileName;
6056 if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
6057 !aContent->IsHTMLElement(nsGkAtoms::area) &&
6058 !aContent->IsSVGElement(nsGkAtoms::a)) ||
6059 !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) ||
6060 NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal
()->CheckMayLoad(aLinkURI, true))), 0)))
) {
6061 fileName.SetIsVoid(true); // No actionable download attribute was found.
6062 }
6063
6064 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
6065 nsCOMPtr<nsIContentSecurityPolicy> csp = aContent->GetCsp();
6066
6067 // Sanitize fileNames containing null characters by replacing them with
6068 // underscores.
6069 if (!fileName.IsVoid()) {
6070 fileName.ReplaceChar(char16_t(0), '_');
6071 }
6072 nsDocShell::Cast(docShell)->OnLinkClick(
6073 aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName,
6074 nullptr, nullptr, UserActivation::IsHandlingUserInput(),
6075 triggeringPrincipal, csp);
6076 }
6077}
6078
6079/* static */
6080void nsContentUtils::GetLinkLocation(Element* aElement,
6081 nsString& aLocationString) {
6082 nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
6083 if (hrefURI) {
6084 nsAutoCString specUTF8;
6085 nsresult rv = hrefURI->GetSpec(specUTF8);
6086 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString);
6087 }
6088}
6089
6090/* static */
6091nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) {
6092 if (!aWidget) return nullptr;
6093
6094 return aWidget->GetTopLevelWidget();
6095}
6096
6097/* static */
6098const nsDependentString nsContentUtils::GetLocalizedEllipsis() {
6099 static char16_t sBuf[4] = {0, 0, 0, 0};
6100 if (!sBuf[0]) {
6101 if (!SpoofLocaleEnglish()) {
6102 nsAutoString tmp;
6103 Preferences::GetLocalizedString("intl.ellipsis", tmp);
6104 uint32_t len =
6105 std::min(uint32_t(tmp.Length()), uint32_t(std::size(sBuf) - 1));
6106 CopyUnicodeTo(tmp, 0, sBuf, len);
6107 }
6108 if (!sBuf[0]) sBuf[0] = char16_t(0x2026);
6109 }
6110 return nsDependentString(sBuf);
6111}
6112
6113/* static */
6114void nsContentUtils::AddScriptBlocker() {
6115 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6115; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6116 if (!sScriptBlockerCount) {
6117 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { *((volatile
int*)__null) = 6118; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6118 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { *((volatile
int*)__null) = 6118; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6119 sRunnersCountAtFirstBlocker =
6120 sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
6121 }
6122 ++sScriptBlockerCount;
6123}
6124
6125#ifdef DEBUG1
6126static bool sRemovingScriptBlockers = false;
6127#endif
6128
6129/* static */
6130void nsContentUtils::RemoveScriptBlocker() {
6131 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6132 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sRemovingScriptBlockers"
")"); do { *((volatile int*)__null) = 6132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6133 NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers")do { if (!(sScriptBlockerCount != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Negative script blockers", "sScriptBlockerCount != 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6133); MOZ_PretendNoReturn(); } } while (0)
;
6134 --sScriptBlockerCount;
6135 if (sScriptBlockerCount) {
6136 return;
6137 }
6138
6139 if (!sBlockedScriptRunners) {
6140 return;
6141 }
6142
6143 uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
6144 uint32_t lastBlocker = sBlockedScriptRunners->Length();
6145 uint32_t originalFirstBlocker = firstBlocker;
6146 uint32_t blockersCount = lastBlocker - firstBlocker;
6147 sRunnersCountAtFirstBlocker = 0;
6148 NS_ASSERTION(firstBlocker <= lastBlocker, "bad sRunnersCountAtFirstBlocker")do { if (!(firstBlocker <= lastBlocker)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "bad sRunnersCountAtFirstBlocker", "firstBlocker <= lastBlocker"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6148); MOZ_PretendNoReturn(); } } while (0)
;
6149
6150 while (firstBlocker < lastBlocker) {
6151 nsCOMPtr<nsIRunnable> runnable;
6152 runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
6153 ++firstBlocker;
6154
6155 // Calling the runnable can reenter us
6156 {
6157 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
6158 runnable->Run();
6159 }
6160 // So can dropping the reference to the runnable
6161 runnable = nullptr;
6162
6163 NS_ASSERTION(sRunnersCountAtFirstBlocker == 0, "Bad count")do { if (!(sRunnersCountAtFirstBlocker == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Bad count", "sRunnersCountAtFirstBlocker == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6163); MOZ_PretendNoReturn(); } } while (0)
;
6164 NS_ASSERTION(!sScriptBlockerCount, "This is really bad")do { if (!(!sScriptBlockerCount)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This is really bad", "!sScriptBlockerCount", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6164); MOZ_PretendNoReturn(); } } while (0)
;
6165 }
6166#ifdef DEBUG1
6167 AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
6168 sRemovingScriptBlockers = true;
6169#endif
6170 sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
6171}
6172
6173/* static */
6174already_AddRefed<nsPIDOMWindowOuter>
6175nsContentUtils::GetMostRecentNonPBWindow() {
6176 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
6177
6178 nsCOMPtr<mozIDOMWindowProxy> window;
6179 wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window));
6180 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
6181 pwindow = do_QueryInterface(window);
6182
6183 return pwindow.forget();
6184}
6185
6186/* static */
6187void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
6188 nsAutoString msg;
6189 bool privateBrowsing = false;
6190 bool chromeContext = false;
6191
6192 if (aDocument) {
6193 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
6194 if (uri) {
6195 msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
6196 msg.AppendLiteral(" : ");
6197 }
6198 privateBrowsing =
6199 aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
6200 chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal();
6201 }
6202
6203 msg.AppendLiteral(
6204 "Unable to run script because scripts are blocked internally.");
6205 LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext);
6206}
6207
6208/* static */
6209void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) {
6210 nsCOMPtr<nsIRunnable> runnable = aRunnable;
6211 if (!runnable) {
6212 return;
6213 }
6214
6215 if (sScriptBlockerCount) {
6216 sBlockedScriptRunners->AppendElement(runnable.forget());
6217 return;
6218 }
6219
6220 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
6221 runnable->Run();
6222}
6223
6224/* static */
6225void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
6226 nsCOMPtr<nsIRunnable> runnable = aRunnable;
6227 AddScriptRunner(runnable.forget());
6228}
6229
6230/* static */ bool nsContentUtils::IsSafeToRunScript() {
6231 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { *((volatile int*)__null) = 6232; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6232 "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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { *((volatile int*)__null) = 6232; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6233 return sScriptBlockerCount == 0;
6234}
6235
6236/* static */
6237void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) {
6238 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6238; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6239 CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable));
6240}
6241
6242/* static */
6243void nsContentUtils::AddPendingIDBTransaction(
6244 already_AddRefed<nsIRunnable> aTransaction) {
6245 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6246 CycleCollectedJSContext::Get()->AddPendingIDBTransaction(
6247 std::move(aTransaction));
6248}
6249
6250/* static */
6251bool nsContentUtils::IsInStableOrMetaStableState() {
6252 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6252); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6252; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6253 return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
6254}
6255
6256/* static */
6257void nsContentUtils::HidePopupsInDocument(Document* aDocument) {
6258 RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance();
6259 if (!pm || !aDocument) {
6260 return;
6261 }
6262 nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
6263 if (docShellToHide) {
6264 pm->HidePopupsInDocShell(docShellToHide);
6265 }
6266}
6267
6268/* static */
6269already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
6270 nsIWidget* aWidget) {
6271 nsCOMPtr<nsIDragSession> dragSession;
6272 nsCOMPtr<nsIDragService> dragService =
6273 do_GetService("@mozilla.org/widget/dragservice;1");
6274 if (dragService) {
6275 dragSession = dragService->GetCurrentSession(aWidget);
6276 }
6277 return dragSession.forget();
6278}
6279
6280/* static */
6281already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
6282 nsPresContext* aPC) {
6283 NS_ENSURE_TRUE(aPC, nullptr)do { if ((__builtin_expect(!!(!(aPC)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "aPC" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6283); return nullptr; } } while (false)
;
6284 auto* widget = aPC->GetRootWidget();
6285 if (!widget) {
6286 return nullptr;
6287 }
6288 return GetDragSession(widget);
6289}
6290
6291/* static */
6292nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) {
6293 if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
6294 return NS_OK;
6295 }
6296
6297 // For dragstart events, the data transfer object is
6298 // created before the event fires, so it should already be set. For other
6299 // drag events, get the object from the drag session.
6300 NS_ASSERTION(aDragEvent->mMessage != eDragStart,do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer"
, "aDragEvent->mMessage != eDragStart", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6301); MOZ_PretendNoReturn(); } } while (0)
6301 "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6301); MOZ_PretendNoReturn(); } } while (0)
;
6302
6303 nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget);
6304 NS_ENSURE_TRUE(dragSession, NS_OK)do { if ((__builtin_expect(!!(!(dragSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "dragSession" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6304); return NS_OK; } } while (false)
; // no drag in progress
6305
6306 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
6307 if (!initialDataTransfer) {
6308 // A dataTransfer won't exist when a drag was started by some other
6309 // means, for instance calling the drag service directly, or a drag
6310 // from another application. In either case, a new dataTransfer should
6311 // be created that reflects the data.
6312 initialDataTransfer = new DataTransfer(
6313 aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing());
6314
6315 // now set it in the drag session so we don't need to create it again
6316 dragSession->SetDataTransfer(initialDataTransfer);
6317 }
6318
6319 bool isCrossDomainSubFrameDrop = false;
6320 if (aDragEvent->mMessage == eDrop) {
6321 isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
6322 }
6323
6324 // each event should use a clone of the original dataTransfer.
6325 initialDataTransfer->Clone(
6326 aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled,
6327 isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer));
6328 if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6328)
) {
6329 return NS_ERROR_OUT_OF_MEMORY;
6330 }
6331
6332 // for the dragenter and dragover events, initialize the drop effect
6333 // from the drop action, which platform specific widget code sets before
6334 // the event is fired based on the keyboard state.
6335 if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
6336 uint32_t action;
6337 dragSession->GetDragAction(&action);
6338 uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt();
6339 aDragEvent->mDataTransfer->SetDropEffectInt(
6340 FilterDropEffect(action, effectAllowed));
6341 } else if (aDragEvent->mMessage == eDrop ||
6342 aDragEvent->mMessage == eDragEnd) {
6343 // For the drop and dragend events, set the drop effect based on the
6344 // last value that the dropEffect had. This will have been set in
6345 // EventStateManager::PostHandleEvent for the last dragenter or
6346 // dragover event.
6347 aDragEvent->mDataTransfer->SetDropEffectInt(
6348 initialDataTransfer->DropEffectInt());
6349 }
6350
6351 return NS_OK;
6352}
6353
6354/* static */
6355uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction,
6356 uint32_t aEffectAllowed) {
6357 // It is possible for the drag action to include more than one action, but
6358 // the widget code which sets the action from the keyboard state should only
6359 // be including one. If multiple actions were set, we just consider them in
6360 // the following order:
6361 // copy, link, move
6362 if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
6363 aAction = nsIDragService::DRAGDROP_ACTION_COPY;
6364 else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
6365 aAction = nsIDragService::DRAGDROP_ACTION_LINK;
6366 else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
6367 aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
6368
6369 // Filter the action based on the effectAllowed. If the effectAllowed
6370 // doesn't include the action, then that action cannot be done, so adjust
6371 // the action to something that is allowed. For a copy, adjust to move or
6372 // link. For a move, adjust to copy or link. For a link, adjust to move or
6373 // link. Otherwise, use none.
6374 if (aAction & aEffectAllowed ||
6375 aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
6376 return aAction;
6377 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
6378 return nsIDragService::DRAGDROP_ACTION_MOVE;
6379 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
6380 return nsIDragService::DRAGDROP_ACTION_COPY;
6381 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
6382 return nsIDragService::DRAGDROP_ACTION_LINK;
6383 return nsIDragService::DRAGDROP_ACTION_NONE;
6384}
6385
6386/* static */
6387bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
6388 WidgetDragEvent* aDropEvent) {
6389 nsCOMPtr<nsIContent> target =
6390 nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget);
6391 if (!target) {
6392 return true;
6393 }
6394
6395 // Always allow dropping onto chrome shells.
6396 BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext();
6397 if (targetBC->IsChrome()) {
6398 return false;
6399 }
6400
6401 WindowContext* targetWC = target->OwnerDoc()->GetWindowContext();
6402
6403 // If there is no source browsing context, then this is a drag from another
6404 // application, which should be allowed.
6405 RefPtr<WindowContext> sourceWC;
6406 aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
6407 if (sourceWC) {
6408 // Get each successive parent of the source document and compare it to
6409 // the drop document. If they match, then this is a drag from a child frame.
6410 for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC;
6411 sourceWC = sourceWC->GetParentWindowContext()) {
6412 // If the source and the target match, then the drag started in a
6413 // descendant frame. If the source is discarded, err on the side of
6414 // caution and treat it as a subframe drag.
6415 if (sourceWC == targetWC || sourceWC->IsDiscarded()) {
6416 return true;
6417 }
6418 }
6419 }
6420
6421 return false;
6422}
6423
6424/* static */
6425bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) {
6426 bool isFile;
6427 nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service();
6428
6429 // Important: we do NOT test the entire URI chain here!
6430 return util &&
6431 NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
6432 aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
&&
6433 isFile;
6434}
6435
6436/* static */
6437JSContext* nsContentUtils::GetCurrentJSContext() {
6438 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 6438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6439 if (!IsJSAPIActive()) {
6440 return nullptr;
6441 }
6442 return danger::GetJSContext();
6443}
6444
6445template <typename StringType, typename CharType>
6446void _ASCIIToLowerInSitu(StringType& aStr) {
6447 CharType* iter = aStr.BeginWriting();
6448 CharType* end = aStr.EndWriting();
6449 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end"
")"); do { *((volatile int*)__null) = 6449; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6450
6451 while (iter != end) {
6452 CharType c = *iter;
6453 if (c >= 'A' && c <= 'Z') {
6454 *iter = c + ('a' - 'A');
6455 }
6456 ++iter;
6457 }
6458}
6459
6460/* static */
6461void nsContentUtils::ASCIIToLower(nsAString& aStr) {
6462 return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
6463}
6464
6465/* static */
6466void nsContentUtils::ASCIIToLower(nsACString& aStr) {
6467 return _ASCIIToLowerInSitu<nsACString, char>(aStr);
6468}
6469
6470template <typename StringType, typename CharType>
6471void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) {
6472 uint32_t len = aSource.Length();
6473 aDest.SetLength(len);
6474 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len"
")"); do { *((volatile int*)__null) = 6474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6475
6476 CharType* dest = aDest.BeginWriting();
6477 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { *((volatile int*)__null) = 6477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6478
6479 const CharType* iter = aSource.BeginReading();
6480 const CharType* end = aSource.EndReading();
6481 while (iter != end) {
6482 CharType c = *iter;
6483 *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
6484 ++iter;
6485 ++dest;
6486 }
6487}
6488
6489/* static */
6490void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
6491 return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
6492}
6493
6494/* static */
6495void nsContentUtils::ASCIIToLower(const nsACString& aSource,
6496 nsACString& aDest) {
6497 return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
6498}
6499
6500template <typename StringType, typename CharType>
6501void _ASCIIToUpperInSitu(StringType& aStr) {
6502 CharType* iter = aStr.BeginWriting();
6503 CharType* end = aStr.EndWriting();
6504 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6504); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end"
")"); do { *((volatile int*)__null) = 6504; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6505
6506 while (iter != end) {
6507 CharType c = *iter;
6508 if (c >= 'a' && c <= 'z') {
6509 *iter = c + ('A' - 'a');
6510 }
6511 ++iter;
6512 }
6513}
6514
6515/* static */
6516void nsContentUtils::ASCIIToUpper(nsAString& aStr) {
6517 return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
6518}
6519
6520/* static */
6521void nsContentUtils::ASCIIToUpper(nsACString& aStr) {
6522 return _ASCIIToUpperInSitu<nsACString, char>(aStr);
6523}
6524
6525template <typename StringType, typename CharType>
6526void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) {
6527 uint32_t len = aSource.Length();
6528 aDest.SetLength(len);
6529 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len"
")"); do { *((volatile int*)__null) = 6529; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6530
6531 CharType* dest = aDest.BeginWriting();
6532 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { *((volatile int*)__null) = 6532; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6533
6534 const CharType* iter = aSource.BeginReading();
6535 const CharType* end = aSource.EndReading();
6536 while (iter != end) {
6537 CharType c = *iter;
6538 *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c;
6539 ++iter;
6540 ++dest;
6541 }
6542}
6543
6544/* static */
6545void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) {
6546 return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
6547}
6548
6549/* static */
6550void nsContentUtils::ASCIIToUpper(const nsACString& aSource,
6551 nsACString& aDest) {
6552 return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
6553}
6554
6555/* static */
6556bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) {
6557 if (aAtom1 == aAtom2) {
6558 return true;
6559 }
6560
6561 // If both are ascii lowercase already, we know that the slow comparison
6562 // below is going to return false.
6563 if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) {
6564 return false;
6565 }
6566
6567 return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1),
6568 nsDependentAtomString(aAtom2));
6569}
6570
6571/* static */
6572bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
6573 const nsAString& aStr2) {
6574 uint32_t len = aStr1.Length();
6575 if (len != aStr2.Length()) {
6576 return false;
6577 }
6578
6579 const char16_t* str1 = aStr1.BeginReading();
6580 const char16_t* str2 = aStr2.BeginReading();
6581 const char16_t* end = str1 + len;
6582
6583 while (str1 < end) {
6584 char16_t c1 = *str1++;
6585 char16_t c2 = *str2++;
6586
6587 // First check if any bits other than the 0x0020 differs
6588 if ((c1 ^ c2) & 0xffdf) {
6589 return false;
6590 }
6591
6592 // We know they can only differ in the 0x0020 bit.
6593 // Likely the two chars are the same, so check that first
6594 if (c1 != c2) {
6595 // They do differ, but since it's only in the 0x0020 bit, check if it's
6596 // the same ascii char, but just differing in case
6597 char16_t c1Upper = c1 & 0xffdf;
6598 if (!('A' <= c1Upper && c1Upper <= 'Z')) {
6599 return false;
6600 }
6601 }
6602 }
6603
6604 return true;
6605}
6606
6607/* static */
6608bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) {
6609 const char16_t* iter = aStr.BeginReading();
6610 const char16_t* end = aStr.EndReading();
6611 while (iter != end) {
6612 char16_t c = *iter;
6613 if (c >= 'A' && c <= 'Z') {
6614 return true;
6615 }
6616 ++iter;
6617 }
6618
6619 return false;
6620}
6621
6622/* static */
6623nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() {
6624 if (!sSameOriginChecker) {
6625 sSameOriginChecker = new SameOriginCheckerImpl();
6626 NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef();
6627 }
6628 return sSameOriginChecker;
6629}
6630
6631/* static */
6632nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel,
6633 nsIChannel* aNewChannel) {
6634 if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE;
6635
6636 nsCOMPtr<nsIPrincipal> oldPrincipal;
6637 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
6638 aOldChannel, getter_AddRefs(oldPrincipal));
6639
6640 nsCOMPtr<nsIURI> newURI;
6641 aNewChannel->GetURI(getter_AddRefs(newURI));
6642 nsCOMPtr<nsIURI> newOriginalURI;
6643 aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
6644
6645 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6645); return NS_ERROR_UNEXPECTED; } } while (false)
;
6646
6647 nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
6648 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) {
6649 rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
6650 }
6651
6652 return rv;
6653}
6654
6655NS_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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
6656; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6656; __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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 6656
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6656; __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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); 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; }
6656 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
6656; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6656; __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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 6656
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6656; __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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6656); 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; }
6657
6658NS_IMETHODIMPnsresult
6659SameOriginCheckerImpl::AsyncOnChannelRedirect(
6660 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
6661 nsIAsyncVerifyRedirectCallback* cb) {
6662 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6662); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel"
") (" "Redirecting to null channel?" ")"); do { *((volatile int
*)__null) = 6662; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6663
6664 nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
6665 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6666 cb->OnRedirectVerifyCallback(NS_OK);
6667 }
6668
6669 return rv;
6670}
6671
6672NS_IMETHODIMPnsresult
6673SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) {
6674 return QueryInterface(aIID, aResult);
6675}
6676
6677/* static */
6678nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
6679 nsACString& aOrigin) {
6680 nsresult rv;
6681 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { *((volatile int*)__null) = 6681; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6682
6683 // For Blob URI, the path is the URL of the owning page.
6684 if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) {
6685 nsAutoCString path;
6686 rv = aURI->GetPathQueryRef(path);
6687 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6687); return rv; } } while (false)
;
6688
6689 nsCOMPtr<nsIURI> uri;
6690 rv = NS_NewURI(getter_AddRefs(uri), path);
6691 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6692 aOrigin.AssignLiteral("null");
6693 return NS_OK;
6694 }
6695
6696 if (
6697 // Schemes in spec. https://url.spec.whatwg.org/#origin
6698 !uri->SchemeIs("http") && !uri->SchemeIs("https") &&
6699 !uri->SchemeIs("file") && !uri->SchemeIs("resource") &&
6700 // Our own schemes.
6701 !uri->SchemeIs("moz-extension")) {
6702 aOrigin.AssignLiteral("null");
6703 return NS_OK;
6704 }
6705
6706 return GetWebExposedOriginSerialization(uri, aOrigin);
6707 }
6708
6709 nsAutoCString scheme;
6710 aURI->GetScheme(scheme);
6711
6712 // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then
6713 // return "null" as the origin serialization.
6714 // We make an exception for "ftp" since we don't have a protocol handler
6715 // for this scheme
6716 uint32_t flags = 0;
6717 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
6718 if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
6719 NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
6720 if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) {
6721 aOrigin.AssignLiteral("null");
6722 return NS_OK;
6723 }
6724 }
6725
6726 aOrigin.Truncate();
6727
6728 nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
6729 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(uri)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "uri" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6729); return NS_ERROR_UNEXPECTED; } } while (false)
;
6730
6731 nsAutoCString host;
6732 rv = uri->GetAsciiHost(host);
6733
6734 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) {
6735 nsAutoCString userPass;
6736 uri->GetUserPass(userPass);
6737
6738 nsAutoCString prePath;
6739 if (!userPass.IsEmpty()) {
6740 rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri);
6741 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6741); return rv; } } while (false)
;
6742 }
6743
6744 rv = uri->GetPrePath(prePath);
6745 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6745); return rv; } } while (false)
;
6746
6747 aOrigin = prePath;
6748 } else {
6749 aOrigin.AssignLiteral("null");
6750 }
6751
6752 return NS_OK;
6753}
6754
6755/* static */
6756nsresult nsContentUtils::GetWebExposedOriginSerialization(
6757 nsIPrincipal* aPrincipal, nsAString& aOrigin) {
6758 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
") (" "missing principal" ")"); do { *((volatile int*)__null
) = 6758; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
6759
6760 aOrigin.Truncate();
6761 nsAutoCString webExposedOriginSerialization;
6762
6763 nsresult rv = aPrincipal->GetWebExposedOriginSerialization(
6764 webExposedOriginSerialization);
6765 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6766 webExposedOriginSerialization.AssignLiteral("null");
6767 }
6768
6769 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
6770 return NS_OK;
6771}
6772
6773/* static */
6774nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
6775 nsAString& aOrigin) {
6776 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { *((volatile int*)__null) = 6776; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6777 nsresult rv;
6778
6779#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
6780 // Check if either URI has a special origin.
6781 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
6782 do_QueryInterface(aURI);
6783 if (uriWithSpecialOrigin) {
6784 nsCOMPtr<nsIURI> origin;
6785 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
6786 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6786); return rv; } } while (false)
;
6787
6788 return GetWebExposedOriginSerialization(origin, aOrigin);
6789 }
6790#endif
6791
6792 nsAutoCString webExposedOriginSerialization;
6793 rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization);
6794 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6794); return rv; } } while (false)
;
6795
6796 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
6797 return NS_OK;
6798}
6799
6800/* static */
6801bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
6802 nsIChannel* aChannel,
6803 bool aAllowIfInheritsPrincipal) {
6804 nsCOMPtr<nsIURI> channelURI;
6805 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
6806 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6806); return false; } } while (false)
;
6807
6808 return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
6809 aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
;
6810}
6811
6812/* static */
6813bool nsContentUtils::CanAccessNativeAnon() {
6814 return LegacyIsCallerChromeOrNativeCode();
6815}
6816
6817/* static */
6818nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted,
6819 Event* aSourceEvent,
6820 PresShell* aPresShell, bool aCtrl,
6821 bool aAlt, bool aShift, bool aMeta,
6822 uint16_t aInputSource,
6823 int16_t aButton) {
6824 NS_ENSURE_STATE(aTarget)do { if ((__builtin_expect(!!(!(aTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTarget" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6824); return NS_ERROR_UNEXPECTED; } } while (false)
;
6825 Document* doc = aTarget->OwnerDoc();
6826 nsPresContext* presContext = doc->GetPresContext();
6827
6828 RefPtr<XULCommandEvent> xulCommand =
6829 new XULCommandEvent(doc, presContext, nullptr);
6830 xulCommand->InitCommandEvent(u"command"_ns, true, true,
6831 nsGlobalWindowInner::Cast(doc->GetInnerWindow()),
6832 0, aCtrl, aAlt, aShift, aMeta, aButton,
6833 aSourceEvent, aInputSource, IgnoreErrors());
6834
6835 if (aPresShell) {
6836 nsEventStatus status = nsEventStatus_eIgnore;
6837 return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
6838 }
6839
6840 ErrorResult rv;
6841 aTarget->DispatchEvent(*xulCommand, rv);
6842 return rv.StealNSResult();
6843}
6844
6845// static
6846nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native,
6847 nsWrapperCache* cache, const nsIID* aIID,
6848 JS::MutableHandle<JS::Value> vp,
6849 bool aAllowWrapping) {
6850 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()"
")"); do { *((volatile int*)__null) = 6850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6851
6852 if (!native) {
6853 vp.setNull();
6854
6855 return NS_OK;
6856 }
6857
6858 JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
6859 if (wrapper) {
6860 return NS_OK;
6861 }
6862
6863 NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(sXPConnect)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sXPConnect" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6863); return NS_ERROR_UNEXPECTED; } } while (false)
;
6864
6865 if (!NS_IsMainThread()) {
6866 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6866); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 6866; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
6867 }
6868
6869 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
6870 nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
6871 aAllowWrapping, vp);
6872 return rv;
6873}
6874
6875void nsContentUtils::StripNullChars(const nsAString& aInStr,
6876 nsAString& aOutStr) {
6877 // In common cases where we don't have nulls in the
6878 // string we can simple simply bypass the checking code.
6879 int32_t firstNullPos = aInStr.FindChar('\0');
6880 if (firstNullPos == kNotFound) {
6881 aOutStr.Assign(aInStr);
6882 return;
6883 }
6884
6885 aOutStr.SetCapacity(aInStr.Length() - 1);
6886 nsAString::const_iterator start, end;
6887 aInStr.BeginReading(start);
6888 aInStr.EndReading(end);
6889 while (start != end) {
6890 if (*start != '\0') aOutStr.Append(*start);
6891 ++start;
6892 }
6893}
6894
6895struct ClassMatchingInfo {
6896 AtomArray mClasses;
6897 nsCaseTreatment mCaseTreatment;
6898};
6899
6900// static
6901bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
6902 nsAtom* aAtom, void* aData) {
6903 // We can't match if there are no class names
6904 const nsAttrValue* classAttr = aElement->GetClasses();
6905 if (!classAttr) {
6906 return false;
6907 }
6908
6909 // need to match *all* of the classes
6910 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
6911 uint32_t length = info->mClasses.Length();
6912 if (!length) {
6913 // If we actually had no classes, don't match.
6914 return false;
6915 }
6916 uint32_t i;
6917 for (i = 0; i < length; ++i) {
6918 if (!classAttr->Contains(info->mClasses[i], info->mCaseTreatment)) {
6919 return false;
6920 }
6921 }
6922
6923 return true;
6924}
6925
6926// static
6927void nsContentUtils::DestroyClassNameArray(void* aData) {
6928 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
6929 delete info;
6930}
6931
6932// static
6933void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
6934 const nsString* aClasses) {
6935 nsAttrValue attrValue;
6936 attrValue.ParseAtomArray(*aClasses);
6937 // nsAttrValue::Equals is sensitive to order, so we'll send an array
6938 auto* info = new ClassMatchingInfo;
6939 if (attrValue.Type() == nsAttrValue::eAtomArray) {
6940 info->mClasses = attrValue.GetAtomArrayValue()->mArray.Clone();
6941 } else if (attrValue.Type() == nsAttrValue::eAtom) {
6942 info->mClasses.AppendElement(attrValue.GetAtomValue());
6943 }
6944
6945 info->mCaseTreatment =
6946 aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
6947 ? eIgnoreCase
6948 : eCaseMatters;
6949 return info;
6950}
6951
6952void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
6953 if (!aWindow) {
6954 return;
6955 }
6956
6957 // Note that because FlushPendingNotifications flushes parents, this
6958 // is O(N^2) in docshell tree depth. However, the docshell tree is
6959 // usually pretty shallow.
6960
6961 if (RefPtr<Document> doc = aWindow->GetDoc()) {
6962 doc->FlushPendingNotifications(FlushType::Layout);
6963 }
6964
6965 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
6966 int32_t i = 0, i_end;
6967 docShell->GetInProcessChildCount(&i_end);
6968 for (; i < i_end; ++i) {
6969 nsCOMPtr<nsIDocShellTreeItem> item;
6970 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
6971 item) {
6972 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
6973 FlushLayoutForTree(win);
6974 }
6975 }
6976 }
6977 }
6978}
6979
6980void nsContentUtils::RemoveNewlines(nsString& aString) { aString.StripCRLF(); }
6981
6982void nsContentUtils::PlatformToDOMLineBreaks(nsString& aString) {
6983 if (!PlatformToDOMLineBreaks(aString, fallible)) {
6984 aString.AllocFailed(aString.Length());
6985 }
6986}
6987
6988bool nsContentUtils::PlatformToDOMLineBreaks(nsString& aString,
6989 const fallible_t& aFallible) {
6990 if (aString.FindChar(char16_t('\r')) != -1) {
6991 // Windows linebreaks: Map CRLF to LF:
6992 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
6993 return false;
6994 }
6995
6996 // Mac linebreaks: Map any remaining CR to LF:
6997 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
6998 return false;
6999 }
7000 }
7001
7002 return true;
7003}
7004
7005already_AddRefed<nsContentList> nsContentUtils::GetElementsByClassName(
7006 nsINode* aRootNode, const nsAString& aClasses) {
7007 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") ("
"Must have root node" ")"); do { *((volatile int*)__null) = 7007
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7008
7009 return GetFuncStringContentList<nsCacheableFuncStringHTMLCollection>(
7010 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
7011 aClasses);
7012}
7013
7014PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
7015 const Document* doc = aDocument;
7016 Document* displayDoc = doc->GetDisplayDocument();
7017 if (displayDoc) {
7018 doc = displayDoc;
7019 }
7020
7021 PresShell* presShell = doc->GetPresShell();
7022 if (presShell) {
7023 return presShell;
7024 }
7025
7026 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
7027 while (docShellTreeItem) {
7028 // We may be in a display:none subdocument, or we may not have a presshell
7029 // created yet.
7030 // Walk the docshell tree to find the nearest container that has a
7031 // presshell, and return that.
7032 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
7033 if (PresShell* presShell = docShell->GetPresShell()) {
7034 return presShell;
7035 }
7036 nsCOMPtr<nsIDocShellTreeItem> parent;
7037 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
7038 docShellTreeItem = parent;
7039 }
7040
7041 return nullptr;
7042}
7043
7044/* static */
7045nsPresContext* nsContentUtils::FindPresContextForDocument(
7046 const Document* aDocument) {
7047 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
7048 return presShell->GetPresContext();
7049 }
7050 return nullptr;
7051}
7052
7053nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
7054 PresShell* presShell = FindPresShellForDocument(aDocument);
7055 if (!presShell) {
7056 return nullptr;
7057 }
7058 nsViewManager* vm = presShell->GetViewManager();
7059 if (!vm) {
7060 return nullptr;
7061 }
7062 nsView* rootView = vm->GetRootView();
7063 if (!rootView) {
7064 return nullptr;
7065 }
7066 nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView);
7067 if (!displayRoot) {
7068 return nullptr;
7069 }
7070 return displayRoot->GetNearestWidget(nullptr);
7071}
7072
7073nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
7074 nsIFrame* frame = aContent->GetPrimaryFrame();
7075 if (frame) {
7076 frame = nsLayoutUtils::GetDisplayRootFrame(frame);
7077
7078 nsView* view = frame->GetView();
7079 if (view) {
7080 return view->GetWidget();
7081 }
7082 }
7083
7084 return nullptr;
7085}
7086
7087WindowRenderer* nsContentUtils::WindowRendererForContent(
7088 const nsIContent* aContent) {
7089 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
7090 if (widget) {
7091 return widget->GetWindowRenderer();
7092 }
7093
7094 return nullptr;
7095}
7096
7097WindowRenderer* nsContentUtils::WindowRendererForDocument(
7098 const Document* aDoc) {
7099 nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc);
7100 if (widget) {
7101 return widget->GetWindowRenderer();
7102 }
7103
7104 return nullptr;
7105}
7106
7107bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
7108 if (!aPrincipal) {
7109 return false;
7110 }
7111
7112 if (aPrincipal->IsSystemPrincipal()) {
7113 return true;
7114 }
7115
7116 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
7117}
7118
7119bool nsContentUtils::IsPDFJSEnabled() {
7120 nsCOMPtr<nsIStreamConverter> conv = do_CreateInstance(
7121 "@mozilla.org/streamconv;1?from=application/pdf&to=text/html");
7122 return conv;
7123}
7124
7125bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
7126 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
7127 return false;
7128 }
7129 nsAutoCString spec;
7130 nsresult rv = aPrincipal->GetAsciiSpec(spec);
7131 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7131); return false; } } while (false)
;
7132 return spec.EqualsLiteral("resource://pdf.js/web/viewer.html");
7133}
7134
7135bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
7136 nsIPrincipal* principal = SubjectPrincipal(aCx);
7137 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
7138}
7139
7140bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
7141 JSObject* aGlobal) {
7142 nsIPrincipal* principal = SubjectPrincipal(aCx);
7143 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
7144 aGlobal) ||
7145 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
7146}
7147
7148already_AddRefed<nsIDocumentLoaderFactory>
7149nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
7150 DocumentViewerType* aLoaderType) {
7151 if (aLoaderType) {
7152 *aLoaderType = TYPE_UNSUPPORTED;
7153 }
7154
7155 // one helper factory, please
7156 nsCOMPtr<nsICategoryManager> catMan(
7157 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
7158 if (!catMan) return nullptr;
7159
7160 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
7161
7162 nsCString contractID;
7163 nsresult rv =
7164 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
7165 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7166 docFactory = do_GetService(contractID.get());
7167 if (docFactory && aLoaderType) {
7168 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
7169 *aLoaderType = TYPE_CONTENT;
7170 else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID"@mozilla.org/content/plugin/document-loader-factory;1"))
7171 *aLoaderType = TYPE_FALLBACK;
7172 else
7173 *aLoaderType = TYPE_UNKNOWN;
7174 }
7175 return docFactory.forget();
7176 }
7177
7178 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
7179 // another type which we may dynamically support, such as `text/*` types or
7180 // video document types. These types are all backed by the nsContentDLF.
7181 if (IsPlainTextType(aType) ||
7182 DecoderTraits::IsSupportedInVideoDocument(aType)) {
7183 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
7184 if (docFactory && aLoaderType) {
7185 *aLoaderType = TYPE_CONTENT;
7186 }
7187 return docFactory.forget();
7188 }
7189
7190 return nullptr;
7191}
7192
7193static void ReportPatternCompileFailure(nsAString& aPattern,
7194 const JS::RegExpFlags& aFlags,
7195 const Document* aDocument,
7196 JS::MutableHandle<JS::Value> error,
7197 JSContext* cx) {
7198 AutoTArray<nsString, 3> strings;
7199
7200 strings.AppendElement(aPattern);
7201
7202 std::stringstream flag_ss;
7203 flag_ss << aFlags;
7204 nsString* flagstr = strings.AppendElement();
7205 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
7206
7207 JS::AutoSaveExceptionState savedExc(cx);
7208 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
7209 JS::Rooted<JS::Value> messageVal(cx);
7210 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
7211 return;
7212 }
7213 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
7214 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { *((volatile int*)__null) = 7214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7215 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
7216 return;
7217 }
7218
7219 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
7220 aDocument, nsContentUtils::eDOM_PROPERTIES,
7221 "PatternAttributeCompileFailurev2", strings);
7222 savedExc.drop();
7223}
7224
7225// static
7226Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
7227 nsString&& aPattern,
7228 const Document* aDocument,
7229 bool aHasMultiple,
7230 JS::RegExpFlags aFlags) {
7231 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7231); MOZ_PretendNoReturn(); } } while (0)
;
7232
7233 // The fact that we're using a JS regexp under the hood should not be visible
7234 // to things like window onerror handlers, so we don't initialize our JSAPI
7235 // with the document's window (which may not exist anyway).
7236 AutoJSAPI jsapi;
7237 jsapi.Init();
7238 JSContext* cx = jsapi.cx();
7239 AutoDisableJSInterruptCallback disabler(cx);
7240
7241 // We can use the junk scope here, because we're just using it for regexp
7242 // evaluation, not actual script execution, and we disable statics so that the
7243 // evaluation does not interact with the execution global.
7244 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
7245
7246 // Check if the pattern by itself is valid first, and not that it only becomes
7247 // valid once we add ^(?: and )$.
7248 JS::Rooted<JS::Value> error(cx);
7249 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
7250 aFlags, &error)) {
7251 return Nothing();
7252 }
7253
7254 if (!error.isUndefined()) {
7255 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
7256 return Some(true);
7257 }
7258
7259 // The pattern has to match the entire value.
7260 aPattern.InsertLiteral(u"^(?:", 0);
7261 aPattern.AppendLiteral(")$");
7262
7263 JS::Rooted<JSObject*> re(
7264 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
7265 aFlags));
7266 if (!re) {
7267 return Nothing();
7268 }
7269
7270 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
7271 if (!aHasMultiple) {
7272 size_t idx = 0;
7273 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
7274 aValue.Length(), &idx, true, &rval)) {
7275 return Nothing();
7276 }
7277 return Some(!rval.isNull());
7278 }
7279
7280 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
7281 while (tokenizer.hasMoreTokens()) {
7282 const nsAString& value = tokenizer.nextToken();
7283 size_t idx = 0;
7284 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
7285 value.Length(), &idx, true, &rval)) {
7286 return Nothing();
7287 }
7288 if (rval.isNull()) {
7289 return Some(false);
7290 }
7291 }
7292 return Some(true);
7293}
7294
7295// static
7296nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
7297 bool* aResult) {
7298 // Note: about:blank URIs do NOT inherit the security context from the
7299 // current document, which is what this function tests for...
7300 return NS_URIChainHasFlags(
7301 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
7302}
7303
7304// static
7305bool nsContentUtils::ChannelShouldInheritPrincipal(
7306 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
7307 bool aForceInherit) {
7308 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7309; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7309 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7309; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7310
7311 // Only tell the channel to inherit if it can't provide its own security
7312 // context.
7313 //
7314 // XXX: If this is ever changed, check all callers for what owners
7315 // they're passing in. In particular, see the code and
7316 // comments in nsDocShell::LoadURI where we fall back on
7317 // inheriting the owner if called from chrome. That would be
7318 // very wrong if this code changed anything but channels that
7319 // can't provide their own security context!
7320 //
7321 // If aForceInherit is true, we will inherit, even for a channel that
7322 // can provide its own security context. This is used for srcdoc loads.
7323 bool inherit = aForceInherit;
7324 if (!inherit) {
7325 bool uriInherits;
7326 // We expect URIInheritsSecurityContext to return success for an
7327 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
7328 // This condition needs to match the one in nsDocShell::InternalLoad where
7329 // we're checking for things that will use the owner.
7330 inherit =
7331 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
7332 (uriInherits || (aInheritForAboutBlank &&
7333 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
7334 //
7335 // file: uri special-casing
7336 //
7337 // If this is a file: load opened from another file: then it may need
7338 // to inherit the owner from the referrer so they can script each other.
7339 // If we don't set the owner explicitly then each file: gets an owner
7340 // based on its own codebase later.
7341 //
7342 (URIIsLocalFile(aURI) &&
7343 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
7344 // One more check here. CheckMayLoad will always return true for the
7345 // system principal, but we do NOT want to inherit in that case.
7346 !aLoadingPrincipal->IsSystemPrincipal());
7347 }
7348 return inherit;
7349}
7350
7351/* static */
7352bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
7353 nsIPrincipal& aSubjectPrincipal) {
7354 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
7355 aDocument->HasValidTransientUserGestureActivation()) {
7356 return true;
7357 }
7358
7359 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
7360}
7361
7362/* static */
7363bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
7364 if (!aDoc1 || !aDoc2) {
7365 return false;
7366 }
7367 bool principalsEqual = false;
7368 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
7369 return principalsEqual;
7370}
7371
7372/* static */
7373void nsContentUtils::FireMutationEventsForDirectParsing(
7374 Document* aDoc, nsIContent* aDest, int32_t aOldChildCount) {
7375 // Fire mutation events. Optimize for the case when there are no listeners
7376 int32_t newChildCount = aDest->GetChildCount();
7377 if (newChildCount && nsContentUtils::HasMutationListeners(
7378 aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED0x02)) {
7379 AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
7380 NS_ASSERTION(newChildCount - aOldChildCount >= 0,do { if (!(newChildCount - aOldChildCount >= 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "What, some unexpected dom mutation has happened?"
, "newChildCount - aOldChildCount >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7381); MOZ_PretendNoReturn(); } } while (0)
7381 "What, some unexpected dom mutation has happened?")do { if (!(newChildCount - aOldChildCount >= 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "What, some unexpected dom mutation has happened?"
, "newChildCount - aOldChildCount >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7381); MOZ_PretendNoReturn(); } } while (0)
;
7382 childNodes.SetCapacity(newChildCount - aOldChildCount);
7383 for (nsIContent* child = aDest->GetFirstChild(); child;
7384 child = child->GetNextSibling()) {
7385 childNodes.AppendElement(child);
7386 }
7387 FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes);
7388 }
7389}
7390
7391/* static */
7392const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
7393 const Document* aDoc) {
7394 if (!aDoc) {
7395 return nullptr;
7396 }
7397 const Document* doc = aDoc;
7398 while (doc->GetInProcessParentDocument()) {
7399 doc = doc->GetInProcessParentDocument();
7400 }
7401 return doc;
7402}
7403
7404// static
7405int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
7406 int32_t aOffset) {
7407 // The structure of the anonymous frames within a text control frame is
7408 // an optional block frame, followed by an optional br frame.
7409
7410 // If the offset frame has a child, then this frame is the block which
7411 // has the text frames (containing the content) as its children. This will
7412 // be the case if we click to the right of any of the text frames, or at the
7413 // bottom of the text area.
7414 nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
7415 if (firstChild) {
7416 // In this case, the passed-in offset is incorrect, and we want the length
7417 // of the entire content in the text control frame.
7418 return firstChild->GetContent()->Length();
7419 }
7420
7421 if (aOffsetFrame->GetPrevSibling() && !aOffsetFrame->GetNextSibling()) {
7422 // In this case, we're actually within the last frame, which is a br
7423 // frame. Our offset should therefore be the length of the first child of
7424 // our parent.
7425 int32_t aOutOffset = aOffsetFrame->GetParent()
7426 ->PrincipalChildList()
7427 .FirstChild()
7428 ->GetContent()
7429 ->Length();
7430 return aOutOffset;
7431 }
7432
7433 // Otherwise, we're within one of the text frames, in which case our offset
7434 // has already been correctly calculated.
7435 return aOffset;
7436}
7437
7438// static
7439bool nsContentUtils::IsPointInSelection(
7440 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
7441 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
7442 const bool selectionIsCollapsed =
7443 !aAllowCrossShadowBoundary
7444 ? aSelection.IsCollapsed()
7445 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
7446 if (selectionIsCollapsed) {
7447 return false;
7448 }
7449
7450 const uint32_t rangeCount = aSelection.RangeCount();
7451 for (const uint32_t i : IntegerRange(rangeCount)) {
7452 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount"
")"); do { *((volatile int*)__null) = 7452; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7453 RefPtr<const nsRange> range = aSelection.GetRangeAt(i);
7454 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7454)
) {
7455 // Don't bail yet, iterate through them all
7456 continue;
7457 }
7458
7459 // Done when we find a range that we are in
7460 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
7461 aAllowCrossShadowBoundary)) {
7462 return true;
7463 }
7464 }
7465
7466 return false;
7467}
7468
7469// static
7470void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
7471 Element* aRoot,
7472 uint32_t& aOutStartOffset,
7473 uint32_t& aOutEndOffset) {
7474 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection && aRoot"
")"); do { *((volatile int*)__null) = 7474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7475
7476 // We don't care which end of this selection is anchor and which is focus. In
7477 // fact, we explicitly want to know which is the _start_ and which is the
7478 // _end_, not anchor vs focus.
7479 const nsRange* range = aSelection->GetAnchorFocusRange();
7480 if (!range) {
7481 // Nothing selected
7482 aOutStartOffset = aOutEndOffset = 0;
7483 return;
7484 }
7485
7486 // All the node pointers here are raw pointers for performance. We shouldn't
7487 // be doing anything in this function that invalidates the node tree.
7488 nsINode* startContainer = range->GetStartContainer();
7489 uint32_t startOffset = range->StartOffset();
7490 nsINode* endContainer = range->GetEndContainer();
7491 uint32_t endOffset = range->EndOffset();
7492
7493 // We have at most two children, consisting of an optional text node followed
7494 // by an optional <br>.
7495 NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children")do { if (!(aRoot->GetChildCount() <= 2)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Unexpected children", "aRoot->GetChildCount() <= 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7495); MOZ_PretendNoReturn(); } } while (0)
;
7496 nsIContent* firstChild = aRoot->GetFirstChild();
7497#ifdef DEBUG1
7498 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
7499 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7501); MOZ_PretendNoReturn(); } } while (0)
7500 startContainer == lastChild,do { if (!(startContainer == aRoot || startContainer == firstChild
|| startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7501); MOZ_PretendNoReturn(); } } while (0)
7501 "Unexpected startContainer")do { if (!(startContainer == aRoot || startContainer == firstChild
|| startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7501); MOZ_PretendNoReturn(); } } while (0)
;
7502 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7504); MOZ_PretendNoReturn(); } } while (0)
7503 endContainer == lastChild,do { if (!(endContainer == aRoot || endContainer == firstChild
|| endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7504); MOZ_PretendNoReturn(); } } while (0)
7504 "Unexpected endContainer")do { if (!(endContainer == aRoot || endContainer == firstChild
|| endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7504); MOZ_PretendNoReturn(); } } while (0)
;
7505 // firstChild is either text or a <br> (hence an element).
7506 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { *((volatile int*)__null) = 7506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7507#endif
7508 if (!firstChild || firstChild->IsElement()) {
7509 // No text node, so everything is 0
7510 startOffset = endOffset = 0;
7511 } else {
7512 // First child is text. If the start/end is already in the text node,
7513 // or the start of the root node, no change needed. If it's in the root
7514 // node but not the start, or in the trailing <br>, we need to set the
7515 // offset to the end.
7516 if ((startContainer == aRoot && startOffset != 0) ||
7517 (startContainer != aRoot && startContainer != firstChild)) {
7518 startOffset = firstChild->Length();
7519 }
7520 if ((endContainer == aRoot && endOffset != 0) ||
7521 (endContainer != aRoot && endContainer != firstChild)) {
7522 endOffset = firstChild->Length();
7523 }
7524 }
7525
7526 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startOffset <= endOffset"
")"); do { *((volatile int*)__null) = 7526; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7527 aOutStartOffset = startOffset;
7528 aOutEndOffset = endOffset;
7529}
7530
7531// static
7532HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
7533 if (!aPresContext) {
7534 return nullptr;
7535 }
7536 return GetHTMLEditor(aPresContext->GetDocShell());
7537}
7538
7539// static
7540HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
7541 bool isEditable;
7542 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
7543 !isEditable) {
7544 return nullptr;
7545 }
7546 return aDocShell->GetHTMLEditor();
7547}
7548
7549// static
7550EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
7551 if (!aPresContext) {
7552 return nullptr;
7553 }
7554
7555 return GetActiveEditor(aPresContext->Document()->GetWindow());
7556}
7557
7558// static
7559EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
7560 if (!aWindow || !aWindow->GetExtantDoc()) {
7561 return nullptr;
7562 }
7563
7564 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
7565 // handles all events. I.e., it's focused editor in this case.
7566 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
7567 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7568 }
7569
7570 // If focused element is associated with TextEditor, it must be <input>
7571 // element or <textarea> element. Let's return it even if it's in a
7572 // contenteditable element.
7573 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
7574 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
7575 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
7576 getter_AddRefs(focusedWindow))) {
7577 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
7578 return textEditor;
7579 }
7580 }
7581
7582 // Otherwise, HTMLEditor may handle inputs even non-editable element has
7583 // focus or nobody has focus.
7584 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7585}
7586
7587// static
7588TextEditor* nsContentUtils::GetTextEditorFromAnonymousNodeWithoutCreation(
7589 const nsIContent* aAnonymousContent) {
7590 if (!aAnonymousContent) {
7591 return nullptr;
7592 }
7593 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
7594 if (!parent || parent == aAnonymousContent) {
7595 return nullptr;
7596 }
7597 if (HTMLInputElement* inputElement =
7598 HTMLInputElement::FromNodeOrNull(parent)) {
7599 return inputElement->GetTextEditorWithoutCreation();
7600 }
7601 if (HTMLTextAreaElement* textareaElement =
7602 HTMLTextAreaElement::FromNodeOrNull(parent)) {
7603 return textareaElement->GetTextEditorWithoutCreation();
7604 }
7605 return nullptr;
7606}
7607
7608// static
7609bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
7610 while (aNode) {
7611 if (aNode->IsEditable()) {
7612 return true;
7613 }
7614 aNode = aNode->GetParent();
7615 }
7616 return false;
7617}
7618
7619// static
7620bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
7621 const nsACString& aValue) {
7622 if (IsForbiddenSystemRequestHeader(aHeader)) {
7623 return true;
7624 }
7625
7626 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
7627 nsContentUtils::ContainsForbiddenMethod(aValue))) {
7628 return true;
7629 }
7630
7631 if (StringBeginsWith(aHeader, "proxy-"_ns,
7632 nsCaseInsensitiveCStringComparator) ||
7633 StringBeginsWith(aHeader, "sec-"_ns,
7634 nsCaseInsensitiveCStringComparator)) {
7635 return true;
7636 }
7637
7638 return false;
7639}
7640
7641// static
7642bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
7643 static const char* kInvalidHeaders[] = {"accept-charset",
7644 "accept-encoding",
7645 "access-control-request-headers",
7646 "access-control-request-method",
7647 "connection",
7648 "content-length",
7649 "cookie",
7650 "cookie2",
7651 "date",
7652 "dnt",
7653 "expect",
7654 "host",
7655 "keep-alive",
7656 "origin",
7657 "referer",
7658 "set-cookie",
7659 "te",
7660 "trailer",
7661 "transfer-encoding",
7662 "upgrade",
7663 "via"};
7664 for (auto& kInvalidHeader : kInvalidHeaders) {
7665 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
7666 return true;
7667 }
7668 }
7669 return false;
7670}
7671
7672// static
7673bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
7674 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
7675 aHeader.LowerCaseEqualsASCII("set-cookie2"));
7676}
7677
7678// static
7679bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
7680 return headerName.EqualsIgnoreCase("x-http-method-override") ||
7681 headerName.EqualsIgnoreCase("x-http-method") ||
7682 headerName.EqualsIgnoreCase("x-method-override");
7683}
7684
7685// static
7686bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
7687 bool hasInsecureMethod = false;
7688 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
7689
7690 while (tokenizer.hasMoreTokens()) {
7691 const nsDependentCSubstring& value = tokenizer.nextToken();
7692
7693 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
7694 value.EqualsIgnoreCase("track")) {
7695 hasInsecureMethod = true;
7696 break;
7697 }
7698 }
7699
7700 return hasInsecureMethod;
7701}
7702
7703Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
7704 const nsACString& aHeaderValue, bool aAllowWhitespace) {
7705 // See https://fetch.spec.whatwg.org/#simple-range-header-value
7706 mozilla::Tokenizer p(aHeaderValue);
7707 Maybe<uint64_t> rangeStart;
7708 Maybe<uint64_t> rangeEnd;
7709
7710 // Step 2 and 3
7711 if (!p.CheckWord("bytes")) {
7712 return Nothing();
7713 }
7714
7715 // Step 4
7716 if (aAllowWhitespace) {
7717 p.SkipWhites();
7718 }
7719
7720 // Step 5 and 6
7721 if (!p.CheckChar('=')) {
7722 return Nothing();
7723 }
7724
7725 // Step 7
7726 if (aAllowWhitespace) {
7727 p.SkipWhites();
7728 }
7729
7730 // Step 8 and 9
7731 uint64_t res;
7732 if (p.ReadInteger(&res)) {
7733 rangeStart = Some(res);
7734 }
7735
7736 // Step 10
7737 if (aAllowWhitespace) {
7738 p.SkipWhites();
7739 }
7740
7741 // Step 11
7742 if (!p.CheckChar('-')) {
7743 return Nothing();
7744 }
7745
7746 // Step 13
7747 if (aAllowWhitespace) {
7748 p.SkipWhites();
7749 }
7750
7751 // Step 14 and 15
7752 if (p.ReadInteger(&res)) {
7753 rangeEnd = Some(res);
7754 }
7755
7756 // Step 16
7757 if (!p.CheckEOF()) {
7758 return Nothing();
7759 }
7760
7761 // Step 17
7762 if (!rangeStart && !rangeEnd) {
7763 return Nothing();
7764 }
7765
7766 // Step 18
7767 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
7768 return Nothing();
7769 }
7770
7771 return Some(ParsedRange(rangeStart, rangeEnd));
7772}
7773
7774// static
7775bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
7776 const nsACString& aHeaderValue) {
7777 const char* cur = aHeaderValue.BeginReading();
7778 const char* end = aHeaderValue.EndReading();
7779
7780 while (cur != end) {
7781 // Implementation of
7782 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
7783 // than a space but not a horizontal tab
7784 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
7785 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
7786 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
7787 *cur == ']' || *cur == '{' || *cur == '}' ||
7788 *cur == 0x7F) { // 0x75 is DEL
7789 return true;
7790 }
7791 cur++;
7792 }
7793 return false;
7794}
7795
7796// static
7797bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
7798 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7799 return false;
7800 }
7801 return true;
7802}
7803
7804// static
7805bool nsContentUtils::IsAllowedNonCorsContentType(
7806 const nsACString& aHeaderValue) {
7807 nsAutoCString contentType;
7808 nsAutoCString unused;
7809
7810 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7811 return false;
7812 }
7813
7814 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
7815 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7816 return false;
7817 }
7818
7819 return contentType.LowerCaseEqualsLiteral("text/plain") ||
7820 contentType.LowerCaseEqualsLiteral(
7821 "application/x-www-form-urlencoded") ||
7822 contentType.LowerCaseEqualsLiteral("multipart/form-data");
7823}
7824
7825// static
7826bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
7827 const char* cur = aHeaderValue.BeginReading();
7828 const char* end = aHeaderValue.EndReading();
7829
7830 while (cur != end) {
7831 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
7832 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
7833 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
7834 *cur == '=') {
7835 cur++;
7836 continue;
7837 }
7838 return false;
7839 }
7840 return true;
7841}
7842
7843bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
7844 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
7845 if (!parsedRange) {
7846 return false;
7847 }
7848
7849 if (!parsedRange->Start()) {
7850 return false;
7851 }
7852
7853 return true;
7854}
7855
7856// static
7857bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
7858 const nsACString& aValue) {
7859 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
7860 if (aValue.Length() > 128) {
7861 return false;
7862 }
7863 return (aName.LowerCaseEqualsLiteral("accept") &&
7864 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
7865 (aName.LowerCaseEqualsLiteral("accept-language") &&
7866 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7867 (aName.LowerCaseEqualsLiteral("content-language") &&
7868 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7869 (aName.LowerCaseEqualsLiteral("content-type") &&
7870 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
7871 (aName.LowerCaseEqualsLiteral("range") &&
7872 nsContentUtils::IsAllowedNonCorsRange(aValue)) ||
7873 (StaticPrefs::network_http_idempotencyKey_enabled() &&
7874 aName.LowerCaseEqualsLiteral("idempotency-key"));
7875}
7876
7877mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
7878 return gResistFingerprintingLog;
7879}
7880mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
7881
7882bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7883 nsAString& aResult,
7884 const fallible_t& aFallible) {
7885 aResult.Truncate();
7886 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7887}
7888
7889void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7890 nsAString& aResult) {
7891 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
7892 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
7893 }
7894}
7895
7896void nsContentUtils::DestroyMatchString(void* aData) {
7897 if (aData) {
7898 nsString* matchString = static_cast<nsString*>(aData);
7899 delete matchString;
7900 }
7901}
7902
7903// Table ordered from most to least likely JS MIME types.
7904static constexpr std::string_view kJavascriptMIMETypes[] = {
7905 "text/javascript",
7906 "text/ecmascript",
7907 "application/javascript",
7908 "application/ecmascript",
7909 "application/x-javascript",
7910 "application/x-ecmascript",
7911 "text/javascript1.0",
7912 "text/javascript1.1",
7913 "text/javascript1.2",
7914 "text/javascript1.3",
7915 "text/javascript1.4",
7916 "text/javascript1.5",
7917 "text/jscript",
7918 "text/livescript",
7919 "text/x-ecmascript",
7920 "text/x-javascript"};
7921
7922bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
7923 for (std::string_view type : kJavascriptMIMETypes) {
7924 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
7925 return true;
7926 }
7927 }
7928 return false;
7929}
7930
7931bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
7932 for (std::string_view type : kJavascriptMIMETypes) {
7933 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
7934 return true;
7935 }
7936 }
7937 return false;
7938}
7939
7940bool nsContentUtils::IsJsonMimeType(const nsAString& aMimeType) {
7941 // Table ordered from most to least likely JSON MIME types.
7942 static constexpr std::string_view jsonTypes[] = {"application/json",
7943 "text/json"};
7944
7945 for (std::string_view type : jsonTypes) {
7946 if (aMimeType.LowerCaseEqualsASCII(type.data(), type.length())) {
7947 return true;
7948 }
7949 }
7950
7951 return StringEndsWith(aMimeType, u"+json"_ns);
7952}
7953
7954bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
7955 //
7956 // SECURITY CHECK: disable prefetching and preloading from mailnews!
7957 //
7958 // walk up the docshell tree to see if any containing
7959 // docshell are of type MAIL.
7960 //
7961
7962 if (!aDocShell) {
7963 return false;
7964 }
7965
7966 nsCOMPtr<nsIDocShell> docshell = aDocShell;
7967 nsCOMPtr<nsIDocShellTreeItem> parentItem;
7968
7969 do {
7970 auto appType = docshell->GetAppType();
7971 if (appType == nsIDocShell::APP_TYPE_MAIL) {
7972 return false; // do not prefetch, preload, preconnect from mailnews
7973 }
7974
7975 docshell->GetInProcessParent(getter_AddRefs(parentItem));
7976 if (parentItem) {
7977 docshell = do_QueryInterface(parentItem);
7978 if (!docshell) {
7979 NS_ERROR("cannot get a docshell from a treeItem!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "cannot get a docshell from a treeItem!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7979); MOZ_PretendNoReturn(); } while (0)
;
7980 return false;
7981 }
7982 }
7983 } while (parentItem);
7984
7985 return true;
7986}
7987
7988uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
7989 // can't do anything if there's no nsIRequest!
7990 if (!aRequest) {
7991 return 0;
7992 }
7993
7994 nsCOMPtr<nsILoadGroup> loadGroup;
7995 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
7996
7997 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
7998 return 0;
7999 }
8000
8001 return GetInnerWindowID(loadGroup);
8002}
8003
8004uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
8005 if (!aLoadGroup) {
8006 return 0;
8007 }
8008
8009 nsCOMPtr<nsIInterfaceRequestor> callbacks;
8010 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
8011 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
8012 return 0;
8013 }
8014
8015 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
8016 if (!loadContext) {
8017 return 0;
8018 }
8019
8020 nsCOMPtr<mozIDOMWindowProxy> window;
8021 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
8022 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
8023 return 0;
8024 }
8025
8026 auto* pwindow = nsPIDOMWindowOuter::From(window);
8027 if (!pwindow) {
8028 return 0;
8029 }
8030
8031 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
8032 return inner ? inner->WindowID() : 0;
8033}
8034
8035// static
8036void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
8037 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
8038 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.IsEmpty()"
")"); do { *((volatile int*)__null) = 8038; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8039 if (aHost.Length() >= 2 && aHost[0] != '[' &&
8040 aHost[aHost.Length() - 1] != ']') {
8041 aHost.Insert('[', 0);
8042 aHost.Append(']');
8043 }
8044 }
8045}
8046
8047nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8048 nsACString& aHost) {
8049 aHost.Truncate();
8050 nsresult rv = aURI->GetHost(aHost);
8051 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8052 return rv;
8053 }
8054
8055 MaybeFixIPv6Host(aHost);
8056
8057 return NS_OK;
8058}
8059
8060nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8061 nsAString& aHost) {
8062 nsAutoCString hostname;
8063 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
8064 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8065 return rv;
8066 }
8067 CopyUTF8toUTF16(hostname, aHost);
8068 return NS_OK;
8069}
8070
8071nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
8072 nsACString& aHost) {
8073 nsresult rv = aPrincipal->GetAsciiHost(aHost);
8074 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8075 return rv;
8076 }
8077
8078 MaybeFixIPv6Host(aHost);
8079 return NS_OK;
8080}
8081
8082CallState nsContentUtils::CallOnAllRemoteChildren(
8083 MessageBroadcaster* aManager,
8084 const std::function<CallState(BrowserParent*)>& aCallback) {
8085 uint32_t browserChildCount = aManager->ChildCount();
8086 for (uint32_t j = 0; j < browserChildCount; ++j) {
8087 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
8088 if (!childMM) {
8089 continue;
8090 }
8091
8092 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
8093 if (nonLeafMM) {
8094 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
8095 return CallState::Stop;
8096 }
8097 continue;
8098 }
8099
8100 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
8101 if (cb) {
8102 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
8103 BrowserParent* remote = BrowserParent::GetFrom(fl);
8104 if (remote && aCallback) {
8105 if (aCallback(remote) == CallState::Stop) {
8106 return CallState::Stop;
8107 }
8108 }
8109 }
8110 }
8111
8112 return CallState::Continue;
8113}
8114
8115void nsContentUtils::CallOnAllRemoteChildren(
8116 nsPIDOMWindowOuter* aWindow,
8117 const std::function<CallState(BrowserParent*)>& aCallback) {
8118 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
8119 if (window->IsChromeWindow()) {
8120 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
8121 if (windowMM) {
8122 CallOnAllRemoteChildren(windowMM, aCallback);
8123 }
8124 }
8125}
8126
8127bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
8128 const IPCTransferableDataItem& aItem) {
8129 // Unknown types are converted to kCustomTypesMime.
8130 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
8131 return true;
8132 }
8133
8134 for (const char* format : DataTransfer::kKnownFormats) {
8135 if (aItem.flavor().EqualsASCII(format)) {
8136 return true;
8137 }
8138 }
8139
8140 return false;
8141}
8142
8143nsresult nsContentUtils::IPCTransferableDataToTransferable(
8144 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
8145 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8146 nsresult rv;
8147 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
8148 for (const auto& item : items) {
8149 if (aFilterUnknownFlavors && !IPCTransferableDataItemHasKnownFlavor(item)) {
8150 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8152)
8151 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8152)
8152 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8152)
;
8153 continue;
8154 }
8155
8156 if (aAddDataFlavor) {
8157 aTransferable->AddDataFlavor(item.flavor().get());
8158 }
8159
8160 nsCOMPtr<nsISupports> transferData;
8161 switch (item.data().type()) {
8162 case IPCTransferableDataType::TIPCTransferableDataString: {
8163 const auto& data = item.data().get_IPCTransferableDataString();
8164 nsCOMPtr<nsISupportsString> dataWrapper =
8165 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
8166 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8166); return rv; } } while (false)
;
8167 rv = dataWrapper->SetData(nsDependentSubstring(
8168 reinterpret_cast<const char16_t*>(data.data().Data()),
8169 data.data().Size() / sizeof(char16_t)));
8170 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8170); return rv; } } while (false)
;
8171 transferData = dataWrapper;
8172 break;
8173 }
8174 case IPCTransferableDataType::TIPCTransferableDataCString: {
8175 const auto& data = item.data().get_IPCTransferableDataCString();
8176 nsCOMPtr<nsISupportsCString> dataWrapper =
8177 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
8178 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8178); return rv; } } while (false)
;
8179 rv = dataWrapper->SetData(nsDependentCSubstring(
8180 reinterpret_cast<const char*>(data.data().Data()),
8181 data.data().Size()));
8182 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8182); return rv; } } while (false)
;
8183 transferData = dataWrapper;
8184 break;
8185 }
8186 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8187 const auto& data = item.data().get_IPCTransferableDataInputStream();
8188 nsCOMPtr<nsIInputStream> stream;
8189 rv = NS_NewByteInputStream(getter_AddRefs(stream),
8190 AsChars(data.data().AsSpan()),
8191 NS_ASSIGNMENT_COPY);
8192 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8192); return rv; } } while (false)
;
8193 transferData = stream.forget();
8194 break;
8195 }
8196 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8197 const auto& data = item.data().get_IPCTransferableDataImageContainer();
8198 nsCOMPtr<imgIContainer> container;
8199 rv = DeserializeTransferableDataImageContainer(
8200 data, getter_AddRefs(container));
8201 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8201); return rv; } } while (false)
;
8202 transferData = container;
8203 break;
8204 }
8205 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8206 const auto& data = item.data().get_IPCTransferableDataBlob();
8207 transferData = IPCBlobUtils::Deserialize(data.blob());
8208 break;
8209 }
8210 case IPCTransferableDataType::T__None:
8211 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: "
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8211; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8212 return NS_ERROR_FAILURE;
8213 }
8214
8215 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
8216 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8216); return rv; } } while (false)
;
8217 }
8218 return NS_OK;
8219}
8220
8221nsresult nsContentUtils::IPCTransferableToTransferable(
8222 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
8223 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8224 // Note that we need to set privacy status of transferable before adding any
8225 // data into it.
8226 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
8227
8228 nsresult rv =
8229 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
8230 aTransferable, aFilterUnknownFlavors);
8231 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8231); return rv; } } while (false)
;
8232
8233 if (aIPCTransferable.cookieJarSettings().isSome()) {
8234 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
8235 net::CookieJarSettings::Deserialize(
8236 aIPCTransferable.cookieJarSettings().ref(),
8237 getter_AddRefs(cookieJarSettings));
8238 aTransferable->SetCookieJarSettings(cookieJarSettings);
8239 }
8240 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
8241 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
8242 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
8243
8244 return NS_OK;
8245}
8246
8247nsresult nsContentUtils::IPCTransferableDataItemToVariant(
8248 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
8249 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { *((volatile int*)__null) = 8249; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8250
8251 switch (aItem.data().type()) {
8252 case IPCTransferableDataType::TIPCTransferableDataString: {
8253 const auto& data = aItem.data().get_IPCTransferableDataString();
8254 return aVariant->SetAsAString(nsDependentSubstring(
8255 reinterpret_cast<const char16_t*>(data.data().Data()),
8256 data.data().Size() / sizeof(char16_t)));
8257 }
8258 case IPCTransferableDataType::TIPCTransferableDataCString: {
8259 const auto& data = aItem.data().get_IPCTransferableDataCString();
8260 return aVariant->SetAsACString(nsDependentCSubstring(
8261 reinterpret_cast<const char*>(data.data().Data()),
8262 data.data().Size()));
8263 }
8264 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8265 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
8266 nsCOMPtr<nsIInputStream> stream;
8267 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
8268 AsChars(data.data().AsSpan()),
8269 NS_ASSIGNMENT_COPY);
8270 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8270); return rv; } } while (false)
;
8271 return aVariant->SetAsISupports(stream);
8272 }
8273 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8274 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
8275 nsCOMPtr<imgIContainer> container;
8276 nsresult rv = DeserializeTransferableDataImageContainer(
8277 data, getter_AddRefs(container));
8278 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8278); return rv; } } while (false)
;
8279 return aVariant->SetAsISupports(container);
8280 }
8281 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8282 const auto& data = aItem.data().get_IPCTransferableDataBlob();
8283 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
8284 return aVariant->SetAsISupports(blobImpl);
8285 }
8286 case IPCTransferableDataType::T__None:
8287 break;
8288 }
8289
8290 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: "
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8290; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8291 return NS_ERROR_UNEXPECTED;
8292}
8293
8294void nsContentUtils::TransferablesToIPCTransferableDatas(
8295 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
8296 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8297 aIPC.Clear();
8298 if (aTransferables) {
8299 uint32_t transferableCount = 0;
8300 aTransferables->GetLength(&transferableCount);
8301 for (uint32_t i = 0; i < transferableCount; ++i) {
8302 IPCTransferableData* dt = aIPC.AppendElement();
8303 nsCOMPtr<nsITransferable> transferable =
8304 do_QueryElementAt(aTransferables, i);
8305 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
8306 aParent);
8307 }
8308 }
8309}
8310
8311nsresult nsContentUtils::CalculateBufferSizeForImage(
8312 const uint32_t& aStride, const IntSize& aImageSize,
8313 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
8314 size_t* aUsedBufferSize) {
8315 CheckedInt32 requiredBytes =
8316 CheckedInt32(aStride) * CheckedInt32(aImageSize.height);
8317
8318 CheckedInt32 usedBytes =
8319 requiredBytes - aStride +
8320 (CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat));
8321 if (!usedBytes.isValid()) {
8322 return NS_ERROR_FAILURE;
8323 }
8324
8325 MOZ_ASSERT(requiredBytes.isValid(), "usedBytes valid but not required?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(requiredBytes.isValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(requiredBytes.isValid()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("requiredBytes.isValid()"
" (" "usedBytes valid but not required?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "requiredBytes.isValid()"
") (" "usedBytes valid but not required?" ")"); do { *((volatile
int*)__null) = 8325; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8326 *aMaxBufferSize = requiredBytes.value();
8327 *aUsedBufferSize = usedBytes.value();
8328 return NS_OK;
8329}
8330
8331static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
8332 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
8333 SurfaceFormat aFormat) {
8334 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
8335 return nullptr;
8336 }
8337
8338 // Validate shared memory buffer size
8339 size_t imageBufLen = 0;
8340 size_t maxBufLen = 0;
8341 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
8342 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
8343 return nullptr;
8344 }
8345 if (imageBufLen > aData.Size()) {
8346 return nullptr;
8347 }
8348 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
8349 aStride);
8350}
8351
8352nsresult nsContentUtils::DeserializeTransferableDataImageContainer(
8353 const IPCTransferableDataImageContainer& aData,
8354 imgIContainer** aContainer) {
8355 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aData.image());
8356 if (!surface) {
8357 return NS_ERROR_FAILURE;
8358 }
8359
8360 RefPtr<gfxDrawable> drawable =
8361 new gfxSurfaceDrawable(surface, surface->GetSize());
8362 nsCOMPtr<imgIContainer> imageContainer =
8363 image::ImageOps::CreateFromDrawable(drawable);
8364 imageContainer.forget(aContainer);
8365
8366 return NS_OK;
8367}
8368
8369bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
8370 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
8371 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
8372 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
8373 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
8374 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
8375}
8376
8377// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
8378// will be implicitly serialized in shmem when sent over IPDL directly.
8379static IPCTransferableDataString AsIPCTransferableDataString(
8380 Span<const char16_t> aInput) {
8381 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
8382}
8383
8384// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
8385// will be implicitly serialized in shmem when sent over IPDL directly.
8386static IPCTransferableDataCString AsIPCTransferableDataCString(
8387 Span<const char> aInput) {
8388 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
8389}
8390
8391void nsContentUtils::TransferableToIPCTransferableData(
8392 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
8393 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8394 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { *((volatile int*)__null) = 8394; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8395
8396 if (aTransferable) {
8397 nsTArray<nsCString> flavorList;
8398 aTransferable->FlavorsTransferableCanExport(flavorList);
8399
8400 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
8401 nsCString& flavorStr = flavorList[j];
8402 if (!flavorStr.Length()) {
8403 continue;
8404 }
8405
8406 nsCOMPtr<nsISupports> data;
8407 nsresult rv =
8408 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
8409
8410 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
8411 if (aInSyncMessage) {
8412 // Can't do anything.
8413 // FIXME: This shouldn't be the case anymore!
8414 continue;
8415 }
8416
8417 // This is a hack to support kFilePromiseMime.
8418 // On Windows there just needs to be an entry for it,
8419 // and for OSX we need to create
8420 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
8421 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
8422 IPCTransferableDataItem* item =
8423 aTransferableData->items().AppendElement();
8424 item->flavor() = flavorStr;
8425 item->data() =
8426 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
8427 continue;
8428 }
8429
8430 // Empty element, transfer only the flavor
8431 IPCTransferableDataItem* item =
8432 aTransferableData->items().AppendElement();
8433 item->flavor() = flavorStr;
8434 item->data() = AsIPCTransferableDataString(EmptyString());
8435 continue;
8436 }
8437
8438 // We need to handle nsIInputStream before nsISupportsCString, otherwise
8439 // nsStringInputStream would be converted into a wrong type.
8440 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
8441 IPCTransferableDataItem* item =
8442 aTransferableData->items().AppendElement();
8443 item->flavor() = flavorStr;
8444 nsCString imageData;
8445 DebugOnly<nsresult> rv =
8446 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
8447 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8449; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8448 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8449; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8449 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8449; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8450 // FIXME: This can probably be simplified once bug 1783240 lands, as
8451 // `nsCString` will be implicitly serialized in shmem when sent over
8452 // IPDL directly.
8453 item->data() =
8454 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
8455 continue;
8456 }
8457
8458 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
8459 nsAutoString dataAsString;
8460 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))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8460); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(text->GetData(dataAsString))"
")"); do { *((volatile int*)__null) = 8460; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8461
8462 IPCTransferableDataItem* item =
8463 aTransferableData->items().AppendElement();
8464 item->flavor() = flavorStr;
8465 item->data() = AsIPCTransferableDataString(dataAsString);
8466 continue;
8467 }
8468
8469 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
8470 nsAutoCString dataAsString;
8471 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))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8471); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8472
8473 IPCTransferableDataItem* item =
8474 aTransferableData->items().AppendElement();
8475 item->flavor() = flavorStr;
8476 item->data() = AsIPCTransferableDataCString(dataAsString);
8477 continue;
8478 }
8479
8480 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
8481 // Images to be placed on the clipboard are imgIContainers.
8482 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
8483 imgIContainer::FRAME_CURRENT,
8484 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
8485 if (!surface) {
8486 continue;
8487 }
8488 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
8489 surface->GetDataSurface();
8490 if (!dataSurface) {
8491 continue;
8492 }
8493
8494 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
8495 if (!imageData) {
8496 continue;
8497 }
8498
8499 IPCTransferableDataItem* item =
8500 aTransferableData->items().AppendElement();
8501 item->flavor() = flavorStr;
8502 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
8503 continue;
8504 }
8505
8506 // Otherwise, handle this as a file.
8507 nsCOMPtr<BlobImpl> blobImpl;
8508 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
8509 if (aParent) {
8510 bool isDir = false;
8511 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
8512 nsAutoString path;
8513 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))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8513)
) {
8514 continue;
8515 }
8516
8517 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
8518 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
8519 }
8520 }
8521
8522 blobImpl = new FileBlobImpl(file);
8523
8524 IgnoredErrorResult rv;
8525
8526 // Ensure that file data is cached no that the content process
8527 // has this data available to it when passed over:
8528 blobImpl->GetSize(rv);
8529 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8529)
) {
8530 continue;
8531 }
8532
8533 blobImpl->GetLastModified(rv);
8534 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8534)
) {
8535 continue;
8536 }
8537 } else {
8538 if (aInSyncMessage) {
8539 // Can't do anything.
8540 // FIXME: This shouldn't be the case anymore!
8541 continue;
8542 }
8543
8544 blobImpl = do_QueryInterface(data);
8545 }
8546
8547 if (blobImpl) {
8548 // If we failed to create the blob actor, then this blob probably
8549 // can't get the file size for the underlying file, ignore it for
8550 // now. TODO pass this through anyway.
8551 IPCBlob ipcBlob;
8552 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
8553 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8553)
) {
8554 continue;
8555 }
8556
8557 IPCTransferableDataItem* item =
8558 aTransferableData->items().AppendElement();
8559 item->flavor() = flavorStr;
8560 item->data() = IPCTransferableDataBlob(ipcBlob);
8561 }
8562 }
8563 }
8564}
8565
8566void nsContentUtils::TransferableToIPCTransferable(
8567 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
8568 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8569 IPCTransferableData ipcTransferableData;
8570 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
8571 aInSyncMessage, aParent);
8572
8573 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
8574 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
8575 aTransferable->GetCookieJarSettings()) {
8576 net::CookieJarSettingsArgs args;
8577 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
8578 cookieJarSettingsArgs = Some(std::move(args));
8579 }
8580
8581 aIPCTransferable->data() = std::move(ipcTransferableData);
8582 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
8583 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
8584 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
8585 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
8586 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
8587}
8588
8589Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
8590 size_t* aLength,
8591 int32_t* aStride) {
8592 mozilla::gfx::DataSourceSurface::MappedSurface map;
8593 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
8594 return Nothing();
8595 }
8596
8597 size_t bufLen = 0;
8598 size_t maxBufLen = 0;
8599 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
8600 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
8601 &bufLen);
8602 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8603 aSurface.Unmap();
8604 return Nothing();
8605 }
8606
8607 BigBuffer surfaceData(maxBufLen);
8608 memcpy(surfaceData.Data(), map.mData, bufLen);
8609 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
8610
8611 *aLength = maxBufLen;
8612 *aStride = map.mStride;
8613
8614 aSurface.Unmap();
8615 return Some(std::move(surfaceData));
8616}
8617
8618Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
8619 size_t len = 0;
8620 int32_t stride = 0;
8621 auto mem = GetSurfaceData(aSurface, &len, &stride);
8622 if (!mem) {
8623 return Nothing();
8624 }
8625 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
8626 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
8627}
8628
8629already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
8630 const IPCImage& aImage) {
8631 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
8632 aImage.size().ToUnknownSize(), aImage.format());
8633}
8634
8635Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
8636 Modifiers result = 0;
8637 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
8638 result |= mozilla::MODIFIER_SHIFT;
8639 }
8640 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
8641 result |= mozilla::MODIFIER_CONTROL;
8642 }
8643 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
8644 result |= mozilla::MODIFIER_ALT;
8645 }
8646 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
8647 result |= mozilla::MODIFIER_META;
8648 }
8649 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
8650 result |= mozilla::MODIFIER_ALTGRAPH;
8651 }
8652 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
8653 result |= mozilla::MODIFIER_CAPSLOCK;
8654 }
8655 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
8656 result |= mozilla::MODIFIER_FN;
8657 }
8658 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
8659 result |= mozilla::MODIFIER_FNLOCK;
8660 }
8661 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
8662 result |= mozilla::MODIFIER_NUMLOCK;
8663 }
8664 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
8665 result |= mozilla::MODIFIER_SCROLLLOCK;
8666 }
8667 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
8668 result |= mozilla::MODIFIER_SYMBOL;
8669 }
8670 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
8671 result |= mozilla::MODIFIER_SYMBOLLOCK;
8672 }
8673 return result;
8674}
8675
8676nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
8677 if (!aPresShell) {
8678 return nullptr;
8679 }
8680 nsIFrame* frame = aPresShell->GetRootFrame();
8681 if (!frame) {
8682 return nullptr;
8683 }
8684 return frame->GetView()->GetNearestWidget(aOffset);
8685}
8686
8687int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
8688 switch (aButton) {
8689 case -1:
8690 return MouseButtonsFlag::eNoButtons;
8691 case MouseButton::ePrimary:
8692 return MouseButtonsFlag::ePrimaryFlag;
8693 case MouseButton::eMiddle:
8694 return MouseButtonsFlag::eMiddleFlag;
8695 case MouseButton::eSecondary:
8696 return MouseButtonsFlag::eSecondaryFlag;
8697 case 3:
8698 return MouseButtonsFlag::e4thFlag;
8699 case 4:
8700 return MouseButtonsFlag::e5thFlag;
8701 case MouseButton::eEraser:
8702 return MouseButtonsFlag::eEraserFlag;
8703 default:
8704 NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8704); MOZ_PretendNoReturn(); } while (0)
;
8705 return 0;
8706 }
8707}
8708
8709LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
8710 const CSSPoint& aPoint, const nsPoint& aOffset,
8711 nsPresContext* aPresContext) {
8712 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
8713 nsPoint visualRelative =
8714 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
8715 return LayoutDeviceIntPoint::FromAppUnitsRounded(
8716 visualRelative, aPresContext->AppUnitsPerDevPixel());
8717}
8718
8719nsView* nsContentUtils::GetViewToDispatchEvent(nsPresContext* aPresContext,
8720 PresShell** aPresShell) {
8721 if (!aPresContext || !aPresShell) {
8722 return nullptr;
8723 }
8724 RefPtr<PresShell> presShell = aPresContext->PresShell();
8725 if (NS_WARN_IF(!presShell)NS_warn_if_impl(!presShell, "!presShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8725)
) {
8726 *aPresShell = nullptr;
8727 return nullptr;
8728 }
8729 nsViewManager* viewManager = presShell->GetViewManager();
8730 if (!viewManager) {
8731 presShell.forget(aPresShell); // XXX Is this intentional?
8732 return nullptr;
8733 }
8734 presShell.forget(aPresShell);
8735 return viewManager->GetRootView();
8736}
8737
8738nsresult nsContentUtils::SendMouseEvent(
8739 mozilla::PresShell* aPresShell, const nsAString& aType, float aX, float aY,
8740 int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers,
8741 bool aIgnoreRootScrollFrame, float aPressure,
8742 unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
8743 bool* aPreventDefault, bool aIsDOMEventSynthesized,
8744 bool aIsWidgetEventSynthesized) {
8745 nsPoint offset;
8746 nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
8747 if (!widget) return NS_ERROR_FAILURE;
8748
8749 EventMessage msg;
8750 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
8751 bool contextMenuKey = false;
8752 if (aType.EqualsLiteral("mousedown")) {
8753 msg = eMouseDown;
8754 } else if (aType.EqualsLiteral("mouseup")) {
8755 msg = eMouseUp;
8756 } else if (aType.EqualsLiteral("mousemove")) {
8757 msg = eMouseMove;
8758 } else if (aType.EqualsLiteral("mouseover")) {
8759 msg = eMouseEnterIntoWidget;
8760 } else if (aType.EqualsLiteral("mouseout")) {
8761 msg = eMouseExitFromWidget;
8762 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
8763 } else if (aType.EqualsLiteral("mousecancel")) {
8764 msg = eMouseExitFromWidget;
8765 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
8766 : WidgetMouseEvent::ePuppet);
8767 } else if (aType.EqualsLiteral("mouselongtap")) {
8768 msg = eMouseLongTap;
8769 } else if (aType.EqualsLiteral("contextmenu")) {
8770 msg = eContextMenu;
8771 contextMenuKey = !aButton && aInputSourceArg !=
8772 dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH;
8773 } else if (aType.EqualsLiteral("MozMouseHittest")) {
8774 msg = eMouseHitTest;
8775 } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
8776 msg = eMouseExploreByTouch;
8777 } else {
8778 return NS_ERROR_FAILURE;
8779 }
8780
8781 if (aInputSourceArg == MouseEvent_Binding::MOZ_SOURCE_UNKNOWN) {
8782 aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
8783 }
8784
8785 Maybe<WidgetPointerEvent> pointerEvent;
8786 Maybe<WidgetMouseEvent> mouseEvent;
8787 if (IsPointerEventMessage(msg)) {
8788 MOZ_ASSERT(!aIsWidgetEventSynthesized,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIsWidgetEventSynthesized)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIsWidgetEventSynthesized))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aIsWidgetEventSynthesized"
" (" "The event shouldn't be dispatched as a synthesized event"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8789; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8789 "The event shouldn't be dispatched as a synthesized event")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIsWidgetEventSynthesized)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIsWidgetEventSynthesized))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aIsWidgetEventSynthesized"
" (" "The event shouldn't be dispatched as a synthesized event"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8789; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8790 if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)(__builtin_expect(!!(aIsWidgetEventSynthesized), 0))) {
8791 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
8792 // synthesized event.
8793 return NS_ERROR_INVALID_ARG;
8794 }
8795 pointerEvent.emplace(true, msg, widget,
8796 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8797 : WidgetMouseEvent::eNormal);
8798 } else {
8799 mouseEvent.emplace(true, msg, widget,
8800 aIsWidgetEventSynthesized
8801 ? WidgetMouseEvent::eSynthesized
8802 : WidgetMouseEvent::eReal,
8803 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8804 : WidgetMouseEvent::eNormal);
8805 }
8806 WidgetMouseEvent& mouseOrPointerEvent =
8807 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
8808 mouseOrPointerEvent.pointerId = aIdentifier;
8809 mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers);
8810 mouseOrPointerEvent.mButton = aButton;
8811 mouseOrPointerEvent.mButtons =
8812 aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ? aButtons
8813 : msg == eMouseUp ? 0
8814 : GetButtonsFlagForButton(aButton);
8815 mouseOrPointerEvent.mPressure = aPressure;
8816 mouseOrPointerEvent.mInputSource = aInputSourceArg;
8817 mouseOrPointerEvent.mClickCount = aClickCount;
8818 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
8819 mouseOrPointerEvent.mExitFrom = exitFrom;
8820
8821 nsPresContext* presContext = aPresShell->GetPresContext();
8822 if (!presContext) return NS_ERROR_FAILURE;
8823
8824 mouseOrPointerEvent.mRefPoint =
8825 ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
8826 mouseOrPointerEvent.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
8827
8828 nsEventStatus status = nsEventStatus_eIgnore;
8829 if (aToWindow) {
8830 RefPtr<PresShell> presShell;
8831 nsView* view =
8832 GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
8833 if (!presShell || !view) {
8834 return NS_ERROR_FAILURE;
8835 }
8836 return presShell->HandleEvent(view->GetFrame(), &mouseOrPointerEvent, false,
8837 &status);
8838 }
8839 if (StaticPrefs::test_events_async_enabled()) {
8840 status = widget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
8841 } else {
8842 nsresult rv = widget->DispatchEvent(&mouseOrPointerEvent, status);
8843 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8843); return rv; } } while (false)
;
8844 }
8845 if (aPreventDefault) {
8846 *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
8847 }
8848
8849 return NS_OK;
8850}
8851
8852/* static */
8853void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
8854 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8855 bool aOnlySystemGroup) {
8856 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8856); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { *((volatile int*)__null) = 8856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8857 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8857); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler"
")"); do { *((volatile int*)__null) = 8857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8858
8859 if (RefPtr<Document> doc = aItem->GetDocument()) {
8860 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
8861 }
8862
8863 int32_t childCount = 0;
8864 aItem->GetInProcessChildCount(&childCount);
8865 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8866 kids.AppendElements(childCount);
8867 for (int32_t i = 0; i < childCount; ++i) {
8868 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8869 }
8870
8871 for (uint32_t i = 0; i < kids.Length(); ++i) {
8872 if (kids[i]) {
8873 FirePageHideEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8874 aOnlySystemGroup);
8875 }
8876 }
8877}
8878
8879// The pageshow event is fired for a given document only if IsShowing() returns
8880// the same thing as aFireIfShowing. This gives us a way to fire pageshow only
8881// on documents that are still loading or only on documents that are already
8882// loaded.
8883/* static */
8884void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
8885 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8886 bool aFireIfShowing, bool aOnlySystemGroup) {
8887 int32_t childCount = 0;
8888 aItem->GetInProcessChildCount(&childCount);
8889 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8890 kids.AppendElements(childCount);
8891 for (int32_t i = 0; i < childCount; ++i) {
8892 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8893 }
8894
8895 for (uint32_t i = 0; i < kids.Length(); ++i) {
8896 if (kids[i]) {
8897 FirePageShowEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8898 aFireIfShowing, aOnlySystemGroup);
8899 }
8900 }
8901
8902 RefPtr<Document> doc = aItem->GetDocument();
8903 if (doc && doc->IsShowing() == aFireIfShowing) {
8904 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
8905 }
8906}
8907
8908/* static */
8909already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
8910 if (aDoc) {
8911 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
8912 return win->GetTopWindowRoot();
8913 }
8914 }
8915 return nullptr;
8916}
8917
8918/* static */
8919bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
8920 nsIURI* aDocURI) {
8921 if (aAnchor.IsEmpty()) {
8922 // anchor parameter not present or empty -> same document reference
8923 return true;
8924 }
8925
8926 // the document URI might contain a fragment identifier ("#...')
8927 // we want to ignore that because it's invisible to the server
8928 // and just affects the local interpretation in the recipient
8929 nsCOMPtr<nsIURI> contextUri;
8930 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
8931
8932 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8933 // copying failed
8934 return false;
8935 }
8936
8937 // resolve anchor against context
8938 nsCOMPtr<nsIURI> resolvedUri;
8939 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
8940
8941 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8942 // resolving failed
8943 return false;
8944 }
8945
8946 bool same;
8947 rv = contextUri->Equals(resolvedUri, &same);
8948 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8949 // comparison failed
8950 return false;
8951 }
8952
8953 return same;
8954}
8955
8956/* static */
8957bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
8958 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
8959 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
8960 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
8961 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
8962 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
8963 aType == nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD ||
8964 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
8965}
8966
8967// static
8968ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
8969 nsIChannel* aChannel) {
8970 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
8971 if (!httpChannel) {
8972 return ReferrerPolicy::_empty;
8973 }
8974
8975 nsresult rv;
8976 nsAutoCString headerValue;
8977 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
8978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
8979 return ReferrerPolicy::_empty;
8980 }
8981
8982 return ReferrerInfo::ReferrerPolicyFromHeaderString(
8983 NS_ConvertUTF8toUTF16(headerValue));
8984}
8985
8986// static
8987bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
8988 nsLoadFlags loadFlags = 0;
8989 aChannel->GetLoadFlags(&loadFlags);
8990 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
8991 return true;
8992 }
8993
8994 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
8995 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
8996 return IsNonSubresourceInternalPolicyType(type);
8997}
8998
8999// static
9000bool nsContentUtils::IsNonSubresourceInternalPolicyType(
9001 nsContentPolicyType aType) {
9002 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
9003 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
9004 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
9005 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
9006 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
9007}
9008
9009// static public
9010bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
9011 nsPIDOMWindowInner* aWindow) {
9012 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9012; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9013
9014 Document* document = aWindow->GetExtantDoc();
9015 if (!document) {
9016 return false;
9017 }
9018
9019 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9020 do_QueryInterface(document->GetChannel());
9021 if (!classifiedChannel) {
9022 return false;
9023 }
9024
9025 return classifiedChannel->IsThirdPartyTrackingResource();
9026}
9027
9028// static public
9029bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
9030 nsPIDOMWindowInner* aWindow) {
9031 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9031; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9032
9033 Document* document = aWindow->GetExtantDoc();
9034 if (!document) {
9035 return false;
9036 }
9037
9038 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9039 do_QueryInterface(document->GetChannel());
9040 if (!classifiedChannel) {
9041 return false;
9042 }
9043
9044 uint32_t classificationFlags =
9045 classifiedChannel->GetFirstPartyClassificationFlags();
9046
9047 return mozilla::net::UrlClassifierCommon::IsTrackingClassificationFlag(
9048 classificationFlags, NS_UsePrivateBrowsing(document->GetChannel()));
9049}
9050
9051namespace {
9052
9053// We put StringBuilder in the anonymous namespace to prevent anything outside
9054// this file from accidentally being linked against it.
9055class BulkAppender {
9056 using size_type = typename nsAString::size_type;
9057
9058 public:
9059 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
9060 : mHandle(std::move(aHandle)), mPosition(0) {}
9061 ~BulkAppender() = default;
9062
9063 template <int N>
9064 void AppendLiteral(const char16_t (&aStr)[N]) {
9065 size_t len = N - 1;
9066 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9066; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9067 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
9068 mPosition += len;
9069 }
9070
9071 void Append(Span<const char16_t> aStr) {
9072 size_t len = aStr.Length();
9073 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9074 // Both mHandle.Elements() and aStr.Elements() are guaranteed
9075 // to be non-null (by the string implementation and by Span,
9076 // respectively), so not checking the pointers for null before
9077 // memcpy does not lead to UB even if len was zero.
9078 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
9079 len * sizeof(char16_t));
9080 mPosition += len;
9081 }
9082
9083 void Append(Span<const char> aStr) {
9084 size_t len = aStr.Length();
9085 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9086 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
9087 mPosition += len;
9088 }
9089
9090 void Finish() { mHandle.Finish(mPosition, false); }
9091
9092 private:
9093 BulkWriteHandle<char16_t> mHandle;
9094 size_type mPosition;
9095};
9096
9097class StringBuilder {
9098 private:
9099 class Unit {
9100 public:
9101 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<nsISupports, StringBuilder::Unit>::value
, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder::Unit"
, sizeof(*this)); } while (0)
; }
9102 ~Unit() {
9103 if (mType == Type::String || mType == Type::StringWithEncode) {
9104 mString.~nsString();
9105 }
9106 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<nsISupports, StringBuilder::Unit>::value
, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder::Unit"
, sizeof(*this)); } while (0)
;
9107 }
9108
9109 enum class Type : uint8_t {
9110 Unknown,
9111 Atom,
9112 String,
9113 StringWithEncode,
9114 Literal,
9115 TextFragment,
9116 TextFragmentWithEncode,
9117 };
9118
9119 struct LiteralSpan {
9120 const char16_t* mData;
9121 uint32_t mLength;
9122
9123 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
9124 };
9125
9126 union {
9127 nsAtom* mAtom;
9128 LiteralSpan mLiteral;
9129 nsString mString;
9130 const nsTextFragment* mTextFragment;
9131 };
9132 Type mType = Type::Unknown;
9133 };
9134
9135 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
9136 "Unit should remain small");
9137
9138 public:
9139 // Try to keep the size of StringBuilder close to a jemalloc bucket size (the
9140 // 16kb one in this case).
9141 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
9142
9143 // The number of units we need to remove from the inline buffer so that the
9144 // rest of the builder members fit. A more precise approach would be to
9145 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) / sizeof(Unit)
9146 // or so, but this is simpler.
9147 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
9148
9149 static constexpr uint32_t STRING_BUFFER_UNITS =
9150 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
9151
9152 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0)
; }
9153
9154 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0); }
9155
9156 void Append(nsAtom* aAtom) {
9157 Unit* u = AddUnit();
9158 u->mAtom = aAtom;
9159 u->mType = Unit::Type::Atom;
9160 uint32_t len = aAtom->GetLength();
9161 mLength += len;
9162 }
9163
9164 template <int N>
9165 void Append(const char16_t (&aLiteral)[N]) {
9166 constexpr uint32_t len = N - 1;
9167 Unit* u = AddUnit();
9168 u->mLiteral = {aLiteral, len};
9169 u->mType = Unit::Type::Literal;
9170 mLength += len;
9171 }
9172
9173 void Append(nsString&& aString) {
9174 Unit* u = AddUnit();
9175 uint32_t len = aString.Length();
9176 new (&u->mString) nsString(std::move(aString));
9177 u->mType = Unit::Type::String;
9178 mLength += len;
9179 }
9180
9181 // aLen can be !isValid(), which will get propagated into mLength.
9182 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
9183 Unit* u = AddUnit();
9184 new (&u->mString) nsString(std::move(aString));
9185 u->mType = Unit::Type::StringWithEncode;
9186 mLength += aLen;
9187 }
9188
9189 void Append(const nsTextFragment* aTextFragment) {
9190 Unit* u = AddUnit();
9191 u->mTextFragment = aTextFragment;
9192 u->mType = Unit::Type::TextFragment;
9193 uint32_t len = aTextFragment->GetLength();
9194 mLength += len;
9195 }
9196
9197 // aLen can be !isValid(), which will get propagated into mLength.
9198 void AppendWithEncode(const nsTextFragment* aTextFragment,
9199 CheckedInt<uint32_t> aLen) {
9200 Unit* u = AddUnit();
9201 u->mTextFragment = aTextFragment;
9202 u->mType = Unit::Type::TextFragmentWithEncode;
9203 mLength += aLen;
9204 }
9205
9206 bool ToString(nsAString& aOut) {
9207 if (!mLength.isValid()) {
9208 return false;
9209 }
9210 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
9211 if (appenderOrErr.isErr()) {
9212 return false;
9213 }
9214
9215 BulkAppender appender{appenderOrErr.unwrap()};
9216
9217 for (StringBuilder* current = this; current;
9218 current = current->mNext.get()) {
9219 uint32_t len = current->mUnits.Length();
9220 for (uint32_t i = 0; i < len; ++i) {
9221 Unit& u = current->mUnits[i];
9222 switch (u.mType) {
9223 case Unit::Type::Atom:
9224 appender.Append(*(u.mAtom));
9225 break;
9226 case Unit::Type::String:
9227 appender.Append(u.mString);
9228 break;
9229 case Unit::Type::StringWithEncode:
9230 EncodeAttrString(u.mString, appender);
9231 break;
9232 case Unit::Type::Literal:
9233 appender.Append(u.mLiteral.AsSpan());
9234 break;
9235 case Unit::Type::TextFragment:
9236 if (u.mTextFragment->Is2b()) {
9237 appender.Append(
9238 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()));
9239 } else {
9240 appender.Append(
9241 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()));
9242 }
9243 break;
9244 case Unit::Type::TextFragmentWithEncode:
9245 if (u.mTextFragment->Is2b()) {
9246 EncodeTextFragment(
9247 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()),
9248 appender);
9249 } else {
9250 EncodeTextFragment(
9251 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()),
9252 appender);
9253 }
9254 break;
9255 default:
9256 MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9256); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown unit type?"
")"); do { *((volatile int*)__null) = 9256; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9257 }
9258 }
9259 }
9260 appender.Finish();
9261 return true;
9262 }
9263
9264 private:
9265 Unit* AddUnit() {
9266 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
9267 new StringBuilder(this);
9268 }
9269 return mLast->mUnits.AppendElement();
9270 }
9271
9272 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
9273 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0)
;
9274 aFirst->mLast->mNext = WrapUnique(this);
9275 aFirst->mLast = this;
9276 }
9277
9278 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
9279 size_t flushedUntil = 0;
9280 size_t currentPosition = 0;
9281 for (char16_t c : aStr) {
9282 switch (c) {
9283 case '"':
9284 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9285 aAppender.AppendLiteral(u"&quot;");
9286 flushedUntil = currentPosition + 1;
9287 break;
9288 case '&':
9289 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9290 aAppender.AppendLiteral(u"&amp;");
9291 flushedUntil = currentPosition + 1;
9292 break;
9293 case 0x00A0:
9294 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9295 aAppender.AppendLiteral(u"&nbsp;");
9296 flushedUntil = currentPosition + 1;
9297 break;
9298 default:
9299 break;
9300 }
9301 currentPosition++;
9302 }
9303 if (currentPosition > flushedUntil) {
9304 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9305 }
9306 }
9307
9308 template <class T>
9309 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
9310 size_t flushedUntil = 0;
9311 size_t currentPosition = 0;
9312 for (T c : aStr) {
9313 switch (c) {
9314 case '<':
9315 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9316 aAppender.AppendLiteral(u"&lt;");
9317 flushedUntil = currentPosition + 1;
9318 break;
9319 case '>':
9320 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9321 aAppender.AppendLiteral(u"&gt;");
9322 flushedUntil = currentPosition + 1;
9323 break;
9324 case '&':
9325 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9326 aAppender.AppendLiteral(u"&amp;");
9327 flushedUntil = currentPosition + 1;
9328 break;
9329 case T(0xA0):
9330 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9331 aAppender.AppendLiteral(u"&nbsp;");
9332 flushedUntil = currentPosition + 1;
9333 break;
9334 default:
9335 break;
9336 }
9337 currentPosition++;
9338 }
9339 if (currentPosition > flushedUntil) {
9340 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9341 }
9342 }
9343
9344 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
9345 UniquePtr<StringBuilder> mNext;
9346 StringBuilder* mLast;
9347 // mLength is used only in the first StringBuilder object in the linked list.
9348 CheckedInt<uint32_t> mLength;
9349};
9350
9351static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
9352 "StringBuilder should fit in the target bucket");
9353
9354} // namespace
9355
9356static void AppendEncodedCharacters(const nsTextFragment* aText,
9357 StringBuilder& aBuilder) {
9358 uint32_t numEncodedChars = 0;
9359 uint32_t len = aText->GetLength();
9360 if (aText->Is2b()) {
9361 const char16_t* data = aText->Get2b();
9362 for (uint32_t i = 0; i < len; ++i) {
9363 const char16_t c = data[i];
9364 switch (c) {
9365 case '<':
9366 case '>':
9367 case '&':
9368 case 0x00A0:
9369 ++numEncodedChars;
9370 break;
9371 default:
9372 break;
9373 }
9374 }
9375 } else {
9376 const char* data = aText->Get1b();
9377 for (uint32_t i = 0; i < len; ++i) {
9378 const unsigned char c = data[i];
9379 switch (c) {
9380 case '<':
9381 case '>':
9382 case '&':
9383 case 0x00A0:
9384 ++numEncodedChars;
9385 break;
9386 default:
9387 break;
9388 }
9389 }
9390 }
9391
9392 if (numEncodedChars) {
9393 // For simplicity, conservatively estimate the size of the string after
9394 // encoding. This will result in reserving more memory than we actually
9395 // need, but that should be fine unless the string has an enormous number of
9396 // eg < in it. We subtract 1 for the null terminator, then 1 more for the
9397 // existing character that will be replaced.
9398 constexpr uint32_t maxCharExtraSpace =
9399 std::max({std::size("&lt;"), std::size("&gt;"), std::size("&amp;"),
9400 std::size("&nbsp;")}) -
9401 2;
9402 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9403 CheckedInt<uint32_t> maxExtraSpace =
9404 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9405 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
9406 } else {
9407 aBuilder.Append(aText);
9408 }
9409}
9410
9411static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
9412 const nsAString& aValue) {
9413 const char16_t* c = aValue.BeginReading();
9414 const char16_t* end = aValue.EndReading();
9415
9416 uint32_t numEncodedChars = 0;
9417 while (c < end) {
9418 switch (*c) {
9419 case '"':
9420 case '&':
9421 case 0x00A0:
9422 ++numEncodedChars;
9423 break;
9424 default:
9425 break;
9426 }
9427 ++c;
9428 }
9429
9430 if (!numEncodedChars) {
9431 return 0;
9432 }
9433
9434 // For simplicity, conservatively estimate the size of the string after
9435 // encoding. This will result in reserving more memory than we actually
9436 // need, but that should be fine unless the string has an enormous number of
9437 // & in it. We subtract 1 for the null terminator, then 1 more for the
9438 // existing character that will be replaced.
9439 constexpr uint32_t maxCharExtraSpace =
9440 std::max({std::size("&quot;"), std::size("&amp;"), std::size("&nbsp;")}) -
9441 2;
9442 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9443 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9444}
9445
9446static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
9447 StringBuilder& aBuilder) {
9448 if (nsAtom* atom = aValue.GetStoredAtom()) {
9449 nsDependentAtomString atomStr(atom);
9450 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
9451 if (space.isValid() && !space.value()) {
9452 aBuilder.Append(atom);
9453 } else {
9454 aBuilder.AppendWithAttrEncode(nsString(atomStr),
9455 space + atomStr.Length());
9456 }
9457 return;
9458 }
9459 // NOTE(emilio): In most cases this will just be a reference to the stored
9460 // nsStringBuffer.
9461 nsString str;
9462 aValue.ToString(str);
9463 auto space = ExtraSpaceNeededForAttrEncoding(str);
9464 if (!space.isValid() || space.value()) {
9465 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
9466 } else {
9467 aBuilder.Append(std::move(str));
9468 }
9469}
9470
9471static void StartElement(Element* aElement, StringBuilder& aBuilder) {
9472 nsAtom* localName = aElement->NodeInfo()->NameAtom();
9473 const int32_t tagNS = aElement->GetNameSpaceID();
9474
9475 aBuilder.Append(u"<");
9476 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
9477 tagNS == kNameSpaceID_MathML6) {
9478 aBuilder.Append(localName);
9479 } else {
9480 aBuilder.Append(nsString(aElement->NodeName()));
9481 }
9482
9483 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
9484 nsAtom* isAttr = ceData->GetIs(aElement);
9485 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
9486 aBuilder.Append(uR"( is=")");
9487 aBuilder.Append(isAttr);
9488 aBuilder.Append(uR"(")");
9489 }
9490 }
9491
9492 uint32_t i = 0;
9493 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
9494 const nsAttrName* name = info.mName;
9495
9496 int32_t attNs = name->NamespaceID();
9497 nsAtom* attName = name->LocalName();
9498
9499 // Filter out any attribute starting with [-|_]moz
9500 // FIXME(emilio): Do we still need this?
9501 nsDependentAtomString attrNameStr(attName);
9502 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
9503 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
9504 continue;
9505 }
9506
9507 aBuilder.Append(u" ");
9508
9509 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
9510 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
9511 // Nothing else required
9512 } else if (attNs == kNameSpaceID_XML2) {
9513 aBuilder.Append(u"xml:");
9514 } else if (attNs == kNameSpaceID_XMLNS1) {
9515 aBuilder.Append(u"xmlns:");
9516 } else if (attNs == kNameSpaceID_XLink4) {
9517 aBuilder.Append(u"xlink:");
9518 } else if (nsAtom* prefix = name->GetPrefix()) {
9519 aBuilder.Append(prefix);
9520 aBuilder.Append(u":");
9521 }
9522
9523 aBuilder.Append(attName);
9524 aBuilder.Append(uR"(=")");
9525 AppendEncodedAttributeValue(*info.mValue, aBuilder);
9526 aBuilder.Append(uR"(")");
9527 }
9528
9529 aBuilder.Append(u">");
9530
9531 /*
9532 // Per HTML spec we should append one \n if the first child of
9533 // pre/textarea/listing is a textnode and starts with a \n.
9534 // But because browsers haven't traditionally had that behavior,
9535 // we're not changing our behavior either - yet.
9536 if (aContent->IsHTMLElement()) {
9537 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
9538 localName == nsGkAtoms::listing) {
9539 nsIContent* fc = aContent->GetFirstChild();
9540 if (fc &&
9541 (fc->NodeType() == nsINode::TEXT_NODE ||
9542 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
9543 const nsTextFragment* text = fc->GetText();
9544 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
9545 aBuilder.Append("\n");
9546 }
9547 }
9548 }
9549 }*/
9550}
9551
9552static inline bool ShouldEscape(nsIContent* aParent) {
9553 if (!aParent || !aParent->IsHTMLElement()) {
9554 return true;
9555 }
9556
9557 static const nsAtom* nonEscapingElements[] = {
9558 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
9559 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
9560 nsGkAtoms::plaintext, nsGkAtoms::noscript};
9561 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
9562 static bool sInitialized = false;
9563 if (!sInitialized) {
9564 sInitialized = true;
9565 for (auto& nonEscapingElement : nonEscapingElements) {
9566 sFilter.add(nonEscapingElement);
9567 }
9568 }
9569
9570 nsAtom* tag = aParent->NodeInfo()->NameAtom();
9571 if (sFilter.mightContain(tag)) {
9572 for (auto& nonEscapingElement : nonEscapingElements) {
9573 if (tag == nonEscapingElement) {
9574 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
9575 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
9576 return true;
9577 }
9578 return false;
9579 }
9580 }
9581 }
9582 return true;
9583}
9584
9585static inline bool IsVoidTag(Element* aElement) {
9586 if (!aElement->IsHTMLElement()) {
9587 return false;
9588 }
9589 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
9590}
9591
9592static bool StartSerializingShadowDOM(
9593 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
9594 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9595 ShadowRoot* shadow = aNode->GetShadowRoot();
9596 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
9597 !aShadowRoots.Contains(shadow))) {
9598 return false;
9599 }
9600
9601 aBuilder.Append(u"<template shadowrootmode=\"");
9602 if (shadow->IsClosed()) {
9603 aBuilder.Append(u"closed\"");
9604 } else {
9605 aBuilder.Append(u"open\"");
9606 }
9607
9608 if (shadow->DelegatesFocus()) {
9609 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
9610 }
9611 if (shadow->Serializable()) {
9612 aBuilder.Append(u" shadowrootserializable=\"\"");
9613 }
9614 if (shadow->Clonable()) {
9615 aBuilder.Append(u" shadowrootclonable=\"\"");
9616 }
9617
9618 aBuilder.Append(u">");
9619
9620 if (!shadow->HasChildren()) {
9621 aBuilder.Append(u"</template>");
9622 return false;
9623 }
9624 return true;
9625}
9626
9627template <SerializeShadowRoots ShouldSerializeShadowRoots>
9628static void SerializeNodeToMarkupInternal(
9629 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
9630 bool aSerializableShadowRoots,
9631 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9632 nsINode* current =
9633 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
9634 if (!current) {
9635 return;
9636 }
9637
9638 nsIContent* next;
9639 while (true) {
9640 bool isVoid = false;
9641 switch (current->NodeType()) {
9642 case nsINode::ELEMENT_NODE: {
9643 Element* elem = current->AsElement();
9644 StartElement(elem, aBuilder);
9645
9646 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9647 if (StartSerializingShadowDOM(
9648 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
9649 current = current->GetShadowRoot()->GetFirstChild();
9650 continue;
9651 }
9652 }
9653
9654 isVoid = IsVoidTag(elem);
9655 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
9656 current = next;
9657 continue;
9658 }
9659 break;
9660 }
9661
9662 case nsINode::TEXT_NODE:
9663 case nsINode::CDATA_SECTION_NODE: {
9664 const nsTextFragment* text = &current->AsText()->TextFragment();
9665 nsIContent* parent = current->GetParent();
9666 if (ShouldEscape(parent)) {
9667 AppendEncodedCharacters(text, aBuilder);
9668 } else {
9669 aBuilder.Append(text);
9670 }
9671 break;
9672 }
9673
9674 case nsINode::COMMENT_NODE: {
9675 aBuilder.Append(u"<!--");
9676 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9677 aBuilder.Append(u"-->");
9678 break;
9679 }
9680
9681 case nsINode::DOCUMENT_TYPE_NODE: {
9682 aBuilder.Append(u"<!DOCTYPE ");
9683 aBuilder.Append(nsString(current->NodeName()));
9684 aBuilder.Append(u">");
9685 break;
9686 }
9687
9688 case nsINode::PROCESSING_INSTRUCTION_NODE: {
9689 aBuilder.Append(u"<?");
9690 aBuilder.Append(nsString(current->NodeName()));
9691 aBuilder.Append(u" ");
9692 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9693 aBuilder.Append(u">");
9694 break;
9695 }
9696 }
9697
9698 while (true) {
9699 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
9700 aBuilder.Append(u"</");
9701 nsIContent* elem = static_cast<nsIContent*>(current);
9702 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
9703 elem->IsMathMLElement()) {
9704 aBuilder.Append(elem->NodeInfo()->NameAtom());
9705 } else {
9706 aBuilder.Append(nsString(current->NodeName()));
9707 }
9708 aBuilder.Append(u">");
9709 }
9710 isVoid = false;
9711
9712 if (current == aRoot) {
9713 return;
9714 }
9715
9716 if ((next = current->GetNextSibling())) {
9717 current = next;
9718 break;
9719 }
9720
9721 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9722 // If the current node is a shadow root, then we must go to its host.
9723 // Since shadow DOMs are serialized declaratively as template elements,
9724 // we serialize the end tag of the template before going back to
9725 // serializing the shadow host.
9726 if (current->IsShadowRoot()) {
9727 current = current->GetContainingShadowHost();
9728 aBuilder.Append(u"</template>");
9729
9730 if (current->HasChildren()) {
9731 current = current->GetFirstChildOfTemplateOrNode();
9732 break;
9733 }
9734 continue;
9735 }
9736 }
9737
9738 current = current->GetParentNode();
9739
9740 // Handle template element. If the parent is a template's content,
9741 // then adjust the parent to be the template element.
9742 if (current != aRoot &&
9743 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
9744 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
9745 nsIContent* fragHost = frag->GetHost();
9746 if (fragHost && fragHost->IsTemplateElement()) {
9747 current = fragHost;
9748 }
9749 }
9750
9751 if (aDescendantsOnly && current == aRoot) {
9752 return;
9753 }
9754 }
9755 }
9756}
9757
9758template <SerializeShadowRoots ShouldSerializeShadowRoots>
9759bool nsContentUtils::SerializeNodeToMarkup(
9760 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9761 bool aSerializableShadowRoots,
9762 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9763 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
9764 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { *((volatile int*)__null) = 9764; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9765
9766 StringBuilder builder;
9767 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9768 if (aDescendantsOnly &&
9769 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
9770 aShadowRoots)) {
9771 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
9772 aRoot->GetShadowRoot()->GetFirstChild(), false, builder,
9773 aSerializableShadowRoots, aShadowRoots);
9774 // The template tag is opened in StartSerializingShadowDOM, so we need
9775 // to close it here before serializing any children of aRoot.
9776 builder.Append(u"</template>");
9777 }
9778 }
9779
9780 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
9781 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
9782 return builder.ToString(aOut);
9783}
9784
9785template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
9786 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9787 bool aSerializableShadowRoots,
9788 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9789template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
9790 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9791 bool aSerializableShadowRoots,
9792 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9793
9794bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
9795 // aUri must start with about: or this isn't the right function to be using.
9796 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { *((volatile int*)__null) = 9796; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9797
9798 // Make sure the global is a window
9799 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9799); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)"
")"); do { *((volatile int*)__null) = 9799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9800 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
9801 if (!win) {
9802 return false;
9803 }
9804
9805 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
9806 NS_ENSURE_TRUE(principal, false)do { if ((__builtin_expect(!!(!(principal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9806); return false; } } while (false)
;
9807
9808 // First check the scheme to avoid getting long specs in the common case.
9809 if (!principal->SchemeIs("about")) {
9810 return false;
9811 }
9812
9813 nsAutoCString spec;
9814 principal->GetAsciiSpec(spec);
9815
9816 return spec.EqualsASCII(aUri);
9817}
9818
9819/* static */
9820void nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell,
9821 bool aVisible) {
9822 if (!aDocShell) {
9823 return;
9824 }
9825 auto pref = aVisible ? ScrollbarPreference::Auto : ScrollbarPreference::Never;
9826 nsDocShell::Cast(aDocShell)->SetScrollbarPreference(pref);
9827}
9828
9829/* static */
9830nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
9831 if (!aTarget) {
9832 return nullptr;
9833 }
9834
9835 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
9836 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
9837 bool ignore;
9838 innerWindow =
9839 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
9840 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
9841 // Nothing else to do
9842 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
9843 do_QueryInterface(aTarget)) {
9844 innerWindow = helper->GetOwnerWindow();
9845 }
9846
9847 if (innerWindow) {
9848 return innerWindow->GetDocShell();
9849 }
9850
9851 return nullptr;
9852}
9853
9854/*
9855 * Note: this function only relates to figuring out HTTPS state, which is an
9856 * input to the Secure Context algorithm. We are not actually implementing any
9857 * part of the Secure Context algorithm itself here.
9858 *
9859 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
9860 * nsIChannel as described in the Fetch and HTML specs, but making channels
9861 * know about whether they should inherit HTTPS state, propagating information
9862 * about who the channel's "client" is, exposing GetHttpsState API on channels
9863 * and modifying the various cache implementations to store and retrieve HTTPS
9864 * state involves a huge amount of code (see bug 1220687). We avoid that for
9865 * now using this function.
9866 *
9867 * This function takes advantage of the observation that we can return true if
9868 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
9869 * the document's origin (e.g. the origin has a scheme of 'https' or host
9870 * 'localhost' etc.). Since we generally propagate a creator document's origin
9871 * onto data:, blob:, etc. documents, this works for them too.
9872 *
9873 * The scenario where this observation breaks down is sandboxing without the
9874 * 'allow-same-origin' flag, since in this case a document is given a unique
9875 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
9876 * by using the origin that the document would have had had it not been
9877 * sandboxed.
9878 *
9879 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
9880 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
9881 * sandboxing is limited to the immediate sandbox. In the case that aDocument
9882 * should inherit its origin (e.g. data: URI) but its parent has ended up
9883 * with a unique origin due to sandboxing further up the parent chain we may
9884 * end up returning false when we would ideally return true (since we will
9885 * examine the parent's origin for 'https' and not finding it.) This means
9886 * that we may restrict the privileges of some pages unnecessarily in this
9887 * edge case.
9888 */
9889/* static */
9890bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
9891 if (!aDocument) {
9892 return false;
9893 }
9894
9895 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
9896
9897 if (principal->IsSystemPrincipal()) {
9898 return true;
9899 }
9900
9901 // If aDocument is sandboxed, try and get the principal that it would have
9902 // been given had it not been sandboxed:
9903 if (principal->GetIsNullPrincipal() &&
9904 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
9905 nsIChannel* channel = aDocument->GetChannel();
9906 if (channel) {
9907 nsCOMPtr<nsIScriptSecurityManager> ssm =
9908 nsContentUtils::GetSecurityManager();
9909 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
9910 channel, getter_AddRefs(principal));
9911 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9912 return false;
9913 }
9914 if (principal->IsSystemPrincipal()) {
9915 // If a document with the system principal is sandboxing a subdocument
9916 // that would normally inherit the embedding element's principal (e.g.
9917 // a srcdoc document) then the embedding document does not trust the
9918 // content that is written to the embedded document. Unlike when the
9919 // embedding document is https, in this case we have no indication as
9920 // to whether the embedded document's contents are delivered securely
9921 // or not, and the sandboxing would possibly indicate that they were
9922 // not. To play it safe we return false here. (See bug 1162772
9923 // comment 73-80.)
9924 return false;
9925 }
9926 }
9927 }
9928
9929 if (principal->GetIsNullPrincipal()) {
9930 return false;
9931 }
9932
9933 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()"
")"); do { *((volatile int*)__null) = 9933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9934
9935 return principal->GetIsOriginPotentiallyTrustworthy();
9936}
9937
9938/* static */
9939bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
9940 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { *((volatile int*)__null) = 9940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9941
9942 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
9943 nsCOMPtr<nsIPrincipal> principal;
9944 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
9945 aChannel, getter_AddRefs(principal));
9946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9947 return false;
9948 }
9949
9950 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9951
9952 if (principal->IsSystemPrincipal()) {
9953 // If the load would've been sandboxed, treat this load as an untrusted
9954 // load, as system code considers sandboxed resources insecure.
9955 return !loadInfo->GetLoadingSandboxed();
9956 }
9957
9958 if (principal->GetIsNullPrincipal()) {
9959 return false;
9960 }
9961
9962 if (const RefPtr<WindowContext> windowContext =
9963 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
9964 if (!windowContext->GetIsSecureContext()) {
9965 return false;
9966 }
9967 }
9968
9969 return principal->GetIsOriginPotentiallyTrustworthy();
9970}
9971
9972/* static */
9973void nsContentUtils::TryToUpgradeElement(Element* aElement) {
9974 NodeInfo* nodeInfo = aElement->NodeInfo();
9975 RefPtr<nsAtom> typeAtom =
9976 aElement->GetCustomElementData()->GetCustomElementType();
9977
9978 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 9978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 9978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9979 CustomElementDefinition* definition =
9980 nsContentUtils::LookupCustomElementDefinition(
9981 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
9982 nodeInfo->NamespaceID(), typeAtom);
9983 if (definition) {
9984 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
9985 } else {
9986 // Add an unresolved custom element that is a candidate for upgrade when a
9987 // custom element is connected to the document.
9988 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
9989 }
9990}
9991
9992MOZ_CAN_RUN_SCRIPT
9993static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
9994 Document* aDoc, NodeInfo* aNodeInfo,
9995 CustomElementConstructor* aConstructor,
9996 ErrorResult& aRv, FromParser aFromParser) {
9997 JS::Rooted<JS::Value> constructResult(aCx);
9998 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
9999 CallbackFunction::eRethrowExceptions);
10000 if (aRv.Failed()) {
10001 return;
10002 }
10003
10004 RefPtr<Element> element;
10005 // constructResult is an ObjectValue because construction with a callback
10006 // always forms the return value from a JSObject.
10007 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
10008 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10009 if (!element || !element->IsHTMLElement()) {
10010 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10011 "HTMLElement");
10012 return;
10013 }
10014 } else {
10015 if (!element || !element->IsXULElement()) {
10016 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10017 "XULElement");
10018 return;
10019 }
10020 }
10021
10022 nsAtom* localName = aNodeInfo->NameAtom();
10023
10024 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
10025 element->HasChildren() || element->GetAttrCount() ||
10026 element->NodeInfo()->NameAtom() != localName) {
10027 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
10028 return;
10029 }
10030
10031 if (element->IsHTMLElement()) {
10032 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
10033 !(aFromParser & FROM_PARSER_NETWORK));
10034 }
10035
10036 element.forget(aElement);
10037}
10038
10039/* static */
10040nsresult nsContentUtils::NewXULOrHTMLElement(
10041 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
10042 FromParser aFromParser, nsAtom* aIsAtom,
10043 mozilla::dom::CustomElementDefinition* aDefinition) {
10044 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
10045 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10047; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
10046 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10047; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10047 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10047; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10048
10049 nsAtom* name = nodeInfo->NameAtom();
10050 int32_t tag = eHTMLTag_unknown;
10051 bool isCustomElementName = false;
10052 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
3
Taking false branch
10053 tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
10054 isCustomElementName =
10055 (tag == eHTMLTag_userdefined &&
10056 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
10057 } else { // kNameSpaceID_XUL
10058 if (aIsAtom) {
4
Assuming 'aIsAtom' is null
5
Taking false branch
10059 // Make sure the customized built-in element to be constructed confirms
10060 // to our naming requirement, i.e. [is] must be a dashed name and
10061 // the tag name must not.
10062 // if so, set isCustomElementName to false to kick off all the logics
10063 // that pick up aIsAtom.
10064 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
10065 !nsContentUtils::IsNameWithDash(name)) {
10066 isCustomElementName = false;
10067 } else {
10068 isCustomElementName =
10069 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10070 }
10071 } else {
10072 isCustomElementName =
10073 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10074 }
10075 }
10076
10077 nsAtom* tagAtom = nodeInfo->NameAtom();
10078 nsAtom* typeAtom = nullptr;
10079 bool isCustomElement = isCustomElementName
5.1
'isCustomElementName' is true
|| aIsAtom;
10080 if (isCustomElement
5.2
'isCustomElement' is true
) {
10081 typeAtom = isCustomElementName
6.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
6
Taking true branch
7
'?' condition is true
10082 }
10083
10084 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { *((volatile int*)__null) = 10084; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
8
Assuming 'aDefinition' is non-null
9
Taking true branch
10
Taking false branch
11
Loop condition is false. Exiting loop
12
Loop condition is false. Exiting loop
10085
10086 // https://dom.spec.whatwg.org/#concept-create-element
10087 // We only handle the "synchronous custom elements flag is set" now.
10088 // For the unset case (e.g. cloning a node), see bug 1319342 for that.
10089 // Step 4.
10090 RefPtr<CustomElementDefinition> definition = aDefinition;
10091 if (isCustomElement
12.1
'isCustomElement' is true
&& !definition) {
13
Taking false branch
10092 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10092); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 10092; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10093 definition = nsContentUtils::LookupCustomElementDefinition(
10094 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
10095 typeAtom);
10096 }
10097
10098 // It might be a problem that parser synchronously calls constructor, so filed
10099 // bug 1378079 to figure out what we should do for parser case.
10100 if (definition) {
14
Taking true branch
10101 /*
10102 * Synchronous custom elements flag is determined by 3 places in spec,
10103 * 1) create an element for a token, the flag is determined by
10104 * "will execute script" which is not originally created
10105 * for the HTML fragment parsing algorithm.
10106 * 2) createElement and createElementNS, the flag is the same as
10107 * NOT_FROM_PARSER.
10108 * 3) clone a node, our implementation will not go into this function.
10109 * For the unset case which is non-synchronous only applied for
10110 * inner/outerHTML.
10111 */
10112 bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT;
15
Assuming 'aFromParser' is not equal to FROM_PARSER_FRAGMENT
10113 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
10114 // use entry global in those places that are called from JS APIs and use the
10115 // node document's global object if it is called from parser.
10116 nsIGlobalObject* global;
10117 if (aFromParser == dom::NOT_FROM_PARSER) {
16
Assuming 'aFromParser' is equal to NOT_FROM_PARSER
17
Taking true branch
10118 global = GetEntryGlobal();
10119
10120 // Documents created from the PrototypeDocumentSink always use
10121 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
10122 // document in that case.
10123 if (!global) {
18
Assuming 'global' is non-null
19
Taking false branch
10124 Document* doc = nodeInfo->GetDocument();
10125 if (doc && doc->LoadedFromPrototype()) {
10126 global = doc->GetScopeObject();
10127 }
10128 }
10129 } else {
10130 global = nodeInfo->GetDocument()->GetScopeObject();
10131 }
10132 if (!global
19.1
'global' is non-null
) {
20
Taking false branch
10133 // In browser chrome code, one may have access to a document which doesn't
10134 // have scope object anymore.
10135 return NS_ERROR_FAILURE;
10136 }
10137
10138 AutoAllowLegacyScriptExecution exemption;
10139 AutoEntryScript aes(global, "create custom elements");
10140 JSContext* cx = aes.cx();
10141 ErrorResult rv;
10142
10143 // Step 5.
10144 if (definition->IsCustomBuiltIn()) {
21
Taking true branch
10145 // SetupCustomElement() should be called with an element that don't have
10146 // CustomElementData setup, if not we will hit the assertion in
10147 // SetCustomElementData().
10148 // Built-in element
10149 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
22
Taking false branch
10150 *aResult =
10151 CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10152 } else {
10153 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
23
Assigning value
10154 }
10155 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
24
Called C++ object pointer is null
10156 if (synchronousCustomElements) {
10157 CustomElementRegistry::Upgrade(*aResult, definition, rv);
10158 if (rv.MaybeSetPendingException(cx)) {
10159 aes.ReportException();
10160 }
10161 } else {
10162 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10163 }
10164
10165 return NS_OK;
10166 }
10167
10168 // Step 6.1.
10169 if (synchronousCustomElements) {
10170 definition->mPrefixStack.AppendElement(nodeInfo->GetPrefixAtom());
10171 RefPtr<Document> doc = nodeInfo->GetDocument();
10172 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
10173 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
10174 aFromParser);
10175 if (rv.MaybeSetPendingException(cx)) {
10176 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10177 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
10178 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
10179 } else {
10180 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10181 }
10182 (*aResult)->SetDefined(false);
10183 }
10184 definition->mPrefixStack.RemoveLastElement();
10185 return NS_OK;
10186 }
10187
10188 // Step 6.2.
10189 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10190 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10191 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10192 } else {
10193 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10194 }
10195 (*aResult)->SetCustomElementData(
10196 MakeUnique<CustomElementData>(definition->mType));
10197 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10198 return NS_OK;
10199 }
10200
10201 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10202 // Per the Custom Element specification, unknown tags that are valid custom
10203 // element names should be HTMLElement instead of HTMLUnknownElement.
10204 if (isCustomElementName) {
10205 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10206 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10207 } else {
10208 *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10209 }
10210 } else {
10211 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10212 }
10213
10214 if (!*aResult) {
10215 return NS_ERROR_OUT_OF_MEMORY;
10216 }
10217
10218 if (isCustomElement) {
10219 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
10220 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
10221 }
10222
10223 return NS_OK;
10224}
10225
10226CustomElementRegistry* nsContentUtils::GetCustomElementRegistry(
10227 Document* aDoc) {
10228 MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")")
; do { *((volatile int*)__null) = 10228; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10229
10230 if (!aDoc->GetDocShell()) {
10231 return nullptr;
10232 }
10233
10234 nsPIDOMWindowInner* window = aDoc->GetInnerWindow();
10235 if (!window) {
10236 return nullptr;
10237 }
10238
10239 return window->CustomElements();
10240}
10241
10242/* static */
10243CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
10244 Document* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
10245 nsAtom* aTypeAtom) {
10246 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
10247 return nullptr;
10248 }
10249
10250 RefPtr<CustomElementRegistry> registry = GetCustomElementRegistry(aDoc);
10251 if (!registry) {
10252 return nullptr;
10253 }
10254
10255 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
10256 aTypeAtom);
10257}
10258
10259/* static */
10260void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
10261 nsAtom* aTypeName) {
10262 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10262; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10263
10264 Document* doc = aElement->OwnerDoc();
10265 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10266 if (registry) {
10267 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
10268 }
10269}
10270
10271/* static */
10272void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
10273 nsAtom* aTypeName) {
10274 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10274); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10274; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10275
10276 Document* doc = aElement->OwnerDoc();
10277 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10278 if (registry) {
10279 registry->RegisterUnresolvedElement(aElement, aTypeName);
10280 }
10281}
10282
10283/* static */
10284void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
10285 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10285; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10286
10287 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
10288 Document* doc = aElement->OwnerDoc();
10289 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10290 if (registry) {
10291 registry->UnregisterUnresolvedElement(aElement, typeAtom);
10292 }
10293}
10294
10295/* static */
10296void nsContentUtils::EnqueueUpgradeReaction(
10297 Element* aElement, CustomElementDefinition* aDefinition) {
10298 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10298); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10298; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10299
10300 Document* doc = aElement->OwnerDoc();
10301
10302 // No DocGroup means no custom element reactions stack.
10303 if (!doc->GetDocGroup()) {
10304 return;
10305 }
10306
10307 CustomElementReactionsStack* stack =
10308 doc->GetDocGroup()->CustomElementReactionsStack();
10309 stack->EnqueueUpgradeReaction(aElement, aDefinition);
10310}
10311
10312/* static */
10313void nsContentUtils::EnqueueLifecycleCallback(
10314 ElementCallbackType aType, Element* aCustomElement,
10315 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
10316 // No DocGroup means no custom element reactions stack.
10317 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
10318 return;
10319 }
10320
10321 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
10322 aDefinition);
10323}
10324
10325/* static */
10326CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
10327 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
10328 if (aState.IsNull()) {
10329 return void_t{};
10330 }
10331 const auto& state = aState.Value();
10332 if (state.IsFile()) {
10333 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
10334 return {std::move(impl)};
10335 }
10336 if (state.IsUSVString()) {
10337 return state.GetAsUSVString();
10338 }
10339 return state.GetAsFormData()->ConvertToCustomElementFormValue();
10340}
10341
10342/* static */
10343Nullable<OwningFileOrUSVStringOrFormData>
10344nsContentUtils::ExtractFormAssociatedCustomElementValue(
10345 nsIGlobalObject* aGlobal,
10346 const mozilla::dom::CustomElementFormValue& aCEValue) {
10347 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { *((volatile int*)__null) = 10347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10348
10349 OwningFileOrUSVStringOrFormData value;
10350 switch (aCEValue.type()) {
10351 case CustomElementFormValue::TBlobImpl: {
10352 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
10353 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10353)
) {
10354 return {};
10355 }
10356 value.SetAsFile() = file;
10357 } break;
10358
10359 case CustomElementFormValue::TnsString:
10360 value.SetAsUSVString() = aCEValue.get_nsString();
10361 break;
10362
10363 case CustomElementFormValue::TArrayOfFormDataTuple: {
10364 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
10365 auto formData = MakeRefPtr<FormData>();
10366
10367 for (auto i = 0ul; i < array.Length(); ++i) {
10368 const auto& item = array.ElementAt(i);
10369 switch (item.value().type()) {
10370 case FormDataValue::TnsString:
10371 formData->AddNameValuePair(item.name(),
10372 item.value().get_nsString());
10373 break;
10374
10375 case FormDataValue::TBlobImpl: {
10376 auto blobImpl = item.value().get_BlobImpl();
10377 auto* blob = Blob::Create(aGlobal, blobImpl);
10378 formData->AddNameBlobPair(item.name(), blob);
10379 } break;
10380
10381 default:
10382 continue;
10383 }
10384 }
10385
10386 value.SetAsFormData() = formData;
10387 } break;
10388 case CustomElementFormValue::Tvoid_t:
10389 return {};
10390 default:
10391 NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10391)
;
10392 return {};
10393 }
10394 return value;
10395}
10396
10397/* static */
10398void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
10399 Document* aDocument, nsTArray<nsIContent*>& aElements) {
10400 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10400); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { *((volatile int*)__null) = 10400; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10401#ifdef DEBUG1
10402 size_t oldLength = aElements.Length();
10403#endif
10404
10405 if (PresShell* presShell = aDocument->GetPresShell()) {
10406 if (ScrollContainerFrame* rootScrollContainerFrame =
10407 presShell->GetRootScrollContainerFrame()) {
10408 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
10409 }
10410 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
10411 canvasFrame->AppendAnonymousContentTo(aElements, 0);
10412 }
10413 }
10414
10415#ifdef DEBUG1
10416 for (size_t i = oldLength; i < aElements.Length(); i++) {
10417 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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10419; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10418 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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10419; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10419 "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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10419; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10420 }
10421#endif
10422}
10423
10424static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
10425 nsTArray<nsIContent*>& aKids,
10426 uint32_t aFlags) {
10427 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
10428 ac->AppendAnonymousContentTo(aKids, aFlags);
10429 }
10430}
10431
10432/* static */
10433void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
10434 nsTArray<nsIContent*>& aKids,
10435 uint32_t aFlags) {
10436 if (aContent->MayHaveAnonymousChildren()) {
10437 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
10438 // NAC created by the element's primary frame.
10439 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
10440
10441 // NAC created by any other non-primary frames for the element.
10442 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
10443 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
10444 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
10445 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { *((volatile int*)__null) = 10445; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10446 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
10447 aFlags);
10448 }
10449 }
10450
10451 // View transition pseudos.
10452 if (aContent->IsRootElement()) {
10453 if (auto* vt = aContent->OwnerDoc()->GetActiveViewTransition()) {
10454 if (auto* root = vt->GetRoot()) {
10455 aKids.AppendElement(root);
10456 }
10457 }
10458 }
10459
10460 // Get manually created NAC (editor resize handles, etc.).
10461 if (auto nac = static_cast<ManualNACArray*>(
10462 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
10463 aKids.AppendElements(*nac);
10464 }
10465 }
10466
10467 // The root scroll frame is not the primary frame of the root element.
10468 // Detect and handle this case.
10469 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
10470 aContent->IsRootElement()) {
10471 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
10472 }
10473}
10474
10475bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
10476 nsIPrincipal* aDefaultTriggeringPrincipal,
10477 CORSMode aCORSMode) {
10478 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10479 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
10480 getter_AddRefs(triggeringPrincipal));
10481 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10481); AnnotateMozCrashReason("MOZ_ASSERT" "(" "triggeringPrincipal"
")"); do { *((volatile int*)__null) = 10481; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10482
10483 Document* doc = aLoadingNode->OwnerDoc();
10484 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
10485}
10486
10487bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
10488 nsIPrincipal* aTriggeringPrincipal,
10489 CORSMode aCORSMode, Document* aDoc) {
10490 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
10491 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
10492 aDoc);
10493}
10494
10495/* static */
10496bool nsContentUtils::QueryTriggeringPrincipal(
10497 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
10498 nsIPrincipal** aTriggeringPrincipal) {
10499 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10499); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { *((volatile int*)__null) = 10499; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10500 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10500); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
")"); do { *((volatile int*)__null) = 10500; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10501
10502 bool result = false;
10503 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
10504 if (!loadingPrincipal) {
10505 loadingPrincipal = aLoadingNode->NodePrincipal();
10506 }
10507
10508 // If aLoadingNode is content, bail out early.
10509 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
10510 loadingPrincipal.forget(aTriggeringPrincipal);
10511 return result;
10512 }
10513
10514 nsAutoString loadingStr;
10515 if (aLoadingNode->IsElement()) {
10516 aLoadingNode->AsElement()->GetAttr(
10517 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
10518 }
10519
10520 // Fall back if 'triggeringprincipal' isn't specified,
10521 if (loadingStr.IsEmpty()) {
10522 loadingPrincipal.forget(aTriggeringPrincipal);
10523 return result;
10524 }
10525
10526 nsCString binary;
10527 nsCOMPtr<nsIPrincipal> serializedPrin =
10528 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
10529 if (serializedPrin) {
10530 result = true;
10531 serializedPrin.forget(aTriggeringPrincipal);
10532 }
10533
10534 if (!result) {
10535 // Fallback if the deserialization is failed.
10536 loadingPrincipal.forget(aTriggeringPrincipal);
10537 }
10538
10539 return result;
10540}
10541
10542/* static */
10543void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
10544 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
10545 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
10546 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequestContextID"
")"); do { *((volatile int*)__null) = 10546; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10547
10548 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
10549 if (result) {
10550 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
10551 // indicating it's a favicon loading.
10552 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
10553
10554 nsAutoString requestContextID;
10555 if (aLoadingNode->IsElement()) {
10556 aLoadingNode->AsElement()->GetAttr(
10557 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
10558 }
10559 nsresult rv;
10560 int64_t val = requestContextID.ToInteger64(&rv);
10561 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
10562 } else {
10563 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
10564 }
10565}
10566
10567/* static */
10568nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
10569 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
10570 JS::MutableHandle<JS::Value> aValue) {
10571 if (aTransfer.IsEmpty()) {
10572 return NS_OK;
10573 }
10574
10575 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
10576 if (!array) {
10577 return NS_ERROR_OUT_OF_MEMORY;
10578 }
10579
10580 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
10581 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
10582 if (!object) {
10583 continue;
10584 }
10585
10586 if (NS_WARN_IF(NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE
), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10587)
10587 !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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10587)
) {
10588 return NS_ERROR_OUT_OF_MEMORY;
10589 }
10590 }
10591
10592 aValue.setObject(*array);
10593 return NS_OK;
10594}
10595
10596/* static */
10597void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
10598 JS::Handle<JS::Value> aValue,
10599 const StructuredSerializeOptions& aOptions,
10600 JS::MutableHandle<JS::Value> aRetval,
10601 ErrorResult& aError) {
10602 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
10603 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
10604 aCx, aOptions.mTransfer, &transferArray);
10605 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10605)
) {
10606 return;
10607 }
10608
10609 JS::CloneDataPolicy clonePolicy;
10610 // We are definitely staying in the same agent cluster.
10611 clonePolicy.allowIntraClusterClonableSharedObjects();
10612 if (aGlobal->IsSharedMemoryAllowed()) {
10613 clonePolicy.allowSharedMemoryObjects();
10614 }
10615
10616 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
10617 StructuredCloneHolder::TransferringSupported,
10618 JS::StructuredCloneScope::SameProcess);
10619 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
10620 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10620)
) {
10621 return;
10622 }
10623
10624 holder.Read(aGlobal, aCx, aRetval, clonePolicy, aError);
10625 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10625)
) {
10626 return;
10627 }
10628
10629 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
10630 Unused << ports;
10631}
10632
10633/* static */
10634bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
10635 nsCOMPtr<nsIPrincipal> principal;
10636 RefPtr<Element> targetElement =
10637 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
10638 nsCOMPtr<nsIBrowser> targetBrowser;
10639 if (targetElement) {
10640 targetBrowser = targetElement->AsBrowser();
10641 }
10642 bool isRemoteBrowser = false;
10643 if (targetBrowser) {
10644 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
10645 }
10646
10647 if (isRemoteBrowser) {
10648 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
10649 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
10650 : false;
10651 }
10652
10653 if (targetElement) {
10654 Document* doc = targetElement->GetUncomposedDoc();
10655 if (doc) {
10656 RefPtr<WindowContext> wc = doc->GetWindowContext();
10657 if (wc) {
10658 return wc->TopWindowContext()->GetShortcutsPermission() ==
10659 nsIPermissionManager::DENY_ACTION;
10660 }
10661 }
10662 }
10663
10664 return false;
10665}
10666
10667/**
10668 * Checks whether the given type is a supported document type for
10669 * loading within the nsObjectLoadingContent specified by aContent.
10670 *
10671 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
10672 * NOTE Does not take content policy or capabilities into account
10673 */
10674static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
10675 nsCOMPtr<nsIWebNavigationInfo> info(
10676 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
10677 if (!info) {
10678 return false;
10679 }
10680
10681 uint32_t supported;
10682 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
10683
10684 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10685 return false;
10686 }
10687
10688 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
10689 // Don't want to support plugins as documents
10690 return supported != nsIWebNavigationInfo::FALLBACK;
10691 }
10692
10693 // Try a stream converter
10694 // NOTE: We treat any type we can convert from as a supported type. If a
10695 // type is not actually supported, the URI loader will detect that and
10696 // return an error, and we'll fallback.
10697 nsCOMPtr<nsIStreamConverterService> convServ =
10698 do_GetService("@mozilla.org/streamConverters;1");
10699 bool canConvert = false;
10700 if (convServ) {
10701 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
10702 }
10703 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
10704}
10705
10706/* static */
10707uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
10708 const nsCString& aMIMEType, bool aIsSandboxed) {
10709 if (aMIMEType.IsEmpty()) {
10710 return nsIObjectLoadingContent::TYPE_FALLBACK;
10711 }
10712
10713 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
10714 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10715 }
10716
10717 // Faking support of the PDF content as a document for EMBED tags
10718 // when internal PDF viewer is enabled.
10719 if (aMIMEType.LowerCaseEqualsLiteral(APPLICATION_PDF"application/pdf") && IsPDFJSEnabled()) {
10720 // Sandboxed iframes are just never allowed to display plugins. In the
10721 // modern world, this just means "application/pdf".
10722 return aIsSandboxed ? nsIObjectLoadingContent::TYPE_FALLBACK
10723 : nsIObjectLoadingContent::TYPE_DOCUMENT;
10724 }
10725
10726 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
10727 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10728 }
10729
10730 return nsIObjectLoadingContent::TYPE_FALLBACK;
10731}
10732
10733/* static */
10734bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
10735 return !aString.IsEmpty() && aString[0] == '#';
10736}
10737
10738// We use only 53 bits for the ID so that it can be converted to and from a JS
10739// value without loss of precision. The upper bits of the ID hold the process
10740// ID. The lower bits identify the object itself.
10741static constexpr uint64_t kIdTotalBits = 53;
10742static constexpr uint64_t kIdProcessBits = 22;
10743static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
10744
10745/* static */
10746uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
10747 uint64_t processId = 0;
10748 if (XRE_IsContentProcess()) {
10749 ContentChild* cc = ContentChild::GetSingleton();
10750 processId = cc->GetID();
10751 }
10752
10753 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10753); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { *((volatile int*)__null) = 10753; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10754 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
10755
10756 uint64_t id = aId;
10757 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10757); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { *((volatile int*)__null) = 10757; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10758 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
10759
10760 return (processBits << kIdBits) | bits;
10761}
10762
10763/* static */
10764std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId(
10765 uint64_t aId) {
10766 return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)};
10767}
10768
10769// Next process-local Tab ID.
10770static uint64_t gNextTabId = 0;
10771
10772/* static */
10773uint64_t nsContentUtils::GenerateTabId() {
10774 return GenerateProcessSpecificId(++gNextTabId);
10775}
10776
10777// Next process-local Browser ID.
10778static uint64_t gNextBrowserId = 0;
10779
10780/* static */
10781uint64_t nsContentUtils::GenerateBrowserId() {
10782 return GenerateProcessSpecificId(++gNextBrowserId);
10783}
10784
10785// Next process-local Browsing Context ID.
10786static uint64_t gNextBrowsingContextId = 0;
10787
10788/* static */
10789uint64_t nsContentUtils::GenerateBrowsingContextId() {
10790 return GenerateProcessSpecificId(++gNextBrowsingContextId);
10791}
10792
10793// Next process-local Window ID.
10794static uint64_t gNextWindowId = 0;
10795
10796/* static */
10797uint64_t nsContentUtils::GenerateWindowId() {
10798 return GenerateProcessSpecificId(++gNextWindowId);
10799}
10800
10801// Next process-local load.
10802static Atomic<uint64_t> gNextLoadIdentifier(0);
10803
10804/* static */
10805uint64_t nsContentUtils::GenerateLoadIdentifier() {
10806 return GenerateProcessSpecificId(++gNextLoadIdentifier);
10807}
10808
10809/* static */
10810bool nsContentUtils::GetUserIsInteracting() {
10811 return UserInteractionObserver::sUserActive;
10812}
10813
10814/* static */
10815bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
10816 nsACString& aResult) {
10817 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
10818 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10819 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
10820 }
10821 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
10822}
10823
10824/* static */
10825bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
10826 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10827 mozilla::dom::PBrowser::PBrowserStart) {
10828 switch (aMsg.type()) {
10829 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
10830 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10831 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
10832 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10833 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10834 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10835 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
10836 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10837 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
10838 return true;
10839 }
10840 }
10841 return false;
10842}
10843
10844/* static */
10845bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) {
10846 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10847 mozilla::dom::PBrowser::PBrowserStart) {
10848 switch (aMsg.type()) {
10849 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10850 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10851 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10852 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10853 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10854 return true;
10855 }
10856 }
10857 return false;
10858}
10859
10860static const char* kUserInteractionInactive = "user-interaction-inactive";
10861static const char* kUserInteractionActive = "user-interaction-active";
10862
10863void nsContentUtils::UserInteractionObserver::Init() {
10864 // Listen for the observer messages from EventStateManager which are telling
10865 // us whether or not the user is interacting.
10866 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10867 obs->AddObserver(this, kUserInteractionInactive, false);
10868 obs->AddObserver(this, kUserInteractionActive, false);
10869
10870 // We can't register ourselves as an annotator yet, as the
10871 // BackgroundHangMonitor hasn't started yet. It will have started by the
10872 // time we have the chance to spin the event loop.
10873 RefPtr<UserInteractionObserver> self = this;
10874 NS_DispatchToMainThread(NS_NewRunnableFunction(
10875 "nsContentUtils::UserInteractionObserver::Init",
10876 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
10877}
10878
10879void nsContentUtils::UserInteractionObserver::Shutdown() {
10880 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10881 if (obs) {
10882 obs->RemoveObserver(this, kUserInteractionInactive);
10883 obs->RemoveObserver(this, kUserInteractionActive);
10884 }
10885
10886 BackgroundHangMonitor::UnregisterAnnotator(*this);
10887}
10888
10889/**
10890 * NB: This function is always called by the BackgroundHangMonitor thread.
10891 * Plan accordingly
10892 */
10893void nsContentUtils::UserInteractionObserver::AnnotateHang(
10894 BackgroundHangAnnotations& aAnnotations) {
10895 // NOTE: Only annotate the hang report if the user is known to be interacting.
10896 if (sUserActive) {
10897 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
10898 }
10899}
10900
10901NS_IMETHODIMPnsresult
10902nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
10903 const char* aTopic,
10904 const char16_t* aData) {
10905 if (!strcmp(aTopic, kUserInteractionInactive)) {
10906 if (sUserActive && XRE_IsParentProcess()) {
10907 glean::RecordPowerMetrics();
10908 }
10909 sUserActive = false;
10910 } else if (!strcmp(aTopic, kUserInteractionActive)) {
10911 if (!sUserActive && XRE_IsParentProcess()) {
10912 glean::RecordPowerMetrics();
10913
10914 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
10915 do_GetService("@mozilla.org/widget/useridleservice;1");
10916 if (idleService) {
10917 idleService->ResetIdleTimeOut(0);
10918 }
10919 }
10920
10921 sUserActive = true;
10922 } else {
10923 NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10923)
;
10924 }
10925 return NS_OK;
10926}
10927
10928Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
10929NS_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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
10929; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10929; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 10929
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10929; __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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10929); 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; }
10930
10931/* static */
10932bool nsContentUtils::IsSpecialName(const nsAString& aName) {
10933 return aName.LowerCaseEqualsLiteral("_blank") ||
10934 aName.LowerCaseEqualsLiteral("_top") ||
10935 aName.LowerCaseEqualsLiteral("_parent") ||
10936 aName.LowerCaseEqualsLiteral("_self");
10937}
10938
10939/* static */
10940bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
10941 return !aName.IsEmpty() && !IsSpecialName(aName);
10942}
10943
10944// Unfortunately, we can't unwrap an IDL object using only a concrete type.
10945// We need to calculate type data based on the IDL typename. Which means
10946// wrapping our templated function in a macro.
10947#define EXTRACT_EXN_VALUES(T, ...) \
10948 ExtractExceptionValues<mozilla::dom::prototypes::id::T, \
10949 T##_Binding::NativeType, T>(__VA_ARGS__) \
10950 .isOk()
10951
10952template <prototypes::ID PrototypeID, class NativeType, typename T>
10953static Result<Ok, nsresult> ExtractExceptionValues(
10954 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aSourceSpecOut,
10955 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
10956 AssertStaticUnwrapOK<PrototypeID>();
10957 RefPtr<T> exn;
10958 MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr)))do { auto mozTryTempResult_ = ::mozilla::ToResult((UnwrapObject
<PrototypeID, NativeType>(aObj, exn, nullptr))); if ((__builtin_expect
(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_
.propagateErr(); } } while (0)
;
10959
10960 exn->GetFilename(aCx, aSourceSpecOut);
10961 if (!aSourceSpecOut.IsEmpty()) {
10962 *aLineOut = exn->LineNumber(aCx);
10963 *aColumnOut = exn->ColumnNumber();
10964 }
10965
10966 exn->GetName(aMessageOut);
10967 aMessageOut.AppendLiteral(": ");
10968
10969 nsAutoString message;
10970 exn->GetMessageMoz(message);
10971 aMessageOut.Append(message);
10972 return Ok();
10973}
10974
10975/* static */
10976void nsContentUtils::ExtractErrorValues(
10977 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
10978 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
10979 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10979); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { *((volatile int*)__null) = 10979; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10980 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { *((volatile int*)__null) = 10980; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10981
10982 if (aValue.isObject()) {
10983 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
10984
10985 // Try to process as an Error object. Use the file/line/column values
10986 // from the Error as they will be more specific to the root cause of
10987 // the problem.
10988 JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr;
10989 if (err) {
10990 // Use xpc to extract the error message only. We don't actually send
10991 // this report anywhere.
10992 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
10993 report->Init(err,
10994 nullptr, // toString result
10995 false, // chrome
10996 0); // window ID
10997
10998 if (!report->mFileName.IsEmpty()) {
10999 aSourceSpecOut = report->mFileName;
11000 *aLineOut = report->mLineNumber;
11001 *aColumnOut = report->mColumn;
11002 }
11003 aMessageOut.Assign(report->mErrorMsg);
11004 }
11005
11006 // Next, try to unwrap the rejection value as a DOMException.
11007 else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
11008 aLineOut, aColumnOut, aMessageOut)) {
11009 return;
11010 }
11011
11012 // Next, try to unwrap the rejection value as an XPC Exception.
11013 else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut, aLineOut,
11014 aColumnOut, aMessageOut)) {
11015 return;
11016 }
11017 }
11018
11019 // If we could not unwrap a specific error type, then perform default safe
11020 // string conversions on primitives. Objects will result in "[Object]"
11021 // unfortunately.
11022 if (aMessageOut.IsEmpty()) {
11023 nsAutoJSString jsString;
11024 if (jsString.init(aCx, aValue)) {
11025 aMessageOut = jsString;
11026 } else {
11027 JS_ClearPendingException(aCx);
11028 }
11029 }
11030}
11031
11032#undef EXTRACT_EXN_VALUES
11033
11034/* static */
11035bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
11036 if (!aContent || !aContent->IsElement()) {
11037 return false;
11038 }
11039
11040 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
11041 return true;
11042 }
11043
11044 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
11045 nsGkAtoms::simple, eCaseMatters);
11046}
11047
11048/* static */
11049already_AddRefed<ContentFrameMessageManager>
11050nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
11051 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
11052 if (!frameLoaderOwner) {
11053 return nullptr;
11054 }
11055
11056 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
11057 if (!frameLoader) {
11058 return nullptr;
11059 }
11060
11061 RefPtr<ContentFrameMessageManager> manager =
11062 frameLoader->GetBrowserChildMessageManager();
11063 return manager.forget();
11064}
11065
11066/* static */
11067uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
11068 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11068; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11069 ++sInnerOrOuterWindowCount;
11070 return ++sInnerOrOuterWindowSerialCounter;
11071}
11072
11073/* static */
11074void nsContentUtils::InnerOrOuterWindowDestroyed() {
11075 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11075); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11075; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11076 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { *((volatile int*)__null) = 11076; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11077 --sInnerOrOuterWindowCount;
11078}
11079
11080/* static */
11081nsresult nsContentUtils::AnonymizeURI(nsIURI* aURI, nsCString& aAnonymizedURI) {
11082 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 11082; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11083
11084 if (aURI->SchemeIs("data")) {
11085 aAnonymizedURI.Assign("data:..."_ns);
11086 return NS_OK;
11087 }
11088 // Anonymize the URL.
11089 // Strip the URL of any possible username/password and make it ready to be
11090 // presented in the UI.
11091 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(aURI);
11092 return exposableURI->GetSpec(aAnonymizedURI);
11093}
11094
11095static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
11096 nsAString* result = static_cast<nsAString*>(aData);
11097 return result->Append(aBuf, aLen, fallible);
11098}
11099
11100/* static */
11101bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
11102 nsAString& aOutStr, JSONBehavior aBehavior) {
11103 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11103); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { *((volatile int*)__null) = 11103; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11104 switch (aBehavior) {
11105 case UndefinedIsNullStringLiteral: {
11106 aOutStr.Truncate();
11107 JS::Rooted<JS::Value> value(aCx, aValue);
11108 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
11109 JSONCreator, &aOutStr);
11110 }
11111 case UndefinedIsVoidString: {
11112 aOutStr.SetIsVoid(true);
11113 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
11114 &aOutStr);
11115 }
11116 default:
11117 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11117); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { *((volatile int*)__null) = 11117; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11118 return false;
11119 }
11120}
11121
11122/* static */
11123bool nsContentUtils::
11124 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
11125 Document* aDocument) {
11126 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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11127; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11127 "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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11127; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11128
11129 if (aDocument && !aDocument->IsLoadedAsData()) {
11130 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
11131 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11132; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11132 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11132; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11133
11134 return !presContext->GetInProcessRootContentDocumentPresContext()
11135 ->HadFirstContentfulPaint() &&
11136 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
11137 }
11138 }
11139 return false;
11140}
11141
11142static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
11143 NS_ENSURE_TRUE(aGlobal, nullptr)do { if ((__builtin_expect(!!(!(aGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aGlobal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11143); return nullptr; } } while (false)
;
11144
11145 if (auto* window = aGlobal->GetAsInnerWindow()) {
11146 return nsGlobalWindowInner::Cast(window);
11147 }
11148
11149 // When Extensions run content scripts inside a sandbox, it uses
11150 // sandboxPrototype to make them appear as though they're running in the
11151 // scope of the page. So when a content script invokes postMessage, it expects
11152 // the |source| of the received message to be the window set as the
11153 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
11154 // now we need to do some special handling to support it.
11155 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
11156 NS_ENSURE_TRUE(scope, nullptr)do { if ((__builtin_expect(!!(!(scope)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scope" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11156); return nullptr; } } while (false)
;
11157
11158 if (xpc::IsSandbox(scope)) {
11159 AutoJSAPI jsapi;
11160 MOZ_ALWAYS_TRUE(jsapi.Init(scope))do { if ((__builtin_expect(!!(jsapi.Init(scope)), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "jsapi.Init(scope)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11160); AnnotateMozCrashReason("MOZ_CRASH(" "jsapi.Init(scope)"
")"); do { *((volatile int*)__null) = 11160; __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11161 JSContext* cx = jsapi.cx();
11162 // Our current Realm on aCx is the sandbox. Using that for unwrapping
11163 // makes sense: if the sandbox can unwrap the window, we can use it.
11164 return xpc::SandboxWindowOrNull(scope, cx);
11165 }
11166
11167 // The calling window must be holding a reference, so we can return a weak
11168 // pointer.
11169 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
11170}
11171
11172/* static */
11173nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
11174 return GetInnerWindowForGlobal(GetIncumbentGlobal());
11175}
11176
11177/* static */
11178nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
11179 return GetInnerWindowForGlobal(GetEntryGlobal());
11180}
11181
11182/* static */
11183bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
11184 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { *((volatile int*)__null) = 11184; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11185
11186 nsAutoCString list;
11187 Preferences::GetCString(aPrefName, list);
11188 ToLowerCase(list);
11189 return IsURIInList(aURI, list);
11190}
11191
11192/* static */
11193bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
11194#ifdef DEBUG1
11195 nsAutoCString listLowerCase(aList);
11196 ToLowerCase(listLowerCase);
11197 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11198; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
11198 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11198; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
11199#endif
11200
11201 if (!aURI) {
11202 return false;
11203 }
11204
11205 if (aList.IsEmpty()) {
11206 return false;
11207 }
11208
11209 nsAutoCString scheme;
11210 aURI->GetScheme(scheme);
11211 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
11212 return false;
11213 }
11214
11215 // The list is comma separated domain list. Each item may start with "*.".
11216 // If starts with "*.", it matches any sub-domains.
11217
11218 nsCCharSeparatedTokenizer tokenizer(aList, ',');
11219 while (tokenizer.hasMoreTokens()) {
11220 const nsCString token(tokenizer.nextToken());
11221
11222 nsAutoCString host;
11223 aURI->GetHost(host);
11224 if (host.IsEmpty()) {
11225 return false;
11226 }
11227 ToLowerCase(host);
11228
11229 for (;;) {
11230 int32_t index = token.Find(host);
11231 if (index >= 0 &&
11232 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
11233 // If we found a full match, return true.
11234 size_t indexAfterHost = index + host.Length();
11235 if (index == 0 && indexAfterHost == token.Length()) {
11236 return true;
11237 }
11238 // If next character is '/', we need to check the path too.
11239 // We assume the path in the list means "/foo" + "*".
11240 if (token[indexAfterHost] == '/') {
11241 nsDependentCSubstring pathInList(
11242 token, indexAfterHost,
11243 static_cast<nsDependentCSubstring::size_type>(-1));
11244 nsAutoCString filePath;
11245 aURI->GetFilePath(filePath);
11246 ToLowerCase(filePath);
11247 if (StringBeginsWith(filePath, pathInList) &&
11248 (filePath.Length() == pathInList.Length() ||
11249 pathInList.EqualsLiteral("/") ||
11250 filePath[pathInList.Length() - 1] == '/' ||
11251 filePath[pathInList.Length() - 1] == '?' ||
11252 filePath[pathInList.Length() - 1] == '#')) {
11253 return true;
11254 }
11255 }
11256 }
11257 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
11258 int32_t startIndexOfNextLevel =
11259 host.Find(".", startIndexOfCurrentLevel + 1);
11260 if (startIndexOfNextLevel <= 0) {
11261 break;
11262 }
11263 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
11264 }
11265 }
11266
11267 return false;
11268}
11269
11270/* static */
11271LayoutDeviceIntMargin nsContentUtils::GetWindowSafeAreaInsets(
11272 nsIScreen* aScreen, const LayoutDeviceIntMargin& aSafeAreaInsets,
11273 const LayoutDeviceIntRect& aWindowRect) {
11274 // This calculates safe area insets of window from screen rectangle, window
11275 // rectangle and safe area insets of screen.
11276 //
11277 // +----------------------------------------+ <-- screen
11278 // | +-------------------------------+ <------- window
11279 // | | window's safe area inset top) | |
11280 // +--+-------------------------------+--+ |
11281 // | | | |<------ safe area rectangle of
11282 // | | | | | screen
11283 // +--+-------------------------------+--+ |
11284 // | |window's safe area inset bottom| |
11285 // | +-------------------------------+ |
11286 // +----------------------------------------+
11287 //
11288 LayoutDeviceIntMargin windowSafeAreaInsets;
11289 if (windowSafeAreaInsets == aSafeAreaInsets) {
11290 // no safe area insets.
11291 return windowSafeAreaInsets;
11292 }
11293
11294 const LayoutDeviceIntRect screenRect = aScreen->GetRect();
11295 LayoutDeviceIntRect safeAreaRect = screenRect;
11296 safeAreaRect.Deflate(aSafeAreaInsets);
11297
11298 // FIXME(bug 1754323): This can trigger because the screen rect is not
11299 // orientation-aware.
11300 // MOZ_ASSERT(screenRect.Contains(windowRect),
11301 // "Screen doesn't contain window rect? Something seems off");
11302
11303 // window's rect of safe area
11304 safeAreaRect = safeAreaRect.Intersect(aWindowRect);
11305
11306 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
11307 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
11308 windowSafeAreaInsets.right =
11309 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
11310 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
11311 (safeAreaRect.y + safeAreaRect.height);
11312
11313 windowSafeAreaInsets.EnsureAtLeast(LayoutDeviceIntMargin());
11314 // This shouldn't be needed, but it wallpapers orientation issues, see bug
11315 // 1754323.
11316 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
11317
11318 return windowSafeAreaInsets;
11319}
11320
11321/* static */
11322nsContentUtils::SubresourceCacheValidationInfo
11323nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
11324 nsIURI* aURI) {
11325 SubresourceCacheValidationInfo info;
11326 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
11327 uint32_t value = 0;
11328 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
11329 // NOTE: If the cache doesn't expire, the value should be
11330 // nsICacheEntry::NO_EXPIRATION_TIME.
11331 info.mExpirationTime.emplace(CacheExpirationTime::ExpireAt(value));
11332 }
11333 }
11334
11335 // Determine whether the cache entry must be revalidated when we try to use
11336 // it. Currently, only HTTP specifies this information...
11337 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
11338 Unused << httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
11339
11340 if (!info.mMustRevalidate) {
11341 Unused << httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
11342 }
11343 }
11344
11345 // data: URIs are safe to cache across documents under any circumstance, so we
11346 // special-case them here even though the channel itself doesn't have any
11347 // caching policy. Same for chrome:// uris.
11348 //
11349 // TODO(emilio): Figure out which other schemes that don't have caching
11350 // policies are safe to cache. Blobs should be...
11351 const bool knownCacheable = [&] {
11352 if (!aURI) {
11353 return false;
11354 }
11355 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
11356 aURI->SchemeIs("moz-extension")) {
11357 return true;
11358 }
11359 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
11360 return !StaticPrefs::nglayout_debug_disable_xul_cache();
11361 }
11362 return false;
11363 }();
11364
11365 if (knownCacheable) {
11366 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mExpirationTime"
")"); do { *((volatile int*)__null) = 11366; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11367 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mMustRevalidate"
")"); do { *((volatile int*)__null) = 11367; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11368 info.mExpirationTime = Some(CacheExpirationTime::Never());
11369 }
11370
11371 return info;
11372}
11373
11374CacheExpirationTime nsContentUtils::GetSubresourceCacheExpirationTime(
11375 nsIRequest* aRequest, nsIURI* aURI) {
11376 auto info = GetSubresourceCacheValidationInfo(aRequest, aURI);
11377
11378 // For now, we never cache entries that we have to revalidate, or whose
11379 // channel don't support caching.
11380 if (info.mMustRevalidate || !info.mExpirationTime) {
11381 return CacheExpirationTime::AlreadyExpired();
11382 }
11383 return *info.mExpirationTime;
11384}
11385
11386/* static */
11387bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
11388 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
11389 if (!lg) {
11390 return false;
11391 }
11392 nsLoadFlags flags;
11393 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
11394 return false;
11395 }
11396 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
11397 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
11398}
11399
11400nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
11401 nsCString spec;
11402 if (aURL) {
11403 aURL->GetSpec(spec);
11404 spec.Truncate(std::min(aMaxLen, spec.Length()));
11405 }
11406 return spec;
11407}
11408
11409/* static */
11410nsresult nsContentUtils::AnonymizeId(nsAString& aId,
11411 const nsACString& aOriginKey,
11412 OriginFormat aFormat) {
11413 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11413; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11414
11415 nsresult rv;
11416 nsCString rawKey;
11417 if (aFormat == OriginFormat::Base64) {
11418 rv = Base64Decode(aOriginKey, rawKey);
11419 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11419); return rv; } } while (false)
;
11420 } else {
11421 rawKey = aOriginKey;
11422 }
11423
11424 HMAC hmac;
11425 rv = hmac.Begin(
11426 SEC_OID_SHA256,
11427 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
11428 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11428); return rv; } } while (false)
;
11429
11430 NS_ConvertUTF16toUTF8 id(aId);
11431 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
11432 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11432); return rv; } } while (false)
;
11433
11434 nsTArray<uint8_t> macBytes;
11435 rv = hmac.End(macBytes);
11436 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11436); return rv; } } while (false)
;
11437
11438 nsCString macBase64;
11439 rv = Base64Encode(
11440 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
11441 macBytes.Length()),
11442 macBase64);
11443 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11443); return rv; } } while (false)
;
11444
11445 CopyUTF8toUTF16(macBase64, aId);
11446 return NS_OK;
11447}
11448
11449void nsContentUtils::RequestGeckoTaskBurst() {
11450 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{ 0x2d96b3df, 0xc051, 0x11d1, { 0xa8, 0x27, 0x00, 0x40, 0x95,
0x9a, 0x28, 0xc9 } }
);
11451 if (appShell) {
11452 appShell->GeckoTaskBurst();
11453 }
11454}
11455
11456nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
11457 for (nsIContent* content = aContent; content;
11458 content = content->GetFlattenedTreeParent()) {
11459 if (nsContentUtils::IsDraggableLink(content)) {
11460 return content;
11461 }
11462 }
11463 return nullptr;
11464}
11465
11466template <TreeKind aKind>
11467MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
11468 if constexpr (aKind == TreeKind::DOM) {
11469 return aNode->GetParentNode();
11470 } else {
11471 return aNode->GetFlattenedTreeParentNode();
11472 }
11473}
11474
11475template <TreeKind aKind>
11476MOZ_ALWAYS_INLINEinline Maybe<uint32_t> GetIndexInParent(const nsINode* aParent,
11477 const nsINode* aNode) {
11478 if constexpr (aKind == TreeKind::DOM) {
11479 return aParent->ComputeIndexOf(aNode);
11480 } else {
11481 return aParent->ComputeFlatTreeIndexOf(aNode);
11482 }
11483}
11484
11485template <TreeKind aTreeKind>
11486int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
11487 const nsINode* aNode2,
11488 const nsINode* aCommonAncestor) {
11489 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") ("
"aNode1 must not be null" ")"); do { *((volatile int*)__null
) = 11489; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11490 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") ("
"aNode2 must not be null" ")"); do { *((volatile int*)__null
) = 11490; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11491
11492 if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11492)
) {
11493 return 0;
11494 }
11495
11496 AutoTArray<const nsINode*, 32> node1Ancestors;
11497 const nsINode* c1;
11498 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
11499 c1 = GetParent<aTreeKind>(c1)) {
11500 node1Ancestors.AppendElement(c1);
11501 }
11502 if (!c1 && aCommonAncestor) {
11503 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
11504 // Never mind. We can continue as if aCommonAncestor was null.
11505 aCommonAncestor = nullptr;
11506 }
11507
11508 AutoTArray<const nsINode*, 32> node2Ancestors;
11509 const nsINode* c2;
11510 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
11511 c2 = GetParent<aTreeKind>(c2)) {
11512 node2Ancestors.AppendElement(c2);
11513 }
11514 if (!c2 && aCommonAncestor) {
11515 // So, it turns out aCommonAncestor was not an ancestor of c2.
11516 // We need to retry with no common ancestor hint.
11517 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr);
11518 }
11519
11520 int last1 = node1Ancestors.Length() - 1;
11521 int last2 = node2Ancestors.Length() - 1;
11522 const nsINode* node1Ancestor = nullptr;
11523 const nsINode* node2Ancestor = nullptr;
11524 while (last1 >= 0 && last2 >= 0 &&
11525 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
11526 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
11527 last1--;
11528 last2--;
11529 }
11530
11531 if (last1 < 0) {
11532 if (last2 < 0) {
11533 NS_ASSERTION(aNode1 == aNode2, "internal error?")do { if (!(aNode1 == aNode2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "internal error?", "aNode1 == aNode2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11533); MOZ_PretendNoReturn(); } } while (0)
;
11534 return 0;
11535 }
11536 // aContent1 is an ancestor of aContent2
11537 return -1;
11538 }
11539
11540 if (last2 < 0) {
11541 // aContent2 is an ancestor of aContent1
11542 return 1;
11543 }
11544
11545 // node1Ancestor != node2Ancestor, so they must be siblings with the
11546 // same parent
11547 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
11548 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11548)
) { // different documents??
11549 return 0;
11550 }
11551
11552 const Maybe<uint32_t> index1 =
11553 GetIndexInParent<aTreeKind>(parent, node1Ancestor);
11554 const Maybe<uint32_t> index2 =
11555 GetIndexInParent<aTreeKind>(parent, node2Ancestor);
11556
11557 // None of the nodes are anonymous, just do a regular comparison.
11558 if (index1.isSome() && index2.isSome()) {
11559 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
11560 }
11561
11562 // Otherwise handle pseudo-element and anonymous node ordering.
11563 // ::marker -> ::before -> anon siblings -> regular siblings -> ::after
11564 auto PseudoIndex = [](const nsINode* aNode,
11565 const Maybe<uint32_t>& aNodeIndex) -> int32_t {
11566 if (aNodeIndex.isSome()) {
11567 return 1; // Not a pseudo.
11568 }
11569 if (aNode->IsGeneratedContentContainerForMarker()) {
11570 return -2;
11571 }
11572 if (aNode->IsGeneratedContentContainerForBefore()) {
11573 return -1;
11574 }
11575 if (aNode->IsGeneratedContentContainerForAfter()) {
11576 return 2;
11577 }
11578 return 0;
11579 };
11580
11581 return PseudoIndex(node1Ancestor, index1) -
11582 PseudoIndex(node2Ancestor, index2);
11583}
11584
11585nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost,
11586 ShadowRootMode aMode,
11587 bool aIsClonable,
11588 bool aIsSerializable,
11589 bool aDelegatesFocus) {
11590 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
11591 if (!host || host->GetShadowRoot()) {
11592 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
11593 return nullptr;
11594 }
11595
11596 ShadowRootInit init;
11597 init.mMode = aMode;
11598 init.mDelegatesFocus = aDelegatesFocus;
11599 init.mSlotAssignment = SlotAssignmentMode::Named;
11600 init.mClonable = aIsClonable;
11601 init.mSerializable = aIsSerializable;
11602
11603 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
11604 if (shadowRoot) {
11605 shadowRoot->SetIsDeclarative(
11606 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
11607 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
11608 shadowRoot->SetAvailableToElementInternals();
11609 }
11610 return shadowRoot;
11611}
11612
11613template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
11614 const nsINode*, const nsINode*, const nsINode*);
11615template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
11616 const nsINode*, const nsINode*, const nsINode*);