Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp
Warning:line 10253, 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-18/lib/clang/18 -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 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-18/lib/clang/18/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 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -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-2024-07-21-021012-413605-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/CallbackFunction.h"
149#include "mozilla/dom/CallbackObject.h"
150#include "mozilla/dom/ChromeMessageBroadcaster.h"
151#include "mozilla/dom/ContentChild.h"
152#include "mozilla/dom/ContentFrameMessageManager.h"
153#include "mozilla/dom/ContentParent.h"
154#include "mozilla/dom/CustomElementRegistry.h"
155#include "mozilla/dom/CustomElementRegistryBinding.h"
156#include "mozilla/dom/CustomElementTypes.h"
157#include "mozilla/dom/DOMArena.h"
158#include "mozilla/dom/DOMException.h"
159#include "mozilla/dom/DOMExceptionBinding.h"
160#include "mozilla/dom/DOMSecurityMonitor.h"
161#include "mozilla/dom/DOMTypes.h"
162#include "mozilla/dom/DataTransfer.h"
163#include "mozilla/dom/DocGroup.h"
164#include "mozilla/dom/Document.h"
165#include "mozilla/dom/DocumentFragment.h"
166#include "mozilla/dom/DocumentInlines.h"
167#include "mozilla/dom/Element.h"
168#include "mozilla/dom/ElementBinding.h"
169#include "mozilla/dom/ElementInlines.h"
170#include "mozilla/dom/Event.h"
171#include "mozilla/dom/EventTarget.h"
172#include "mozilla/dom/FileBlobImpl.h"
173#include "mozilla/dom/FileSystemSecurity.h"
174#include "mozilla/dom/FilteredNodeIterator.h"
175#include "mozilla/dom/FormData.h"
176#include "mozilla/dom/FragmentOrElement.h"
177#include "mozilla/dom/FromParser.h"
178#include "mozilla/dom/HTMLElement.h"
179#include "mozilla/dom/HTMLFormElement.h"
180#include "mozilla/dom/HTMLImageElement.h"
181#include "mozilla/dom/HTMLInputElement.h"
182#include "mozilla/dom/HTMLTemplateElement.h"
183#include "mozilla/dom/HTMLTextAreaElement.h"
184#include "mozilla/dom/IPCBlob.h"
185#include "mozilla/dom/IPCBlobUtils.h"
186#include "mozilla/dom/MessageBroadcaster.h"
187#include "mozilla/dom/MessageListenerManager.h"
188#include "mozilla/dom/MessagePort.h"
189#include "mozilla/dom/MouseEventBinding.h"
190#include "mozilla/dom/NameSpaceConstants.h"
191#include "mozilla/dom/NodeBinding.h"
192#include "mozilla/dom/NodeInfo.h"
193#include "mozilla/dom/PBrowser.h"
194#include "mozilla/dom/PContentChild.h"
195#include "mozilla/dom/PrototypeList.h"
196#include "mozilla/dom/ReferrerPolicyBinding.h"
197#include "mozilla/dom/ScriptSettings.h"
198#include "mozilla/dom/Selection.h"
199#include "mozilla/dom/ShadowRoot.h"
200#include "mozilla/dom/Text.h"
201#include "mozilla/dom/UserActivation.h"
202#include "mozilla/dom/WindowContext.h"
203#include "mozilla/dom/WorkerCommon.h"
204#include "mozilla/dom/WorkerPrivate.h"
205#include "mozilla/dom/WorkerRunnable.h"
206#include "mozilla/dom/XULCommandEvent.h"
207#include "mozilla/glean/GleanPings.h"
208#include "mozilla/fallible.h"
209#include "mozilla/gfx/2D.h"
210#include "mozilla/gfx/BaseMargin.h"
211#include "mozilla/gfx/BasePoint.h"
212#include "mozilla/gfx/BaseSize.h"
213#include "mozilla/gfx/DataSurfaceHelpers.h"
214#include "mozilla/gfx/Point.h"
215#include "mozilla/gfx/Rect.h"
216#include "mozilla/gfx/Types.h"
217#include "mozilla/ipc/ProtocolUtils.h"
218#include "mozilla/ipc/SharedMemory.h"
219#include "mozilla/net/UrlClassifierCommon.h"
220#include "mozilla/Tokenizer.h"
221#include "mozilla/widget/IMEData.h"
222#include "nsAboutProtocolUtils.h"
223#include "nsAlgorithm.h"
224#include "nsArrayUtils.h"
225#include "nsAtomHashKeys.h"
226#include "nsAttrName.h"
227#include "nsAttrValue.h"
228#include "nsAttrValueInlines.h"
229#include "nsBaseHashtable.h"
230#include "nsCCUncollectableMarker.h"
231#include "nsCOMPtr.h"
232#include "nsCRT.h"
233#include "nsCRTGlue.h"
234#include "nsCanvasFrame.h"
235#include "nsCaseTreatment.h"
236#include "nsCharSeparatedTokenizer.h"
237#include "nsCharTraits.h"
238#include "nsCompatibility.h"
239#include "nsComponentManagerUtils.h"
240#include "nsContainerFrame.h"
241#include "nsContentCreatorFunctions.h"
242#include "nsContentDLF.h"
243#include "nsContentList.h"
244#include "nsContentListDeclarations.h"
245#include "nsContentPolicyUtils.h"
246#include "nsCoord.h"
247#include "nsCycleCollectionNoteChild.h"
248#include "nsDOMMutationObserver.h"
249#include "nsDOMString.h"
250#include "nsTHashMap.h"
251#include "nsDebug.h"
252#include "nsDocShell.h"
253#include "nsDocShellCID.h"
254#include "nsError.h"
255#include "nsFocusManager.h"
256#include "nsFrameList.h"
257#include "nsFrameLoader.h"
258#include "nsFrameLoaderOwner.h"
259#include "nsGenericHTMLElement.h"
260#include "nsGkAtoms.h"
261#include "nsGlobalWindowInner.h"
262#include "nsGlobalWindowOuter.h"
263#include "nsHTMLDocument.h"
264#include "nsHTMLTags.h"
265#include "nsHashKeys.h"
266#include "nsHtml5StringParser.h"
267#include "nsIAboutModule.h"
268#include "nsIAnonymousContentCreator.h"
269#include "nsIAppShell.h"
270#include "nsIArray.h"
271#include "nsIAsyncVerifyRedirectCallback.h"
272#include "nsIBidiKeyboard.h"
273#include "nsIBrowser.h"
274#include "nsICacheInfoChannel.h"
275#include "nsICachingChannel.h"
276#include "nsICategoryManager.h"
277#include "nsIChannel.h"
278#include "nsIChannelEventSink.h"
279#include "nsIClassifiedChannel.h"
280#include "nsIConsoleService.h"
281#include "nsIContent.h"
282#include "nsIContentInlines.h"
283#include "nsIContentPolicy.h"
284#include "nsIContentSecurityPolicy.h"
285#include "nsIContentSink.h"
286#include "nsIDOMWindowUtils.h"
287#include "nsIDocShell.h"
288#include "nsIDocShellTreeItem.h"
289#include "nsIDocumentEncoder.h"
290#include "nsIDocumentLoaderFactory.h"
291#include "nsIDocumentViewer.h"
292#include "nsIDragService.h"
293#include "nsIDragSession.h"
294#include "nsIFile.h"
295#include "nsIFocusManager.h"
296#include "nsIFormControl.h"
297#include "nsIFragmentContentSink.h"
298#include "nsIFrame.h"
299#include "nsIGlobalObject.h"
300#include "nsIHttpChannel.h"
301#include "nsIHttpChannelInternal.h"
302#include "nsIIOService.h"
303#include "nsIImageLoadingContent.h"
304#include "nsIInputStream.h"
305#include "nsIInterfaceRequestor.h"
306#include "nsIInterfaceRequestorUtils.h"
307#include "nsILoadContext.h"
308#include "nsILoadGroup.h"
309#include "nsILoadInfo.h"
310#include "nsIMIMEService.h"
311#include "nsIMemoryReporter.h"
312#include "nsINetUtil.h"
313#include "nsINode.h"
314#include "nsIObjectLoadingContent.h"
315#include "nsIObserver.h"
316#include "nsIObserverService.h"
317#include "nsIParserUtils.h"
318#include "nsIPermissionManager.h"
319#include "nsIPrincipal.h"
320#include "nsIProperties.h"
321#include "nsIProtocolHandler.h"
322#include "nsIRequest.h"
323#include "nsIRunnable.h"
324#include "nsIScreen.h"
325#include "nsIScriptError.h"
326#include "nsIScriptGlobalObject.h"
327#include "nsIScriptObjectPrincipal.h"
328#include "nsIScriptSecurityManager.h"
329#include "nsISerialEventTarget.h"
330#include "nsIStreamConverter.h"
331#include "nsIStreamConverterService.h"
332#include "nsIStringBundle.h"
333#include "nsISupports.h"
334#include "nsISupportsPrimitives.h"
335#include "nsISupportsUtils.h"
336#include "nsITransferable.h"
337#include "nsIURI.h"
338#include "nsIURIMutator.h"
339#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
340# include "nsIURIWithSpecialOrigin.h"
341#endif
342#include "nsIUserIdleServiceInternal.h"
343#include "nsIWeakReferenceUtils.h"
344#include "nsIWebNavigation.h"
345#include "nsIWebNavigationInfo.h"
346#include "nsIWidget.h"
347#include "nsIWindowMediator.h"
348#include "nsIXPConnect.h"
349#include "nsJSPrincipals.h"
350#include "nsJSUtils.h"
351#include "nsLayoutUtils.h"
352#include "nsLiteralString.h"
353#include "nsMargin.h"
354#include "nsMimeTypes.h"
355#include "nsNameSpaceManager.h"
356#include "nsNetCID.h"
357#include "nsNetUtil.h"
358#include "nsNodeInfoManager.h"
359#include "nsPIDOMWindow.h"
360#include "nsPIDOMWindowInlines.h"
361#include "nsParser.h"
362#include "nsParserConstants.h"
363#include "nsPoint.h"
364#include "nsPointerHashKeys.h"
365#include "nsPresContext.h"
366#include "nsQueryFrame.h"
367#include "nsQueryObject.h"
368#include "nsRange.h"
369#include "nsRefPtrHashtable.h"
370#include "nsSandboxFlags.h"
371#include "nsScriptSecurityManager.h"
372#include "nsServiceManagerUtils.h"
373#include "nsStreamUtils.h"
374#include "nsString.h"
375#include "nsStringBundle.h"
376#include "nsStringFlags.h"
377#include "nsStringFwd.h"
378#include "nsStringIterator.h"
379#include "nsStringStream.h"
380#include "nsTArray.h"
381#include "nsTLiteralString.h"
382#include "nsTPromiseFlatString.h"
383#include "nsTStringRepr.h"
384#include "nsTextFragment.h"
385#include "nsTextNode.h"
386#include "nsThreadManager.h"
387#include "nsThreadUtils.h"
388#include "nsTreeSanitizer.h"
389#include "nsUGenCategory.h"
390#include "nsURLHelper.h"
391#include "nsUnicodeProperties.h"
392#include "nsVariant.h"
393#include "nsWidgetsCID.h"
394#include "nsView.h"
395#include "nsViewManager.h"
396#include "nsXPCOM.h"
397#include "nsXPCOMCID.h"
398#include "nsXULAppAPI.h"
399#include "nsXULElement.h"
400#include "nsXULPopupManager.h"
401#include "nscore.h"
402#include "prinrval.h"
403#include "xpcprivate.h"
404#include "xpcpublic.h"
405
406#if defined(XP_WIN)
407// Undefine LoadImage to prevent naming conflict with Windows.
408# undef LoadImage
409#endif
410
411extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
412 const char** next, char16_t* result);
413extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
414 const char** colon);
415
416using namespace mozilla::dom;
417using namespace mozilla::ipc;
418using namespace mozilla::gfx;
419using namespace mozilla::layers;
420using namespace mozilla::widget;
421using namespace mozilla;
422
423const char kLoadAsData[] = "loadAsData";
424
425nsIXPConnect* nsContentUtils::sXPConnect;
426nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
427nsIPrincipal* nsContentUtils::sSystemPrincipal;
428nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
429nsIConsoleService* nsContentUtils::sConsoleService;
430
431static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
432static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
433static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
434nsIStringBundleService* nsContentUtils::sStringBundleService;
435
436static StaticRefPtr<nsIStringBundle>
437 sStringBundles[nsContentUtils::PropertiesFile_COUNT];
438
439nsIContentPolicy* nsContentUtils::sContentPolicyService;
440bool nsContentUtils::sTriedToGetContentPolicy = false;
441StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
442uint32_t nsContentUtils::sScriptBlockerCount = 0;
443uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
444AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
445 nullptr;
446uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
447nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
448
449bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
450
451nsString* nsContentUtils::sShiftText = nullptr;
452nsString* nsContentUtils::sControlText = nullptr;
453nsString* nsContentUtils::sCommandOrWinText = nullptr;
454nsString* nsContentUtils::sAltText = nullptr;
455nsString* nsContentUtils::sModifierSeparator = nullptr;
456
457bool nsContentUtils::sInitialized = false;
458#ifndef RELEASE_OR_BETA
459bool nsContentUtils::sBypassCSSOMOriginCheck = false;
460#endif
461
462nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
463nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
464
465nsContentUtils::UserInteractionObserver*
466 nsContentUtils::sUserInteractionObserver = nullptr;
467
468nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
469nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
470nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
471bool nsContentUtils::sFragmentParsingActive = false;
472
473bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false;
474bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false;
475
476mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
477 "nsResistFingerprinting");
478mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
479
480int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
481uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
482
483template Maybe<int32_t> nsContentUtils::ComparePoints(
484 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary);
485template Maybe<int32_t> nsContentUtils::ComparePoints(
486 const RangeBoundary& aFirstBoundary,
487 const RawRangeBoundary& aSecondBoundary);
488template Maybe<int32_t> nsContentUtils::ComparePoints(
489 const RawRangeBoundary& aFirstBoundary,
490 const RangeBoundary& aSecondBoundary);
491template Maybe<int32_t> nsContentUtils::ComparePoints(
492 const RawRangeBoundary& aFirstBoundary,
493 const RawRangeBoundary& aSecondBoundary);
494
495template int32_t nsContentUtils::ComparePoints_Deprecated(
496 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary,
497 bool* aDisconnected);
498template int32_t nsContentUtils::ComparePoints_Deprecated(
499 const RangeBoundary& aFirstBoundary,
500 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
501template int32_t nsContentUtils::ComparePoints_Deprecated(
502 const RawRangeBoundary& aFirstBoundary,
503 const RangeBoundary& aSecondBoundary, bool* aDisconnected);
504template int32_t nsContentUtils::ComparePoints_Deprecated(
505 const RawRangeBoundary& aFirstBoundary,
506 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
507
508// Subset of
509// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
510enum AutocompleteUnsupportedFieldName : uint8_t {
511#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
512 eAutocompleteUnsupportedFieldName_##name_,
513#include "AutocompleteFieldList.h"
514#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
515};
516
517enum AutocompleteNoPersistFieldName : uint8_t {
518#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
519 eAutocompleteNoPersistFieldName_##name_,
520#include "AutocompleteFieldList.h"
521#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
522};
523
524enum AutocompleteUnsupportFieldContactHint : uint8_t {
525#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
526 eAutocompleteUnsupportedFieldContactHint_##name_,
527#include "AutocompleteFieldList.h"
528#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
529};
530
531enum AutocompleteFieldName : uint8_t {
532#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
533#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
534 AUTOCOMPLETE_FIELD_NAME(name_, value_)
535#include "AutocompleteFieldList.h"
536#undef AUTOCOMPLETE_FIELD_NAME
537#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
538};
539
540enum AutocompleteFieldHint : uint8_t {
541#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
542#include "AutocompleteFieldList.h"
543#undef AUTOCOMPLETE_FIELD_HINT
544};
545
546enum AutocompleteFieldContactHint : uint8_t {
547#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
548 eAutocompleteFieldContactHint_##name_,
549#include "AutocompleteFieldList.h"
550#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
551};
552
553enum AutocompleteCredentialType : uint8_t {
554#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
555 eAutocompleteCredentialType_##name_,
556#include "AutocompleteFieldList.h"
557#undef AUTOCOMPLETE_CREDENTIAL_TYPE
558};
559
560enum AutocompleteCategory {
561#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
562#include "AutocompleteFieldList.h"
563#undef AUTOCOMPLETE_CATEGORY
564};
565
566static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
567#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
568 {value_, eAutocompleteUnsupportedFieldName_##name_},
569#include "AutocompleteFieldList.h"
570#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
571 {nullptr, 0}};
572
573static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = {
574#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
575 {value_, eAutocompleteNoPersistFieldName_##name_},
576#include "AutocompleteFieldList.h"
577#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
578 {nullptr, 0}};
579
580static const nsAttrValue::EnumTable
581 kAutocompleteUnsupportedContactFieldHintTable[] = {
582#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
583 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
584#include "AutocompleteFieldList.h"
585#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
586 {nullptr, 0}};
587
588static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
589#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
590 {value_, eAutocompleteFieldName_##name_},
591#include "AutocompleteFieldList.h"
592#undef AUTOCOMPLETE_FIELD_NAME
593 {nullptr, 0}};
594
595static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
596#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
597 {value_, eAutocompleteFieldName_##name_},
598#include "AutocompleteFieldList.h"
599#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
600 {nullptr, 0}};
601
602static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
603#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
604 {value_, eAutocompleteFieldHint_##name_},
605#include "AutocompleteFieldList.h"
606#undef AUTOCOMPLETE_FIELD_HINT
607 {nullptr, 0}};
608
609static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
610#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
611 {value_, eAutocompleteFieldContactHint_##name_},
612#include "AutocompleteFieldList.h"
613#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
614 {nullptr, 0}};
615
616static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = {
617#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
618 {value_, eAutocompleteCredentialType_##name_},
619#include "AutocompleteFieldList.h"
620#undef AUTOCOMPLETE_CREDENTIAL_TYPE
621 {nullptr, 0}};
622
623namespace {
624
625static PLDHashTable* sEventListenerManagersHash;
626
627// A global hashtable to for keeping the arena alive for cross docGroup node
628// adoption.
629static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
630 sDOMArenaHashtable;
631
632class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter {
633 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)static size_t MallocSizeOf(const void* aPtr) { mozilla::dmd::
Report(aPtr); return moz_malloc_size_of(aPtr); }
634
635 ~DOMEventListenerManagersHashReporter() = default;
636
637 public:
638 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:
639
640 NS_IMETHODvirtual nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
641 nsISupports* aData, bool aAnonymize) override {
642 // We don't measure the |EventListenerManager| objects pointed to by the
643 // entries because those references are non-owning.
644 int64_t amount =
645 sEventListenerManagersHash
646 ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
647 MallocSizeOf)
648 : 0;
649
650 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)
651 "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)
652 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)
;
653
654 return NS_OK;
655 }
656};
657
658NS_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"
, 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
658; __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"
, 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 658; __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"
, 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 658
; __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"
, 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 658; __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"
, 658); 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((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
659
660class EventListenerManagerMapEntry : public PLDHashEntryHdr {
661 public:
662 explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {}
663
664 ~EventListenerManagerMapEntry() {
665 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"
, 665); MOZ_PretendNoReturn(); } } while (0)
;
666 }
667
668 protected: // declared protected to silence clang warnings
669 const void* mKey; // must be first, to look like PLDHashEntryStub
670
671 public:
672 RefPtr<EventListenerManager> mListenerManager;
673};
674
675static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry,
676 const void* key) {
677 // Initialize the entry with placement new
678 new (entry) EventListenerManagerMapEntry(key);
679}
680
681static void EventListenerManagerHashClearEntry(PLDHashTable* table,
682 PLDHashEntryHdr* entry) {
683 EventListenerManagerMapEntry* lm =
684 static_cast<EventListenerManagerMapEntry*>(entry);
685
686 // Let the EventListenerManagerMapEntry clean itself up...
687 lm->~EventListenerManagerMapEntry();
688}
689
690class SameOriginCheckerImpl final : public nsIChannelEventSink,
691 public nsIInterfaceRequestor {
692 ~SameOriginCheckerImpl() = default;
693
694 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:
695 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
696 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
697};
698
699} // namespace
700
701void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
702 // Note: Document::SuppressEventHandling will also automatically suppress
703 // event handling for any in-process sub-documents. However, since we need
704 // to deal with cases where remote BrowsingContexts may be interleaved
705 // with in-process ones, we still need to walk the entire tree ourselves.
706 // This may be slightly redundant in some cases, but since event handling
707 // suppressions maintain a count of current blockers, it does not cause
708 // any problems.
709 aDoc->SuppressEventHandling();
710}
711
712void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
713 aDoc->UnsuppressEventHandlingAndFireEvents(true);
714}
715
716AutoSuppressEventHandling::~AutoSuppressEventHandling() {
717 UnsuppressDocuments();
718}
719
720void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
721 AutoSuppressEventHandling::SuppressDocument(aDoc);
722 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
723 win->Suspend();
724 mWindows.AppendElement(win);
725 }
726}
727
728AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
729 for (const auto& win : mWindows) {
730 win->Resume();
731 }
732}
733
734/**
735 * This class is used to determine whether or not the user is currently
736 * interacting with the browser. It listens to observer events to toggle the
737 * value of the sUserActive static.
738 *
739 * This class is an internal implementation detail.
740 * nsContentUtils::GetUserIsInteracting() should be used to access current
741 * user interaction status.
742 */
743class nsContentUtils::UserInteractionObserver final
744 : public nsIObserver,
745 public BackgroundHangAnnotator {
746 public:
747 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:
748 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
749
750 void Init();
751 void Shutdown();
752 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
753
754 static Atomic<bool> sUserActive;
755
756 private:
757 ~UserInteractionObserver() = default;
758};
759
760static constexpr nsLiteralCString kRfpPrefs[] = {
761 "privacy.resistFingerprinting"_ns,
762 "privacy.resistFingerprinting.pbmode"_ns,
763 "privacy.fingerprintingProtection"_ns,
764 "privacy.fingerprintingProtection.pbmode"_ns,
765 "privacy.fingerprintingProtection.overrides"_ns,
766};
767
768static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
769 AutoTArray<RefPtr<BrowsingContextGroup>, 5> bcGroups;
770 BrowsingContextGroup::GetAllGroups(bcGroups);
771 for (auto& bcGroup : bcGroups) {
772 AutoTArray<DocGroup*, 5> docGroups;
773 bcGroup->GetDocGroups(docGroups);
774 for (auto* docGroup : docGroups) {
775 for (Document* doc : *docGroup) {
776 if (doc->RecomputeResistFingerprinting()) {
777 if (auto* pc = doc->GetPresContext()) {
778 pc->MediaFeatureValuesChanged(
779 {MediaFeatureChangeReason::PreferenceChange},
780 MediaFeatureChangePropagation::JustThisDocument);
781 }
782 }
783 }
784 }
785 }
786}
787
788// static
789nsresult nsContentUtils::Init() {
790 if (sInitialized) {
791 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"
, 791)
;
792
793 return NS_OK;
794 }
795
796 nsHTMLTags::AddRefTable();
797
798 sXPConnect = nsXPConnect::XPConnect();
799 // We hold a strong ref to sXPConnect to ensure that it does not go away until
800 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
801 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
802 // various stuff already being torn down by then. Note that this means that
803 // we are effectively making sure that if we leak nsLayoutStatics then we also
804 // leak nsXPConnect.
805 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
806
807 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
808 if (!sSecurityManager) return NS_ERROR_FAILURE;
809 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
810
811 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
812 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"
, 812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSystemPrincipal"
")"); do { *((volatile int*)__null) = 812; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
813
814 RefPtr<NullPrincipal> nullPrincipal =
815 NullPrincipal::CreateWithoutOriginAttributes();
816 if (!nullPrincipal) {
817 return NS_ERROR_FAILURE;
818 }
819
820 nullPrincipal.forget(&sNullSubjectPrincipal);
821
822 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
823
824 if (!sEventListenerManagersHash) {
825 static const PLDHashTableOps hash_table_ops = {
826 PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub,
827 PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry,
828 EventListenerManagerHashInitEntry};
829
830 sEventListenerManagersHash =
831 new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
832
833 RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
834 }
835
836 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
837
838#ifndef RELEASE_OR_BETA
839 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
840#endif
841
842 Element::InitCCCallbacks();
843
844 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
845 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"
, 845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService" ")"
); do { *((volatile int*)__null) = 845; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
846
847 if (XRE_IsParentProcess()) {
848 AsyncPrecreateStringBundles();
849
850#if defined(MOZ_WIDGET_ANDROID)
851 // On Android, at-shutdown ping submission isn't reliable
852 // (( because, on Android, we usually get killed, not shut down )).
853 // To have a chance at submitting the ping, aim for idle after startup.
854 nsresult rv = NS_DispatchToCurrentThreadQueue(
855 NS_NewRunnableFunction(
856 "AndroidUseCounterPingSubmitter",
857 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
858 EventQueuePriority::Idle);
859 // This is mostly best-effort, so if it goes awry, just log.
860 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"
, 860)
;
861#endif // defined(MOZ_WIDGET_ANDROID)
862
863 RunOnShutdown(
864 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
865 ShutdownPhase::AppShutdownConfirmed);
866 }
867
868 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
869 uio->Init();
870 uio.forget(&sUserInteractionObserver);
871
872 for (const auto& pref : kRfpPrefs) {
873 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
874 }
875
876 sInitialized = true;
877
878 return NS_OK;
879}
880
881bool nsContentUtils::InitJSBytecodeMimeType() {
882 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"
, 882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
883 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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType"
")"); do { *((volatile int*)__null) = 883; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
884 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"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType"
")"); do { *((volatile int*)__null) = 884; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
885
886 JS::BuildIdCharVector jsBuildId;
887 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
888 return false;
889 }
890
891 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
892 sJSScriptBytecodeMimeType =
893 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
894 sJSModuleBytecodeMimeType =
895 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
896 return true;
897}
898
899void nsContentUtils::GetShiftText(nsAString& text) {
900 if (!sShiftText) InitializeModifierStrings();
901 text.Assign(*sShiftText);
902}
903
904void nsContentUtils::GetControlText(nsAString& text) {
905 if (!sControlText) InitializeModifierStrings();
906 text.Assign(*sControlText);
907}
908
909void nsContentUtils::GetCommandOrWinText(nsAString& text) {
910 if (!sCommandOrWinText) {
911 InitializeModifierStrings();
912 }
913 text.Assign(*sCommandOrWinText);
914}
915
916void nsContentUtils::GetAltText(nsAString& text) {
917 if (!sAltText) InitializeModifierStrings();
918 text.Assign(*sAltText);
919}
920
921void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
922 if (!sModifierSeparator) InitializeModifierStrings();
923 text.Assign(*sModifierSeparator);
924}
925
926void nsContentUtils::InitializeModifierStrings() {
927 // load the display strings for the keyboard accelerators
928 nsCOMPtr<nsIStringBundleService> bundleService =
929 mozilla::components::StringBundle::Service();
930 nsCOMPtr<nsIStringBundle> bundle;
931 DebugOnly<nsresult> rv = NS_OK;
932 if (bundleService) {
933 rv = bundleService->CreateBundle(
934 "chrome://global-platform/locale/platformKeys.properties",
935 getter_AddRefs(bundle));
936 }
937
938 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"
, 940); MOZ_PretendNoReturn(); } } while (0)
939 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"
, 940); MOZ_PretendNoReturn(); } } while (0)
940 "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"
, 940); MOZ_PretendNoReturn(); } } while (0)
;
941 nsAutoString shiftModifier;
942 nsAutoString commandOrWinModifier;
943 nsAutoString altModifier;
944 nsAutoString controlModifier;
945 nsAutoString modifierSeparator;
946 if (bundle) {
947 // macs use symbols for each modifier key, so fetch each from the bundle,
948 // which also covers i18n
949 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
950 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
951 bundle->GetStringFromName("VK_ALT", altModifier);
952 bundle->GetStringFromName("VK_CONTROL", controlModifier);
953 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
954 }
955 // if any of these don't exist, we get an empty string
956 sShiftText = new nsString(shiftModifier);
957 sCommandOrWinText = new nsString(commandOrWinModifier);
958 sAltText = new nsString(altModifier);
959 sControlText = new nsString(controlModifier);
960 sModifierSeparator = new nsString(modifierSeparator);
961}
962
963mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
964 EventMessage aEventMessage) {
965 switch (aEventMessage) {
966#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
967 case message_: \
968 return struct_;
969#include "mozilla/EventNameList.h"
970#undef MESSAGE_TO_EVENT
971 default:
972 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"
, 972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ *((volatile int*)__null) = 972; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
973 return eBasicEventClass;
974 }
975}
976
977bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
978 bool doesNotReturnData = false;
979 nsresult rv = NS_URIChainHasFlags(
980 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
981 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
982}
983
984/* static */
985nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
986 switch (aEventMessage) {
987#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
988 case message_: \
989 return nsGkAtoms::on##name_;
990#include "mozilla/EventNameList.h"
991#undef MESSAGE_TO_EVENT
992 default:
993 return nullptr;
994 }
995}
996
997bool nsContentUtils::InitializeEventTable() {
998 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"
, 998); MOZ_PretendNoReturn(); } } while (0)
;
999 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"
, 999); MOZ_PretendNoReturn(); } } while (0)
;
1000
1001 static const EventNameMapping eventArray[] = {
1002#define EVENT(name_, _message, _type, _class) \
1003 {nsGkAtoms::on##name_, _type, _message, _class},
1004#define WINDOW_ONLY_EVENT EVENT
1005#define DOCUMENT_ONLY_EVENTEVENT EVENT
1006#define NON_IDL_EVENT EVENT
1007#include "mozilla/EventNameList.h"
1008#undef WINDOW_ONLY_EVENT
1009#undef NON_IDL_EVENT
1010#undef EVENT
1011 {nullptr}};
1012
1013 sAtomEventTable =
1014 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(ArrayLength(eventArray));
1015 sStringEventTable = new nsTHashMap<nsStringHashKey, EventNameMapping>(
1016 ArrayLength(eventArray));
1017 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1018
1019 // Subtract one from the length because of the trailing null
1020 for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) {
1021 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"
, 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1022 "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"
, 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1023 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1024 sStringEventTable->InsertOrUpdate(
1025 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1026 eventArray[i]);
1027 }
1028
1029 return true;
1030}
1031
1032void nsContentUtils::InitializeTouchEventTable() {
1033 static bool sEventTableInitialized = false;
1034 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1035 sEventTableInitialized = true;
1036 static const EventNameMapping touchEventArray[] = {
1037#define EVENT(name_, _message, _type, _class)
1038#define TOUCH_EVENT(name_, _message, _type, _class) \
1039 {nsGkAtoms::on##name_, _type, _message, _class},
1040#include "mozilla/EventNameList.h"
1041#undef TOUCH_EVENT
1042#undef EVENT
1043 {nullptr}};
1044 // Subtract one from the length because of the trailing null
1045 for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
1046 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1047 touchEventArray[i]);
1048 sStringEventTable->InsertOrUpdate(
1049 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1050 touchEventArray[i]);
1051 }
1052 }
1053}
1054
1055static bool Is8bit(const nsAString& aString) {
1056 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1057
1058 for (nsAString::const_char_iterator start = aString.BeginReading(),
1059 end = aString.EndReading();
1060 start != end; ++start) {
1061 if (*start & EIGHT_BIT) {
1062 return false;
1063 }
1064 }
1065
1066 return true;
1067}
1068
1069nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1070 nsAString& aAsciiBase64String) {
1071 if (!Is8bit(aBinaryData)) {
1072 aAsciiBase64String.Truncate();
1073 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1074 }
1075
1076 return Base64Encode(aBinaryData, aAsciiBase64String);
1077}
1078
1079nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1080 nsAString& aBinaryData) {
1081 if (!Is8bit(aAsciiBase64String)) {
1082 aBinaryData.Truncate();
1083 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1084 }
1085
1086 const char16_t* start = aAsciiBase64String.BeginReading();
1087 const char16_t* cur = start;
1088 const char16_t* end = aAsciiBase64String.EndReading();
1089 bool hasWhitespace = false;
1090
1091 while (cur < end) {
1092 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1093 hasWhitespace = true;
1094 break;
1095 }
1096 cur++;
1097 }
1098
1099 nsresult rv;
1100
1101 if (hasWhitespace) {
1102 nsString trimmedString;
1103
1104 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1105 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1106 }
1107
1108 trimmedString.Append(start, cur - start);
1109
1110 while (cur < end) {
1111 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1112 trimmedString.Append(*cur);
1113 }
1114 cur++;
1115 }
1116 rv = Base64Decode(trimmedString, aBinaryData);
1117 } else {
1118 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1119 }
1120
1121 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1122 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1123 }
1124 return rv;
1125}
1126
1127bool nsContentUtils::IsAutocompleteEnabled(
1128 mozilla::dom::HTMLInputElement* aInput) {
1129 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"
, 1129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInput" ") ("
"aInput should not be null!" ")"); do { *((volatile int*)__null
) = 1129; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1130
1131 nsAutoString autocomplete;
1132 aInput->GetAutocomplete(autocomplete);
1133
1134 if (autocomplete.IsEmpty()) {
1135 auto* form = aInput->GetForm();
1136 if (!form) {
1137 return true;
1138 }
1139
1140 form->GetAutocomplete(autocomplete);
1141 }
1142
1143 return !autocomplete.EqualsLiteral("off");
1144}
1145
1146nsContentUtils::AutocompleteAttrState
1147nsContentUtils::SerializeAutocompleteAttribute(
1148 const nsAttrValue* aAttr, nsAString& aResult,
1149 AutocompleteAttrState aCachedState) {
1150 if (!aAttr ||
1151 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1152 return aCachedState;
1153 }
1154
1155 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1156 uint32_t atomCount = aAttr->GetAtomCount();
1157 for (uint32_t i = 0; i < atomCount; i++) {
1158 if (i != 0) {
1159 aResult.Append(' ');
1160 }
1161 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1162 }
1163 nsContentUtils::ASCIIToLower(aResult);
1164 return aCachedState;
1165 }
1166
1167 aResult.Truncate();
1168
1169 mozilla::dom::AutocompleteInfo info;
1170 AutocompleteAttrState state =
1171 InternalSerializeAutocompleteAttribute(aAttr, info);
1172 if (state == eAutocompleteAttrState_Valid) {
1173 // Concatenate the info fields.
1174 aResult = info.mSection;
1175
1176 if (!info.mAddressType.IsEmpty()) {
1177 if (!aResult.IsEmpty()) {
1178 aResult += ' ';
1179 }
1180 aResult += info.mAddressType;
1181 }
1182
1183 if (!info.mContactType.IsEmpty()) {
1184 if (!aResult.IsEmpty()) {
1185 aResult += ' ';
1186 }
1187 aResult += info.mContactType;
1188 }
1189
1190 if (!info.mFieldName.IsEmpty()) {
1191 if (!aResult.IsEmpty()) {
1192 aResult += ' ';
1193 }
1194 aResult += info.mFieldName;
1195 }
1196
1197 // The autocomplete attribute value "webauthn" is interpreted as both a
1198 // field name and a credential type. The corresponding IDL-exposed autofill
1199 // value is "webauthn", not "webauthn webauthn".
1200 if (!info.mCredentialType.IsEmpty() &&
1201 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1202 info.mCredentialType.Equals(aResult))) {
1203 if (!aResult.IsEmpty()) {
1204 aResult += ' ';
1205 }
1206 aResult += info.mCredentialType;
1207 }
1208 }
1209
1210 return state;
1211}
1212
1213nsContentUtils::AutocompleteAttrState
1214nsContentUtils::SerializeAutocompleteAttribute(
1215 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1216 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1217 if (!aAttr ||
1218 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1219 return aCachedState;
1220 }
1221
1222 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1223 aGrantAllValidValue);
1224}
1225
1226/**
1227 * Helper to validate the @autocomplete tokens.
1228 *
1229 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1230 */
1231nsContentUtils::AutocompleteAttrState
1232nsContentUtils::InternalSerializeAutocompleteAttribute(
1233 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1234 bool aGrantAllValidValue) {
1235 // No autocomplete attribute so we are done
1236 if (!aAttrVal) {
1237 return eAutocompleteAttrState_Invalid;
1238 }
1239
1240 uint32_t numTokens = aAttrVal->GetAtomCount();
1241 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1242 return eAutocompleteAttrState_Invalid;
1243 }
1244
1245 uint32_t index = numTokens - 1;
1246 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1247 AutocompleteCategory category;
1248 nsAttrValue enumValue;
1249 nsAutoString credentialTypeStr;
1250
1251 bool result = enumValue.ParseEnumValue(
1252 tokenString, kAutocompleteCredentialTypeTable, false);
1253 if (result) {
1254 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1255 return eAutocompleteAttrState_Invalid;
1256 }
1257 enumValue.ToString(credentialTypeStr);
1258 ASCIIToLower(credentialTypeStr);
1259 // category is Credential and the indexth token is "webauthn"
1260 if (index == 0) {
1261 aInfo.mFieldName.Assign(credentialTypeStr);
1262 aInfo.mCredentialType.Assign(credentialTypeStr);
1263 return eAutocompleteAttrState_Valid;
1264 }
1265
1266 --index;
1267 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1268
1269 // Only the Normal and Contact categories are allowed with webauthn
1270 // - disallow Credential
1271 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1272 false)) {
1273 return eAutocompleteAttrState_Invalid;
1274 }
1275 // - disallow Off and Automatic
1276 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1277 false)) {
1278 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1279 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1280 return eAutocompleteAttrState_Invalid;
1281 }
1282 }
1283
1284 // Proceed to process the remaining tokens as if "webauthn" was not present.
1285 // We need to decrement numTokens to enforce the correct per-category limits
1286 // on the maximum number of tokens.
1287 --numTokens;
1288 }
1289
1290 bool unsupported = false;
1291 if (!aGrantAllValidValue) {
1292 unsupported = enumValue.ParseEnumValue(
1293 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1294 if (unsupported) {
1295 return eAutocompleteAttrState_Invalid;
1296 }
1297 }
1298
1299 nsAutoString fieldNameStr;
1300 result =
1301 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1302
1303 if (result) {
1304 // Off/Automatic/Normal categories.
1305 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1306 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1307 if (numTokens > 1) {
1308 return eAutocompleteAttrState_Invalid;
1309 }
1310 enumValue.ToString(fieldNameStr);
1311 ASCIIToLower(fieldNameStr);
1312 aInfo.mFieldName.Assign(fieldNameStr);
1313 aInfo.mCredentialType.Assign(credentialTypeStr);
1314 aInfo.mCanAutomaticallyPersist =
1315 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1316 return eAutocompleteAttrState_Valid;
1317 }
1318
1319 // Only allow on/off if form autofill @autocomplete values aren't enabled
1320 // and it doesn't grant all valid values.
1321 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1322 !aGrantAllValidValue) {
1323 return eAutocompleteAttrState_Invalid;
1324 }
1325
1326 // Normal category
1327 if (numTokens > 3) {
1328 return eAutocompleteAttrState_Invalid;
1329 }
1330 category = eAutocompleteCategory_NORMAL;
1331 } else { // Check if the last token is of the contact category instead.
1332 // Only allow on/off if form autofill @autocomplete values aren't enabled
1333 // and it doesn't grant all valid values.
1334 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1335 !aGrantAllValidValue) {
1336 return eAutocompleteAttrState_Invalid;
1337 }
1338
1339 result = enumValue.ParseEnumValue(
1340 tokenString, kAutocompleteContactFieldNameTable, false);
1341 if (!result || numTokens > 4) {
1342 return eAutocompleteAttrState_Invalid;
1343 }
1344
1345 category = eAutocompleteCategory_CONTACT;
1346 }
1347
1348 enumValue.ToString(fieldNameStr);
1349 ASCIIToLower(fieldNameStr);
1350
1351 aInfo.mFieldName.Assign(fieldNameStr);
1352 aInfo.mCredentialType.Assign(credentialTypeStr);
1353 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1354 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1355
1356 // We are done if this was the only token.
1357 if (numTokens == 1) {
1358 return eAutocompleteAttrState_Valid;
1359 }
1360
1361 --index;
1362 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1363
1364 if (category == eAutocompleteCategory_CONTACT) {
1365 if (!aGrantAllValidValue) {
1366 unsupported = enumValue.ParseEnumValue(
1367 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1368 if (unsupported) {
1369 return eAutocompleteAttrState_Invalid;
1370 }
1371 }
1372
1373 nsAttrValue contactFieldHint;
1374 result = contactFieldHint.ParseEnumValue(
1375 tokenString, kAutocompleteContactFieldHintTable, false);
1376 if (result) {
1377 nsAutoString contactFieldHintString;
1378 contactFieldHint.ToString(contactFieldHintString);
1379 ASCIIToLower(contactFieldHintString);
1380 aInfo.mContactType.Assign(contactFieldHintString);
1381 if (index == 0) {
1382 return eAutocompleteAttrState_Valid;
1383 }
1384 --index;
1385 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1386 }
1387 }
1388
1389 // Check for billing/shipping tokens
1390 nsAttrValue fieldHint;
1391 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1392 false)) {
1393 nsString fieldHintString;
1394 fieldHint.ToString(fieldHintString);
1395 ASCIIToLower(fieldHintString);
1396 aInfo.mAddressType.Assign(fieldHintString);
1397 if (index == 0) {
1398 return eAutocompleteAttrState_Valid;
1399 }
1400 --index;
1401 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1402 }
1403
1404 // Check for section-* token
1405 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1406 if (section.LowerCaseEqualsASCII("section-")) {
1407 ASCIIToLower(tokenString);
1408 aInfo.mSection.Assign(tokenString);
1409 if (index == 0) {
1410 return eAutocompleteAttrState_Valid;
1411 }
1412 }
1413
1414 // Clear the fields as the autocomplete attribute is invalid.
1415 aInfo.mSection.Truncate();
1416 aInfo.mAddressType.Truncate();
1417 aInfo.mContactType.Truncate();
1418 aInfo.mFieldName.Truncate();
1419 aInfo.mCredentialType.Truncate();
1420
1421 return eAutocompleteAttrState_Invalid;
1422}
1423
1424// Parse an integer according to HTML spec
1425template <class CharT>
1426int32_t nsContentUtils::ParseHTMLIntegerImpl(
1427 const CharT* aStart, const CharT* aEnd,
1428 ParseHTMLIntegerResultFlags* aResult) {
1429 int result = eParseHTMLInteger_NoFlags;
1430
1431 const CharT* iter = aStart;
1432
1433 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1434 result |= eParseHTMLInteger_NonStandard;
1435 ++iter;
1436 }
1437
1438 if (iter == aEnd) {
1439 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1440 *aResult = (ParseHTMLIntegerResultFlags)result;
1441 return 0;
1442 }
1443
1444 int sign = 1;
1445 if (*iter == CharT('-')) {
1446 sign = -1;
1447 result |= eParseHTMLInteger_Negative;
1448 ++iter;
1449 } else if (*iter == CharT('+')) {
1450 result |= eParseHTMLInteger_NonStandard;
1451 ++iter;
1452 }
1453
1454 bool foundValue = false;
1455 CheckedInt32 value = 0;
1456
1457 // Check for leading zeros first.
1458 uint64_t leadingZeros = 0;
1459 while (iter != aEnd) {
1460 if (*iter != CharT('0')) {
1461 break;
1462 }
1463
1464 ++leadingZeros;
1465 foundValue = true;
1466 ++iter;
1467 }
1468
1469 while (iter != aEnd) {
1470 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1471 value = (value * 10) + (*iter - CharT('0')) * sign;
1472 ++iter;
1473 if (!value.isValid()) {
1474 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1475 break;
1476 }
1477 foundValue = true;
1478 } else {
1479 break;
1480 }
1481 }
1482
1483 if (!foundValue) {
1484 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1485 }
1486
1487 if (value.isValid() &&
1488 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1489 (sign == -1 && value == 0))) {
1490 result |= eParseHTMLInteger_NonStandard;
1491 }
1492
1493 if (iter != aEnd) {
1494 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1495 }
1496
1497 *aResult = (ParseHTMLIntegerResultFlags)result;
1498 return value.isValid() ? value.value() : 0;
1499}
1500
1501// Parse an integer according to HTML spec
1502int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1503 const char16_t* aEnd,
1504 ParseHTMLIntegerResultFlags* aResult) {
1505 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1506}
1507
1508int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1509 ParseHTMLIntegerResultFlags* aResult) {
1510 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1511}
1512
1513#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
1514 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
1515 ++(iter); \
1516 } \
1517 if ((iter) == (end_iter)) { \
1518 return (end_res); \
1519 }
1520
1521#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
1522 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
1523 *(iter) != '=') { \
1524 ++(iter); \
1525 }
1526
1527bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
1528 nsAtom* aName, nsAString& aValue) {
1529 aValue.Truncate();
1530
1531 const char16_t* start = aSource.get();
1532 const char16_t* end = start + aSource.Length();
1533 const char16_t* iter;
1534
1535 while (start != end) {
1536 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1537 iter = start;
1538 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
1539
1540 if (start == iter) {
1541 return false;
1542 }
1543
1544 // Remember the attr name.
1545 const nsDependentSubstring& attrName = Substring(start, iter);
1546
1547 // Now check whether this is a valid name="value" pair.
1548 start = iter;
1549 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1550 if (*start != '=') {
1551 // No '=', so this is not a name="value" pair. We don't know
1552 // what it is, and we have no way to handle it.
1553 return false;
1554 }
1555
1556 // Have to skip the value.
1557 ++start;
1558 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1559 char16_t q = *start;
1560 if (q != kQuote && q != kApostrophe) {
1561 // Not a valid quoted value, so bail.
1562 return false;
1563 }
1564
1565 ++start; // Point to the first char of the value.
1566 iter = start;
1567
1568 while (iter != end && *iter != q) {
1569 ++iter;
1570 }
1571
1572 if (iter == end) {
1573 // Oops, unterminated quoted string.
1574 return false;
1575 }
1576
1577 // At this point attrName holds the name of the "attribute" and
1578 // the value is between start and iter.
1579
1580 if (aName->Equals(attrName)) {
1581 // We'll accumulate as many characters as possible (until we hit either
1582 // the end of the string or the beginning of an entity). Chunks will be
1583 // delimited by start and chunkEnd.
1584 const char16_t* chunkEnd = start;
1585 while (chunkEnd != iter) {
1586 if (*chunkEnd == kLessThan) {
1587 aValue.Truncate();
1588
1589 return false;
1590 }
1591
1592 if (*chunkEnd == kAmpersand) {
1593 aValue.Append(start, chunkEnd - start);
1594
1595 const char16_t* afterEntity = nullptr;
1596 char16_t result[2];
1597 uint32_t count = MOZ_XMLTranslateEntity(
1598 reinterpret_cast<const char*>(chunkEnd),
1599 reinterpret_cast<const char*>(iter),
1600 reinterpret_cast<const char**>(&afterEntity), result);
1601 if (count == 0) {
1602 aValue.Truncate();
1603
1604 return false;
1605 }
1606
1607 aValue.Append(result, count);
1608
1609 // Advance to after the entity and begin a new chunk.
1610 start = chunkEnd = afterEntity;
1611 } else {
1612 ++chunkEnd;
1613 }
1614 }
1615
1616 // Append remainder.
1617 aValue.Append(start, iter - start);
1618
1619 return true;
1620 }
1621
1622 // Resume scanning after the end of the attribute value (past the quote
1623 // char).
1624 start = iter + 1;
1625 }
1626
1627 return false;
1628}
1629
1630bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
1631 // Create MIME type as "text/" + given input
1632 nsAutoString mimeType(u"text/");
1633 mimeType.Append(aName);
1634
1635 return IsJavascriptMIMEType(mimeType);
1636}
1637
1638void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
1639 nsString& aParams) {
1640 aType.Truncate();
1641 aParams.Truncate();
1642 int32_t semiIndex = aValue.FindChar(char16_t(';'));
1643 if (-1 != semiIndex) {
1644 aType = Substring(aValue, 0, semiIndex);
1645 aParams =
1646 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
1647 aParams.StripWhitespace();
1648 } else {
1649 aType = aValue;
1650 }
1651 aType.StripWhitespace();
1652}
1653
1654/**
1655 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
1656 * directive) and converts it to the set of flags used internally.
1657 *
1658 * @param aSandboxAttr the sandbox attribute
1659 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
1660 * null)
1661 */
1662uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
1663 const nsAttrValue* aSandboxAttr) {
1664 if (!aSandboxAttr) {
1665 return SANDBOXED_NONE;
1666 }
1667
1668 uint32_t out = SANDBOX_ALL_FLAGS;
1669
1670#define SANDBOX_KEYWORD(string, atom, flags) \
1671 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
1672 out &= ~(flags); \
1673 }
1674#include "IframeSandboxKeywordList.h"
1675#undef SANDBOX_KEYWORD
1676
1677 return out;
1678}
1679
1680/**
1681 * A helper function that checks if a string matches a valid sandbox flag.
1682 *
1683 * @param aFlag the potential sandbox flag.
1684 * @return true if the flag is a sandbox flag.
1685 */
1686bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
1687#define SANDBOX_KEYWORD(string, atom, flags) \
1688 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
1689 return true; \
1690 }
1691#include "IframeSandboxKeywordList.h"
1692#undef SANDBOX_KEYWORD
1693 return false;
1694}
1695
1696/**
1697 * A helper function that returns a string attribute corresponding to the
1698 * sandbox flags.
1699 *
1700 * @param aFlags the sandbox flags
1701 * @param aString the attribute corresponding to the flags (null if aFlags
1702 * is zero)
1703 */
1704void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
1705 if (!aFlags) {
1706 SetDOMStringToNull(aString);
1707 return;
1708 }
1709
1710 aString.Truncate();
1711
1712#define SANDBOX_KEYWORD(string, atom, flags) \
1713 if (!(aFlags & (flags))) { \
1714 if (!aString.IsEmpty()) { \
1715 aString.AppendLiteral(u" "); \
1716 } \
1717 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
1718 }
1719#include "IframeSandboxKeywordList.h"
1720#undef SANDBOX_KEYWORD
1721}
1722
1723nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
1724 if (!sBidiKeyboard) {
1725 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
1726 }
1727 return sBidiKeyboard;
1728}
1729
1730/**
1731 * This is used to determine whether a character is in one of the classes
1732 * which CSS says should be part of the first-letter. Currently, that is
1733 * all punctuation classes (P*). Note that this is a change from CSS2
1734 * which excluded Pc and Pd.
1735 *
1736 * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
1737 * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
1738 * general category [UAX44]) [...]"
1739 */
1740
1741// static
1742bool nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar) {
1743 switch (mozilla::unicode::GetGeneralCategory(aChar)) {
1744 case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
1745 case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */
1746 case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */
1747 case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */
1748 case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
1749 case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */
1750 case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */
1751 return true;
1752 default:
1753 return false;
1754 }
1755}
1756
1757// static
1758bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
1759 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1760
1761 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
1762}
1763
1764// static
1765bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
1766 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1767
1768 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
1769 cat == nsUGenCategory::kSymbol;
1770}
1771
1772// static
1773bool nsContentUtils::IsHyphen(uint32_t aChar) {
1774 // Characters treated as hyphens for the purpose of "emergency" breaking
1775 // when the content would otherwise overflow.
1776 return aChar == uint32_t('-') || // HYPHEN-MINUS
1777 aChar == 0x2010 || // HYPHEN
1778 aChar == 0x2012 || // FIGURE DASH
1779 aChar == 0x2013 || // EN DASH
1780 aChar == 0x058A; // ARMENIAN HYPHEN
1781}
1782
1783/* static */
1784bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
1785 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
1786 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
1787 aChar == char16_t(0x0020);
1788}
1789
1790/* static */
1791bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
1792 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
1793}
1794
1795/* static */
1796bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
1797 return aContent->IsAnyOfHTMLElements(
1798 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
1799 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
1800 nsGkAtoms::dl, // XXX why not dt and dd?
1801 nsGkAtoms::fieldset,
1802 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
1803 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
1804 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
1805 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
1806 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
1807 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
1808 nsGkAtoms::ul, nsGkAtoms::xmp);
1809}
1810
1811/* static */
1812bool nsContentUtils::ParseIntMarginValue(const nsAString& aString,
1813 nsIntMargin& result) {
1814 nsAutoString marginStr(aString);
1815 marginStr.CompressWhitespace(true, true);
1816 if (marginStr.IsEmpty()) {
1817 return false;
1818 }
1819
1820 int32_t start = 0, end = 0;
1821 for (int count = 0; count < 4; count++) {
1822 if ((uint32_t)end >= marginStr.Length()) return false;
1823
1824 // top, right, bottom, left
1825 if (count < 3)
1826 end = Substring(marginStr, start).FindChar(',');
1827 else
1828 end = Substring(marginStr, start).Length();
1829
1830 if (end <= 0) return false;
1831
1832 nsresult ec;
1833 int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec);
1834 if (NS_FAILED(ec)((bool)(__builtin_expect(!!(NS_FAILED_impl(ec)), 0)))) return false;
1835
1836 switch (count) {
1837 case 0:
1838 result.top = val;
1839 break;
1840 case 1:
1841 result.right = val;
1842 break;
1843 case 2:
1844 result.bottom = val;
1845 break;
1846 case 3:
1847 result.left = val;
1848 break;
1849 }
1850 start += end + 1;
1851 }
1852 return true;
1853}
1854
1855// static
1856int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
1857 nsAString::const_iterator iter, end;
1858 aValue.BeginReading(iter);
1859 aValue.EndReading(end);
1860
1861 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
1862 ++iter;
1863 }
1864
1865 if (iter == end) {
1866 return 0;
1867 }
1868
1869 bool relative = false;
1870 bool negate = false;
1871 if (*iter == char16_t('-')) {
1872 relative = true;
1873 negate = true;
1874 ++iter;
1875 } else if (*iter == char16_t('+')) {
1876 relative = true;
1877 ++iter;
1878 }
1879
1880 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
1881 return 0;
1882 }
1883
1884 // We don't have to worry about overflow, since we can bail out as soon as
1885 // we're bigger than 7.
1886 int32_t value = 0;
1887 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
1888 value = 10 * value + (*iter - char16_t('0'));
1889 if (value >= 7) {
1890 break;
1891 }
1892 ++iter;
1893 }
1894
1895 if (relative) {
1896 if (negate) {
1897 value = 3 - value;
1898 } else {
1899 value = 3 + value;
1900 }
1901 }
1902
1903 return clamped(value, 1, 7);
1904}
1905
1906/* static */
1907void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
1908 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"
, 1908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1909 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"
, 1909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 1909; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1910 *aURI = nullptr;
1911
1912 if (aDocument->GetController().isSome()) {
1913 return;
1914 }
1915
1916 Element* docElement = aDocument->GetRootElement();
1917 if (!docElement) {
1918 return;
1919 }
1920
1921 nsAutoString manifestSpec;
1922 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
1923
1924 // Manifest URIs can't have fragment identifiers.
1925 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
1926 return;
1927 }
1928
1929 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
1930 aDocument->GetDocBaseURI());
1931}
1932
1933/* static */
1934bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
1935
1936/* static */
1937bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
1938 return false;
1939}
1940// Static
1941bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
1942 if (!aURI) {
1943 return false;
1944 }
1945
1946 if (!aURI->SchemeIs("about")) {
1947 return false;
1948 }
1949
1950 nsAutoCString name;
1951 nsresult rv = NS_GetAboutModuleName(aURI, name);
1952 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"
, 1952); return false; } } while (false)
;
1953
1954 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
1955 name.EqualsLiteral("blocked");
1956}
1957
1958// static
1959void nsContentUtils::Shutdown() {
1960 sInitialized = false;
1961
1962 nsHTMLTags::ReleaseTable();
1963
1964 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
1965 sTriedToGetContentPolicy = false;
1966 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
1967 bundle = nullptr;
1968 }
1969
1970 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
1971 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
1972 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
1973 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
1974 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
1975 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
1976
1977 sBidiKeyboard = nullptr;
1978
1979 delete sAtomEventTable;
1980 sAtomEventTable = nullptr;
1981 delete sStringEventTable;
1982 sStringEventTable = nullptr;
1983 delete sUserDefinedEvents;
1984 sUserDefinedEvents = nullptr;
1985
1986 if (sEventListenerManagersHash) {
1987 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"
, 1988); MOZ_PretendNoReturn(); } } while (0)
1988 "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"
, 1988); MOZ_PretendNoReturn(); } } while (0)
;
1989
1990 // See comment above.
1991
1992 // However, we have to handle this table differently. If it still
1993 // has entries, we want to leak it too, so that we can keep it alive
1994 // in case any elements are destroyed. Because if they are, we need
1995 // their event listener managers to be destroyed too, or otherwise
1996 // it could leave dangling references in DOMClassInfo's preserved
1997 // wrapper table.
1998
1999 if (sEventListenerManagersHash->EntryCount() == 0) {
2000 delete sEventListenerManagersHash;
2001 sEventListenerManagersHash = nullptr;
2002 }
2003 }
2004
2005 if (sDOMArenaHashtable) {
2006 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"
, 2006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0"
")"); do { *((volatile int*)__null) = 2006; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2007 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"
, 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 2007; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2008 delete sDOMArenaHashtable;
2009 sDOMArenaHashtable = nullptr;
2010 }
2011
2012 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"
, 2013); MOZ_PretendNoReturn(); } } while (0)
2013 "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"
, 2013); MOZ_PretendNoReturn(); } } while (0)
;
2014 delete sBlockedScriptRunners;
2015 sBlockedScriptRunners = nullptr;
2016
2017 delete sShiftText;
2018 sShiftText = nullptr;
2019 delete sControlText;
2020 sControlText = nullptr;
2021 delete sCommandOrWinText;
2022 sCommandOrWinText = nullptr;
2023 delete sAltText;
2024 sAltText = nullptr;
2025 delete sModifierSeparator;
2026 sModifierSeparator = nullptr;
2027
2028 delete sJSScriptBytecodeMimeType;
2029 sJSScriptBytecodeMimeType = nullptr;
2030
2031 delete sJSModuleBytecodeMimeType;
2032 sJSModuleBytecodeMimeType = nullptr;
2033
2034 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2035
2036 if (sUserInteractionObserver) {
2037 sUserInteractionObserver->Shutdown();
2038 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2039 }
2040
2041 for (const auto& pref : kRfpPrefs) {
2042 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2043 }
2044
2045 TextControlState::Shutdown();
2046}
2047
2048/**
2049 * Checks whether two nodes come from the same origin. aTrustedNode is
2050 * considered 'safe' in that a user can operate on it.
2051 */
2052// static
2053nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2054 const nsINode* unTrustedNode) {
2055 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"
, 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { *((volatile int*)__null) = 2055; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2056 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"
, 2056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "unTrustedNode"
")"); do { *((volatile int*)__null) = 2056; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2057
2058 /*
2059 * Get hold of each node's principal
2060 */
2061
2062 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2063 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2064
2065 if (trustedPrincipal == unTrustedPrincipal) {
2066 return NS_OK;
2067 }
2068
2069 bool equal;
2070 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2071 // a separate method for that, with callers using one or the other?
2072 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2073 !equal) {
2074 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2075 }
2076
2077 return NS_OK;
2078}
2079
2080// static
2081bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2082 nsIPrincipal* aPrincipal) {
2083 bool subsumes;
2084 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2085 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"
, 2085); return false; } } while (false)
;
2086
2087 if (subsumes) {
2088 return true;
2089 }
2090
2091 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2092 // is chrome.
2093 return IsCallerChrome();
2094}
2095
2096// static
2097bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2098 nsIPrincipal* subject = SubjectPrincipal();
2099 if (subject->IsSystemPrincipal()) {
2100 return true;
2101 }
2102
2103 if (aNode->ChromeOnlyAccess()) {
2104 return false;
2105 }
2106
2107 return CanCallerAccess(subject, aNode->NodePrincipal());
2108}
2109
2110// static
2111bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2112 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2113 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"
, 2113); return false; } } while (false)
;
2114
2115 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2116}
2117
2118// static
2119bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2120 const nsAtom* aPerm) {
2121 // Chrome gets access by default.
2122 if (aPrincipal.IsSystemPrincipal()) {
2123 return true;
2124 }
2125
2126 // Otherwise, only allow if caller is an addon with the permission.
2127 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2128}
2129
2130// static
2131bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2132 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2133}
2134
2135// static
2136nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2137 nsIContent* aContent, const nsAString& aAttrValue,
2138 nsIPrincipal* aSubjectPrincipal) {
2139 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2140
2141 // If the subject principal is the same as the content principal, or no
2142 // explicit subject principal was provided, we don't need to do any further
2143 // checks. Just return the content principal.
2144 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2145 return contentPrin;
2146 }
2147
2148 // Only use the subject principal if the URL string we are going to end up
2149 // fetching is under the control of that principal, which is never the case
2150 // for relative URLs.
2151 if (aAttrValue.IsEmpty() ||
2152 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2153 return contentPrin;
2154 }
2155
2156 // Only use the subject principal as the attr triggering principal if it
2157 // should override the CSP of the node's principal.
2158 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2159 return aSubjectPrincipal;
2160 }
2161
2162 return contentPrin;
2163}
2164
2165// static
2166bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2167 nsAutoCString scheme;
2168 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2169 // If we can't extract a scheme, it's not an absolute URL.
2170 return false;
2171 }
2172
2173 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2174 // so no need to check with the IO service.
2175 if (net_IsAbsoluteURL(aURL)) {
2176 return true;
2177 }
2178
2179 nsresult rv = NS_OK;
2180 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2181 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"
, 2181); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2182 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2183 return false;
2184 }
2185
2186 uint32_t flags;
2187 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2188 return flags & nsIProtocolHandler::URI_NORELATIVE;
2189 }
2190
2191 return false;
2192}
2193
2194// static
2195bool nsContentUtils::InProlog(nsINode* aNode) {
2196 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"
, 2196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") ("
"missing node to nsContentUtils::InProlog" ")"); do { *((volatile
int*)__null) = 2196; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2197
2198 nsINode* parent = aNode->GetParentNode();
2199 if (!parent || !parent->IsDocument()) {
2200 return false;
2201 }
2202
2203 const Document* doc = parent->AsDocument();
2204 const nsIContent* root = doc->GetRootElement();
2205 if (!root) {
2206 return true;
2207 }
2208 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2209 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2210 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2211 return *indexOfNode < *indexOfRoot;
2212 }
2213 // XXX Keep the odd traditional behavior for now.
2214 return indexOfNode.isNothing() && indexOfRoot.isSome();
2215}
2216
2217bool nsContentUtils::IsCallerChrome() {
2218 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"
, 2218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2218; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2219 return SubjectPrincipal() == sSystemPrincipal;
2220}
2221
2222#ifdef FUZZING
2223bool nsContentUtils::IsFuzzingEnabled() {
2224 return StaticPrefs::fuzzing_enabled();
2225}
2226#endif
2227
2228/* static */
2229bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2230 JSContext* aCx, JSObject*) {
2231 return ThreadsafeIsSystemCaller(aCx) ||
2232 StaticPrefs::dom_element_transform_getters_enabled();
2233}
2234
2235// Older Should RFP Functions ----------------------------------
2236
2237/* static */
2238bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2239 RFPTarget aTarget) {
2240 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2241}
2242
2243/* static */
2244bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2245 RFPTarget aTarget) {
2246 if (!aGlobalObject) {
2247 return ShouldResistFingerprinting("Null Object", aTarget);
2248 }
2249 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2250}
2251
2252// Newer Should RFP Functions ----------------------------------
2253// Utilities ---------------------------------------------------
2254
2255inline void LogDomainAndPrefList(const char* urlType,
2256 const char* exemptedDomainsPrefName,
2257 nsAutoCString& url, bool isExemptDomain) {
2258 nsAutoCString list;
2259 Preferences::GetCString(exemptedDomainsPrefName, list);
2260 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)
2261 ("%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)
2262 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)
2263 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)
;
2264}
2265
2266inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2267 nsILoadInfo* aLoadInfo) {
2268 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2269 nsresult rv =
2270 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2271 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2272 // The TRRLoadInfo in particular does not implement this method
2273 // In that instance. We will return false and let other code decide if
2274 // we shouldRFP for this connection
2275 return nullptr;
2276 }
2277 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"
, 2277)
) {
2278 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)
2279 ("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)
2280 "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)
;
2281 return nullptr;
2282 }
2283
2284 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"
, 2284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cookieJarSettings"
")"); do { *((volatile int*)__null) = 2284; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2285 return cookieJarSettings.forget();
2286}
2287
2288bool ETPSaysShouldNotResistFingerprinting(nsIChannel* aChannel,
2289 nsILoadInfo* aLoadInfo) {
2290 // A positive return from this function should always be obeyed.
2291 // A negative return means we should keep checking things.
2292
2293 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2294 // We do not want this check to apply to RFP, only to FPP
2295 // There is one problematic combination of prefs; however:
2296 // If RFP is enabled in PBMode only and FPP is enabled globally
2297 // (so, in non-PBM mode) - we need to know if we're in PBMode or not.
2298 // But that's kind of expensive and we'd like to avoid it if we
2299 // don't have to, so special-case that scenario
2300 if (StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly() &&
2301 !StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2302 StaticPrefs::privacy_resistFingerprinting_pbmode_DoNotUseDirectly()) {
2303 if (isPBM) {
2304 // In PBM (where RFP is enabled) do not exempt based on the ETP toggle
2305 return false;
2306 }
2307 } else if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() ||
2308 (isPBM &&
2309 StaticPrefs::
2310 privacy_resistFingerprinting_pbmode_DoNotUseDirectly())) {
2311 // In RFP, never use the ETP toggle to exempt.
2312 // We can safely return false here even if we are not in PBM mode
2313 // and RFP_pbmode is enabled because we will later see that and
2314 // return false from the ShouldRFP function entirely.
2315 return false;
2316 }
2317
2318 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2319 GetCookieJarSettings(aLoadInfo);
2320 if (!cookieJarSettings) {
2321 return false;
2322 }
2323
2324 return ContentBlockingAllowList::Check(cookieJarSettings);
2325}
2326
2327inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2328 nsILoadInfo* aLoadInfo) {
2329 // A positive return from this function should always be obeyed.
2330 // A negative return means we should keep checking things.
2331
2332 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2333 GetCookieJarSettings(aLoadInfo);
2334 if (!cookieJarSettings) {
2335 return false;
2336 }
2337 return cookieJarSettings->GetShouldResistFingerprinting();
2338}
2339
2340inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2341 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2342 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2343 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2344}
2345
2346inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2347 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2348 aPrincipal->SchemeIs("view-source") ||
2349 aPrincipal->SchemeIs("moz-extension")) {
2350 return true;
2351 }
2352
2353 if (!aPrincipal->SchemeIs("about")) {
2354 return false;
2355 }
2356
2357 bool isContentAccessibleAboutURI;
2358 Unused << aPrincipal->IsContentAccessibleAboutURI(
2359 &isContentAccessibleAboutURI);
2360 return !isContentAccessibleAboutURI;
2361}
2362
2363const char* kExemptedDomainsPrefName =
2364 "privacy.resistFingerprinting.exemptedDomains";
2365
2366inline bool PartionKeyIsAlsoExempted(
2367 const mozilla::OriginAttributes& aOriginAttributes) {
2368 // If we've gotten here we have (probably) passed the CookieJarSettings
2369 // check that would tell us that if we _are_ a subdocument, then we are on
2370 // an exempted top-level domain and we should see if we ourselves are
2371 // exempted. But we may have gotten here because we directly called the
2372 // _dangerous function and we haven't done that check, but we _were_
2373 // instatiated from a state where we could have been partitioned.
2374 // So perform this last-ditch check for that scenario.
2375 // We arbitrarily use https as the scheme, but it doesn't matter.
2376 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2377 nsCOMPtr<nsIURI> uri;
2378 if (StaticPrefs::privacy_firstparty_isolate() &&
2379 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2380 rv = NS_NewURI(getter_AddRefs(uri),
2381 u"https://"_ns + aOriginAttributes.mFirstPartyDomain);
2382 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2383 rv = NS_NewURI(getter_AddRefs(uri),
2384 u"https://"_ns + aOriginAttributes.mPartitionKey);
2385 }
2386
2387 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2388 bool isExemptPartitionKey =
2389 nsContentUtils::IsURIInPrefList(uri, kExemptedDomainsPrefName);
2390 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2391 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2392 nsAutoCString url;
2393 uri->GetHost(url);
2394 LogDomainAndPrefList("Partition Key", kExemptedDomainsPrefName, url,
2395 isExemptPartitionKey);
2396 }
2397 return isExemptPartitionKey;
2398 }
2399 return true;
2400}
2401
2402// Functions ---------------------------------------------------
2403
2404/* static */
2405bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2406 RFPTarget aTarget) {
2407 // See comment in header file for information about usage
2408 // We hardcode PBM to true to be the more restrictive option.
2409 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2410}
2411
2412namespace {
2413
2414// This function is only called within this file for Positive Return Checks
2415bool ShouldResistFingerprinting_(const char* aJustification,
2416 bool aIsPrivateMode, RFPTarget aTarget) {
2417 // See comment in header file for information about usage
2418 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2419}
2420
2421} // namespace
2422
2423/* static */
2424bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2425 nsIGlobalObject* aGlobalObject,
2426 RFPTarget aTarget) {
2427 if (aCallerType == CallerType::System) {
2428 return false;
2429 }
2430 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2431}
2432
2433bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2434 RFPTarget aTarget) {
2435 if (!aDocShell) {
2436 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)
2437 ("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)
2438 "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)
;
2439 return ShouldResistFingerprinting("Null Object", aTarget);
2440 }
2441 Document* doc = aDocShell->GetDocument();
2442 if (!doc) {
2443 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)
2444 ("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)
2445 "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)
;
2446 return ShouldResistFingerprinting("Null Object", aTarget);
2447 }
2448 return doc->ShouldResistFingerprinting(aTarget);
2449}
2450
2451/* static */
2452bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2453 RFPTarget aTarget) {
2454 if (!aChannel) {
2455 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)
2456 ("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)
2457 "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)
;
2458 return ShouldResistFingerprinting("Null Object", aTarget);
2459 }
2460
2461 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
2462 if (!loadInfo) {
2463 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)
2464 ("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)
2465 "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)
;
2466 return ShouldResistFingerprinting("Null Object", aTarget);
2467 }
2468
2469 // With this check, we can ensure that the prefs and target say yes, so only
2470 // an exemption would cause us to return false.
2471 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2472 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2473 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)
2474 ("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)
2475 " 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)
2476 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)
;
2477 return false;
2478 }
2479
2480 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
2481 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)
2482 ("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)
2483 " 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)
;
2484 return false;
2485 }
2486
2487 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
2488 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)
2489 ("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)
2490 " 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)
;
2491 return true;
2492 }
2493
2494 // Document types have no loading principal. Subdocument types do have a
2495 // loading principal, but it is the loading principal of the parent
2496 // document; not the subdocument.
2497 auto contentType = loadInfo->GetExternalContentPolicyType();
2498 // Case 1: Document or Subdocument load
2499 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
2500 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2501 nsCOMPtr<nsIURI> channelURI;
2502 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2503 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"
, 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2504 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"
, 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2505 "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"
, 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2506 "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"
, 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2507 // this check is to ensure that we do not crash in non-debug builds.
2508 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2509 return true;
2510 }
2511
2512#if 0
2513 if (loadInfo->GetExternalContentPolicyType() == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2514 nsCOMPtr<nsIURI> channelURI;
2515 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2516 nsAutoCString channelSpec;
2517 channelURI->GetSpec(channelSpec);
2518
2519 if (!loadInfo->GetLoadingPrincipal()) {
2520 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)
2521 ("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)
2522 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)
;
2523
2524 } else {
2525 nsAutoCString loadingPrincipalSpec;
2526 loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec);
2527
2528 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)
2529 ("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)
2530 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)
;
2531 }
2532 }
2533
2534#endif
2535
2536 return ShouldResistFingerprinting_dangerous(
2537 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
2538 }
2539
2540 // Case 2: Subresource Load
2541 // Because this code is only used for subresource loads, this
2542 // will check the parent's principal
2543 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
2544
2545 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"
, 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2546 !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"
, 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2547 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"
, 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2548 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"
, 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2549 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
2550 aTarget);
2551}
2552
2553/* static */
2554bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2555 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
2556 const char* aJustification, RFPTarget aTarget) {
2557 // With this check, we can ensure that the prefs and target say yes, so only
2558 // an exemption would cause us to return false.
2559 bool isPBM = aOriginAttributes.IsPrivateBrowsing();
2560 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2561 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)
2562 ("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)
2563 " 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)
2564 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)
;
2565 return false;
2566 }
2567
2568 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)
2569 ("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)
2570 " 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)
2571 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)
;
2572
2573 if (!StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2574 !StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly()) {
2575 // If neither of the 'regular' RFP prefs are set, then one (or both)
2576 // of the PBM-Only prefs are set (or we would have failed the
2577 // Positive return check.) Therefore, if we are not in PBM, return false
2578 if (!aOriginAttributes.IsPrivateBrowsing()) {
2579 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)
2580 ("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)
2581 " 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)
;
2582 return false;
2583 }
2584 }
2585
2586 // Exclude internal schemes and web extensions
2587 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
2588 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)
2589 ("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)
2590 " 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)
;
2591 return false;
2592 }
2593
2594 bool isExemptDomain = false;
2595 nsAutoCString list;
2596 Preferences::GetCString(kExemptedDomainsPrefName, list);
2597 ToLowerCase(list);
2598 isExemptDomain = IsURIInList(aURI, list);
2599
2600 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2601 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2602 nsAutoCString url;
2603 aURI->GetHost(url);
2604 LogDomainAndPrefList("URI", kExemptedDomainsPrefName, url, isExemptDomain);
2605 }
2606
2607 if (isExemptDomain) {
2608 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
2609 }
2610
2611 return !isExemptDomain;
2612}
2613
2614/* static */
2615bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2616 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
2617 if (!aPrincipal) {
2618 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)
2619 ("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)
2620 "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)
;
2621 return ShouldResistFingerprinting("Null object", aTarget);
2622 }
2623
2624 auto originAttributes =
2625 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
2626 // With this check, we can ensure that the prefs and target say yes, so only
2627 // an exemption would cause us to return false.
2628 bool isPBM = originAttributes.IsPrivateBrowsing();
2629 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2630 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)
2631 ("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)
2632 "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)
2633 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)
;
2634 return false;
2635 }
2636
2637 if (aPrincipal->IsSystemPrincipal()) {
2638 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)
2639 ("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)
2640 "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)
;
2641 return false;
2642 }
2643
2644 // Exclude internal schemes and web extensions
2645 if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) {
2646 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)
2647 ("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)
2648 " 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)
;
2649 return false;
2650 }
2651
2652 // Web extension principals are also excluded
2653 if (BasePrincipal::Cast(aPrincipal)->AddonPolicy()) {
2654 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)
2655 ("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)
2656 " 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)
;
2657 return false;
2658 }
2659
2660 bool isExemptDomain = false;
2661 aPrincipal->IsURIInPrefList(kExemptedDomainsPrefName, &isExemptDomain);
2662
2663 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2664 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2665 nsAutoCString origin;
2666 aPrincipal->GetOrigin(origin);
2667 LogDomainAndPrefList("URI", kExemptedDomainsPrefName, origin,
2668 isExemptDomain);
2669 }
2670
2671 if (isExemptDomain) {
2672 isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes);
2673 }
2674
2675 return !isExemptDomain;
2676}
2677
2678// --------------------------------------------------------------------
2679
2680/* static */
2681void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
2682 int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
2683 int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
2684 bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
2685 int32_t* aOutputHeight) {
2686 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"
, 2686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth"
")"); do { *((volatile int*)__null) = 2686; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2687 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"
, 2687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputHeight"
")"); do { *((volatile int*)__null) = 2687; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2688
2689 int32_t availContentWidth = 0;
2690 int32_t availContentHeight = 0;
2691
2692 availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(),
2693 aScreenWidth - aChromeWidth);
2694#ifdef MOZ_WIDGET_GTK1
2695 // In the GTK window, it will not report outside system decorations
2696 // when we get available window size, see Bug 581863. So, we leave a
2697 // 40 pixels space for them when calculating the available content
2698 // height. It is not necessary for the width since the content width
2699 // is usually pretty much the same as the chrome width.
2700 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
2701 (-40 + aScreenHeight) - aChromeHeight);
2702#else
2703 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
2704 aScreenHeight - aChromeHeight);
2705#endif
2706
2707 // Ideally, we'd like to round window size to 1000x1000, but the
2708 // screen space could be too small to accommodate this size in some
2709 // cases. If it happens, we would round the window size to the nearest
2710 // 200x100.
2711 availContentWidth = availContentWidth - (availContentWidth % 200);
2712 availContentHeight = availContentHeight - (availContentHeight % 100);
2713
2714 // If aIsOuter is true, we are setting the outer window. So we
2715 // have to consider the chrome UI.
2716 int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
2717 int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
2718 int32_t resultWidth = 0, resultHeight = 0;
2719
2720 // if the original size is greater than the maximum available size, we set
2721 // it to the maximum size. And if the original value is less than the
2722 // minimum rounded size, we set it to the minimum 200x100.
2723 if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
2724 resultWidth = availContentWidth + chromeOffsetWidth;
2725 } else if (aInputWidth < (200 + chromeOffsetWidth)) {
2726 resultWidth = 200 + chromeOffsetWidth;
2727 } else {
2728 // Otherwise, we round the window to the nearest upper rounded 200x100.
2729 resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 +
2730 chromeOffsetWidth;
2731 }
2732
2733 if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
2734 resultHeight = availContentHeight + chromeOffsetHeight;
2735 } else if (aInputHeight < (100 + chromeOffsetHeight)) {
2736 resultHeight = 100 + chromeOffsetHeight;
2737 } else {
2738 resultHeight =
2739 NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 +
2740 chromeOffsetHeight;
2741 }
2742
2743 *aOutputWidth = resultWidth;
2744 *aOutputHeight = resultHeight;
2745}
2746
2747bool nsContentUtils::ThreadsafeIsCallerChrome() {
2748 return NS_IsMainThread() ? IsCallerChrome()
2749 : IsCurrentThreadRunningChromeWorker();
2750}
2751
2752bool nsContentUtils::IsCallerUAWidget() {
2753 JSContext* cx = GetCurrentJSContext();
2754 if (!cx) {
2755 return false;
2756 }
2757
2758 JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
2759 if (!realm) {
2760 return false;
2761 }
2762
2763 return xpc::IsUAWidgetScope(realm);
2764}
2765
2766bool nsContentUtils::IsSystemCaller(JSContext* aCx) {
2767 // Note that SubjectPrincipal() assumes we are in a compartment here.
2768 return SubjectPrincipal(aCx) == sSystemPrincipal;
2769}
2770
2771bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
2772 CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
2773 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"
, 2773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ccjscx->Context() == aCx"
")"); do { *((volatile int*)__null) = 2773; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2774
2775 return ccjscx->IsSystemCaller();
2776}
2777
2778// static
2779bool nsContentUtils::LookupBindingMember(
2780 JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
2781 JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
2782 return true;
2783}
2784
2785nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode(
2786 nsINode* aChild) {
2787 if (aChild->IsDocument()) {
2788 for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc;
2789 bc = bc->GetParent()) {
2790 if (bc->GetEmbedderElement()) {
2791 return bc->GetEmbedderElement();
2792 }
2793 }
2794 return nullptr;
2795 }
2796
2797 nsINode* parent = aChild->GetParentNode();
2798 if (parent && parent->IsContent() && aChild->IsContent()) {
2799 parent = aChild->AsContent()->GetFlattenedTreeParent();
2800 }
2801
2802 return parent;
2803}
2804
2805bool nsContentUtils::ContentIsHostIncludingDescendantOf(
2806 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2807 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"
, 2807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2807; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2808 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"
, 2808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2808; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2809
2810 do {
2811 if (aPossibleDescendant == aPossibleAncestor) return true;
2812 if (aPossibleDescendant->IsDocumentFragment()) {
2813 aPossibleDescendant =
2814 aPossibleDescendant->AsDocumentFragment()->GetHost();
2815 } else {
2816 aPossibleDescendant = aPossibleDescendant->GetParentNode();
2817 }
2818 } while (aPossibleDescendant);
2819
2820 return false;
2821}
2822
2823// static
2824bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
2825 nsINode* aPossibleAncestor) {
2826 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"
, 2826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2826; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2827 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"
, 2827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2827; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2828
2829 do {
2830 if (aPossibleDescendant == aPossibleAncestor) {
2831 return true;
2832 }
2833
2834 aPossibleDescendant =
2835 GetNearestInProcessCrossDocParentNode(aPossibleDescendant);
2836 } while (aPossibleDescendant);
2837
2838 return false;
2839}
2840
2841// static
2842bool nsContentUtils::ContentIsFlattenedTreeDescendantOf(
2843 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2844 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"
, 2844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2844; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2845 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"
, 2845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2845; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2846
2847 do {
2848 if (aPossibleDescendant == aPossibleAncestor) {
2849 return true;
2850 }
2851 aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
2852 } while (aPossibleDescendant);
2853
2854 return false;
2855}
2856
2857// static
2858bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(
2859 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
2860 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"
, 2860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { *((volatile
int*)__null) = 2860; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2861 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"
, 2861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { *((volatile
int*)__null) = 2861; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2862
2863 do {
2864 if (aPossibleDescendant == aPossibleAncestor) {
2865 return true;
2866 }
2867 aPossibleDescendant =
2868 aPossibleDescendant->GetFlattenedTreeParentNodeForStyle();
2869 } while (aPossibleDescendant);
2870
2871 return false;
2872}
2873
2874// static
2875nsINode* nsContentUtils::Retarget(nsINode* aTargetA, nsINode* aTargetB) {
2876 while (true && aTargetA) {
2877 // If A's root is not a shadow root...
2878 nsINode* root = aTargetA->SubtreeRoot();
2879 if (!root->IsShadowRoot()) {
2880 // ...then return A.
2881 return aTargetA;
2882 }
2883
2884 // or A's root is a shadow-including inclusive ancestor of B...
2885 if (aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
2886 // ...then return A.
2887 return aTargetA;
2888 }
2889
2890 aTargetA = ShadowRoot::FromNode(root)->GetHost();
2891 }
2892
2893 return nullptr;
2894}
2895
2896// static
2897Element* nsContentUtils::GetAnElementForTiming(Element* aTarget,
2898 const Document* aDocument,
2899 nsIGlobalObject* aGlobal) {
2900 if (!aTarget->IsInComposedDoc()) {
2901 return nullptr;
2902 }
2903
2904 if (!aDocument) {
2905 nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal);
2906 if (!inner) {
2907 return nullptr;
2908 }
2909 aDocument = inner->GetExtantDoc();
2910 }
2911
2912 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"
, 2912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 2912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2913
2914 if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument ||
2915 !aDocument->IsCurrentActiveDocument()) {
2916 return nullptr;
2917 }
2918
2919 return aTarget;
2920}
2921
2922// static
2923nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode,
2924 nsTArray<nsINode*>& aArray) {
2925 while (aNode) {
2926 aArray.AppendElement(aNode);
2927 aNode = aNode->GetParentNode();
2928 }
2929 return NS_OK;
2930}
2931
2932// static
2933template <typename GetParentFunc>
2934nsresult static GetInclusiveAncestorsAndOffsetsHelper(
2935 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2936 nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc) {
2937 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"
, 2937); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2938
2939 if (!aNode->IsContent()) {
2940 return NS_ERROR_FAILURE;
2941 }
2942 nsIContent* content = aNode->AsContent();
2943
2944 if (!aAncestorNodes.IsEmpty()) {
2945 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"
, 2945)
;
2946 aAncestorNodes.Clear();
2947 }
2948
2949 if (!aAncestorOffsets.IsEmpty()) {
2950 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"
, 2950)
;
2951 aAncestorOffsets.Clear();
2952 }
2953
2954 // insert the node itself
2955 aAncestorNodes.AppendElement(content);
2956 aAncestorOffsets.AppendElement(Some(aOffset));
2957
2958 // insert all the ancestors
2959 nsIContent* child = content;
2960 nsIContent* parent = aGetParentFunc(child);
2961 while (parent) {
2962 aAncestorNodes.AppendElement(parent->AsContent());
2963 aAncestorOffsets.AppendElement(parent->ComputeIndexOf(child));
2964 child = parent;
2965 parent = aGetParentFunc(child);
2966 }
2967
2968 return NS_OK;
2969}
2970
2971nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
2972 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2973 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
2974 return GetInclusiveAncestorsAndOffsetsHelper(
2975 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
2976 [](nsIContent* aContent) { return aContent->GetParent(); });
2977}
2978
2979nsresult nsContentUtils::GetShadowIncludingAncestorsAndOffsets(
2980 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
2981 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
2982 return GetInclusiveAncestorsAndOffsetsHelper(
2983 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
2984 [](nsIContent* aContent) -> nsIContent* {
2985 return nsIContent::FromNodeOrNull(
2986 aContent->GetParentOrShadowHostNode());
2987 });
2988}
2989
2990template <typename Node, typename GetParentFunc>
2991static Node* GetCommonAncestorInternal(Node* aNode1, Node* aNode2,
2992 GetParentFunc aGetParentFunc) {
2993 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"
, 2993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1 != aNode2"
")"); do { *((volatile int*)__null) = 2993; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2994
2995 // Build the chain of parents
2996 AutoTArray<Node*, 30> parents1, parents2;
2997 do {
2998 parents1.AppendElement(aNode1);
2999 aNode1 = aGetParentFunc(aNode1);
3000 } while (aNode1);
3001 do {
3002 parents2.AppendElement(aNode2);
3003 aNode2 = aGetParentFunc(aNode2);
3004 } while (aNode2);
3005
3006 // Find where the parent chain differs
3007 uint32_t pos1 = parents1.Length();
3008 uint32_t pos2 = parents2.Length();
3009 Node** data1 = parents1.Elements();
3010 Node** data2 = parents2.Elements();
3011 Node* parent = nullptr;
3012 uint32_t len;
3013 for (len = std::min(pos1, pos2); len > 0; --len) {
3014 Node* child1 = data1[--pos1];
3015 Node* child2 = data2[--pos2];
3016 if (child1 != child2) {
3017 break;
3018 }
3019 parent = child1;
3020 }
3021
3022 return parent;
3023}
3024
3025/* static */
3026nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
3027 nsINode* aNode2) {
3028 return GetCommonAncestorInternal(
3029 aNode1, aNode2, [](nsINode* aNode) { return aNode->GetParentNode(); });
3030}
3031
3032/* static */
3033nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3034 nsINode* aNode1, nsINode* aNode2) {
3035 if (aNode1 == aNode2) {
3036 return aNode1;
3037 }
3038
3039 return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
3040 return aNode->GetParentOrShadowHostNode();
3041 });
3042}
3043
3044/* static */
3045nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3046 nsIContent* aContent1, nsIContent* aContent2) {
3047 return GetCommonAncestorInternal(
3048 aContent1, aContent2,
3049 [](nsIContent* aContent) { return aContent->GetFlattenedTreeParent(); });
3050}
3051
3052/* static */
3053nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3054 nsIContent* aContent1, nsIContent* aContent2) {
3055 if (aContent1 == aContent2) {
3056 return aContent1;
3057 }
3058
3059 return GetCommonAncestorInternal(
3060 aContent1, aContent2, [](nsIContent* aContent) {
3061 return aContent->GetFlattenedTreeParentNodeForSelection();
3062 });
3063}
3064
3065/* static */
3066Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3067 Element* aElement1, Element* aElement2) {
3068 return GetCommonAncestorInternal(aElement1, aElement2, [](Element* aElement) {
3069 return aElement->GetFlattenedTreeParentElementForStyle();
3070 });
3071}
3072
3073/* static */
3074bool nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
3075 Maybe<uint32_t>* aNode1Index,
3076 Maybe<uint32_t>* aNode2Index) {
3077 // Note, CompareDocumentPosition takes the latter params in different order.
3078 return (aNode2->CompareDocumentPosition(*aNode1, aNode2Index, aNode1Index) &
3079 (Node_Binding::DOCUMENT_POSITION_PRECEDING |
3080 Node_Binding::DOCUMENT_POSITION_DISCONNECTED)) ==
3081 Node_Binding::DOCUMENT_POSITION_PRECEDING;
3082}
3083
3084/* static */
3085Maybe<int32_t> nsContentUtils::ComparePoints(const nsINode* aParent1,
3086 uint32_t aOffset1,
3087 const nsINode* aParent2,
3088 uint32_t aOffset2,
3089 NodeIndexCache* aIndexCache) {
3090 bool disconnected{false};
3091
3092 const int32_t order = ComparePoints_Deprecated(
3093 aParent1, aOffset1, aParent2, aOffset2, &disconnected, aIndexCache);
3094 if (disconnected) {
3095 return Nothing();
3096 }
3097
3098 return Some(order);
3099}
3100
3101/* static */
3102int32_t nsContentUtils::ComparePoints_Deprecated(
3103 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
3104 uint32_t aOffset2, bool* aDisconnected, NodeIndexCache* aIndexCache) {
3105 if (aParent1 == aParent2) {
3106 return aOffset1 < aOffset2 ? -1 : aOffset1 > aOffset2 ? 1 : 0;
3107 }
3108
3109 AutoTArray<const nsINode*, 32> parents1, parents2;
3110 const nsINode* node1 = aParent1;
3111 const nsINode* node2 = aParent2;
3112 do {
3113 parents1.AppendElement(node1);
3114 node1 = node1->GetParentOrShadowHostNode();
3115 } while (node1);
3116 do {
3117 parents2.AppendElement(node2);
3118 node2 = node2->GetParentOrShadowHostNode();
3119 } while (node2);
3120
3121 uint32_t pos1 = parents1.Length() - 1;
3122 uint32_t pos2 = parents2.Length() - 1;
3123
3124 bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
3125 if (aDisconnected) {
3126 *aDisconnected = disconnected;
3127 }
3128 if (disconnected) {
3129 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"
, 3129); MOZ_PretendNoReturn(); } } while (0)
;
3130 return 1;
3131 }
3132
3133 // Find where the parent chains differ
3134 const nsINode* parent = parents1.ElementAt(pos1);
3135 uint32_t len;
3136 for (len = std::min(pos1, pos2); len > 0; --len) {
3137 const nsINode* child1 = parents1.ElementAt(--pos1);
3138 const nsINode* child2 = parents2.ElementAt(--pos2);
3139 if (child1 != child2) {
3140 if (MOZ_UNLIKELY(child1->IsShadowRoot())(__builtin_expect(!!(child1->IsShadowRoot()), 0))) {
3141 // Shadow roots come before light DOM per
3142 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3143 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"
, 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { *((volatile int*)__null
) = 3143; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3144 return -1;
3145 }
3146 if (MOZ_UNLIKELY(child2->IsShadowRoot())(__builtin_expect(!!(child2->IsShadowRoot()), 0))) {
3147 return 1;
3148 }
3149 Maybe<uint32_t> child1Index;
3150 Maybe<uint32_t> child2Index;
3151 if (aIndexCache) {
3152 aIndexCache->ComputeIndicesOf(parent, child1, child2, child1Index,
3153 child2Index);
3154 } else {
3155 child1Index = parent->ComputeIndexOf(child1);
3156 child2Index = parent->ComputeIndexOf(child2);
3157 }
3158 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3159 return *child1Index < *child2Index ? -1 : 1;
3160 }
3161 // XXX Keep the odd traditional behavior for now.
3162 return child1Index.isNothing() && child2Index.isSome() ? -1 : 1;
3163 }
3164 parent = child1;
3165 }
3166
3167 // The parent chains never differed, so one of the nodes is an ancestor of
3168 // the other
3169
3170 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"
, 3171); MOZ_PretendNoReturn(); } } while (0)
3171 "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"
, 3171); MOZ_PretendNoReturn(); } } while (0)
;
3172
3173 if (!pos1) {
3174 const nsINode* child2 = parents2.ElementAt(--pos2);
3175 const Maybe<uint32_t> child2Index =
3176 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child2)
3177 : parent->ComputeIndexOf(child2);
3178 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"
, 3178)), 0))
) {
3179 return 1;
3180 }
3181 return aOffset1 <= *child2Index ? -1 : 1;
3182 }
3183
3184 const nsINode* child1 = parents1.ElementAt(--pos1);
3185 const Maybe<uint32_t> child1Index =
3186 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child1)
3187 : parent->ComputeIndexOf(child1);
3188 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"
, 3188)), 0))
) {
3189 return -1;
3190 }
3191 return *child1Index < aOffset2 ? -1 : 1;
3192}
3193
3194/* static */
3195BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
3196 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
3197 return GetCommonAncestorInternal(
3198 aBrowserParent1, aBrowserParent2, [](BrowserParent* aBrowserParent) {
3199 return aBrowserParent->GetBrowserBridgeParent()
3200 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
3201 : nullptr;
3202 });
3203}
3204
3205/* static */
3206Element* nsContentUtils::GetTargetElement(Document* aDocument,
3207 const nsAString& aAnchorName) {
3208 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"
, 3208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 3208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3209
3210 if (aAnchorName.IsEmpty()) {
3211 return nullptr;
3212 }
3213 // 1. If there is an element in the document tree that has an ID equal to
3214 // fragment, then return the first such element in tree order.
3215 if (Element* el = aDocument->GetElementById(aAnchorName)) {
3216 return el;
3217 }
3218
3219 // 2. If there is an a element in the document tree that has a name
3220 // attribute whose value is equal to fragment, then return the first such
3221 // element in tree order.
3222 //
3223 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
3224 if (aDocument->IsHTMLDocument()) {
3225 nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName);
3226 // Loop through the named nodes looking for the first anchor
3227 uint32_t length = list->Length();
3228 for (uint32_t i = 0; i < length; i++) {
3229 nsIContent* node = list->Item(i);
3230 if (node->IsHTMLElement(nsGkAtoms::a)) {
3231 return node->AsElement();
3232 }
3233 }
3234 } else {
3235 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
3236 // Get the list of anchor elements
3237 nsCOMPtr<nsINodeList> list =
3238 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
3239 // Loop through the anchors looking for the first one with the given name.
3240 for (uint32_t i = 0; true; i++) {
3241 nsIContent* node = list->Item(i);
3242 if (!node) { // End of list
3243 break;
3244 }
3245
3246 // Compare the name attribute
3247 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
3248 aAnchorName, eCaseMatters)) {
3249 return node->AsElement();
3250 }
3251 }
3252 }
3253
3254 // 3. Return null.
3255 return nullptr;
3256}
3257
3258/* static */
3259template <typename FPT, typename FRT, typename SPT, typename SRT>
3260Maybe<int32_t> nsContentUtils::ComparePoints(
3261 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3262 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary) {
3263 if (!aFirstBoundary.IsSet() || !aSecondBoundary.IsSet()) {
3264 return Nothing{};
3265 }
3266
3267 bool disconnected{false};
3268 const int32_t order =
3269 ComparePoints_Deprecated(aFirstBoundary, aSecondBoundary, &disconnected);
3270
3271 if (disconnected) {
3272 return Nothing{};
3273 }
3274
3275 return Some(order);
3276}
3277
3278/* static */
3279template <typename FPT, typename FRT, typename SPT, typename SRT>
3280int32_t nsContentUtils::ComparePoints_Deprecated(
3281 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3282 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary, bool* aDisconnected) {
3283 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"
, 3283)
||
3284 NS_WARN_IF(!aSecondBoundary.IsSet())NS_warn_if_impl(!aSecondBoundary.IsSet(), "!aSecondBoundary.IsSet()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3284)
) {
3285 return -1;
3286 }
3287 // XXX Re-implement this without calling `Offset()` as far as possible,
3288 // and the other overload should be an alias of this.
3289 return ComparePoints_Deprecated(
3290 aFirstBoundary.Container(),
3291 *aFirstBoundary.Offset(
3292 RangeBoundaryBase<FPT, FRT>::OffsetFilter::kValidOrInvalidOffsets),
3293 aSecondBoundary.Container(),
3294 *aSecondBoundary.Offset(
3295 RangeBoundaryBase<SPT, SRT>::OffsetFilter::kValidOrInvalidOffsets),
3296 aDisconnected);
3297}
3298
3299inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
3300 char16_t ch;
3301 while ((ch = *aSet)) {
3302 if (aChar == char16_t(ch)) {
3303 return true;
3304 }
3305 ++aSet;
3306 }
3307 return false;
3308}
3309
3310/**
3311 * This method strips leading/trailing chars, in given set, from string.
3312 */
3313
3314// static
3315const nsDependentSubstring nsContentUtils::TrimCharsInSet(
3316 const char* aSet, const nsAString& aValue) {
3317 nsAString::const_iterator valueCurrent, valueEnd;
3318
3319 aValue.BeginReading(valueCurrent);
3320 aValue.EndReading(valueEnd);
3321
3322 // Skip characters in the beginning
3323 while (valueCurrent != valueEnd) {
3324 if (!IsCharInSet(aSet, *valueCurrent)) {
3325 break;
3326 }
3327 ++valueCurrent;
3328 }
3329
3330 if (valueCurrent != valueEnd) {
3331 for (;;) {
3332 --valueEnd;
3333 if (!IsCharInSet(aSet, *valueEnd)) {
3334 break;
3335 }
3336 }
3337 ++valueEnd; // Step beyond the last character we want in the value.
3338 }
3339
3340 // valueEnd should point to the char after the last to copy
3341 return Substring(valueCurrent, valueEnd);
3342}
3343
3344/**
3345 * This method strips leading and trailing whitespace from a string.
3346 */
3347
3348// static
3349template <bool IsWhitespace(char16_t)>
3350const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
3351 bool aTrimTrailing) {
3352 nsAString::const_iterator start, end;
3353
3354 aStr.BeginReading(start);
3355 aStr.EndReading(end);
3356
3357 // Skip whitespace characters in the beginning
3358 while (start != end && IsWhitespace(*start)) {
3359 ++start;
3360 }
3361
3362 if (aTrimTrailing) {
3363 // Skip whitespace characters in the end.
3364 while (end != start) {
3365 --end;
3366
3367 if (!IsWhitespace(*end)) {
3368 // Step back to the last non-whitespace character.
3369 ++end;
3370
3371 break;
3372 }
3373 }
3374 }
3375
3376 // Return a substring for the string w/o leading and/or trailing
3377 // whitespace
3378
3379 return Substring(start, end);
3380}
3381
3382// Declaring the templates we are going to use avoid linking issues without
3383// inlining the method. Considering there is not so much spaces checking
3384// methods we can consider this to be better than inlining.
3385template const nsDependentSubstring
3386nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
3387template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3388 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
3389template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3390 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
3391
3392static inline void KeyAppendSep(nsACString& aKey) {
3393 if (!aKey.IsEmpty()) {
3394 aKey.Append('>');
3395 }
3396}
3397
3398static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
3399 KeyAppendSep(aKey);
3400
3401 // Could escape separator here if collisions happen. > is not a legal char
3402 // for a name or type attribute, so we should be safe avoiding that extra
3403 // work.
3404
3405 AppendUTF16toUTF8(aString, aKey);
3406}
3407
3408static inline void KeyAppendString(const nsACString& aString,
3409 nsACString& aKey) {
3410 KeyAppendSep(aKey);
3411
3412 // Could escape separator here if collisions happen. > is not a legal char
3413 // for a name or type attribute, so we should be safe avoiding that extra
3414 // work.
3415
3416 aKey.Append(aString);
3417}
3418
3419static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
3420 KeyAppendSep(aKey);
3421
3422 aKey.AppendInt(aInt);
3423}
3424
3425static inline bool IsAutocompleteOff(const nsIContent* aContent) {
3426 return aContent->IsElement() &&
3427 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
3428 nsGkAtoms::autocomplete, u"off"_ns,
3429 eIgnoreCase);
3430}
3431
3432/*static*/
3433void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
3434 nsACString& aKey) {
3435 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"
, 3435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 3435; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3436
3437 aKey.Truncate();
3438
3439 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
3440
3441 // Don't capture state for anonymous content
3442 if (aContent->IsInNativeAnonymousSubtree()) {
3443 return;
3444 }
3445
3446 if (IsAutocompleteOff(aContent)) {
3447 return;
3448 }
3449
3450 RefPtr<Document> doc = aContent->GetUncomposedDoc();
3451
3452 KeyAppendInt(partID, aKey); // first append a partID
3453 bool generatedUniqueKey = false;
3454
3455 if (doc && doc->IsHTMLOrXHTML()) {
3456 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
3457
3458 // If we have a form control and can calculate form information, use that
3459 // as the key - it is more reliable than just recording position in the
3460 // DOM.
3461 // XXXbz Is it, really? We have bugs on this, I think...
3462 // Important to have a unique key, and tag/type/name may not be.
3463 //
3464 // The format of the key depends on whether the control has a form,
3465 // and whether the element was parser inserted:
3466 //
3467 // [Has Form, Parser Inserted]:
3468 // fp>type>FormNum>IndOfControlInForm>FormName>name
3469 //
3470 // [No Form, Parser Inserted]:
3471 // dp>type>ControlNum>name
3472 //
3473 // [Has Form, Not Parser Inserted]:
3474 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
3475 //
3476 // [No Form, Not Parser Inserted]:
3477 // dn>type>IndOfControlInDoc>name
3478 //
3479 // XXX We don't need to use index if name is there
3480 // XXXbz We don't? Why not? I don't follow.
3481 //
3482 if (const auto* control = nsIFormControl::FromNode(aContent)) {
3483 // Get the control number if this was a parser inserted element from the
3484 // network.
3485 int32_t controlNumber =
3486 control->GetParserInsertedControlNumberForStateKey();
3487 bool parserInserted = controlNumber != -1;
3488
3489 RefPtr<nsContentList> htmlForms;
3490 RefPtr<nsContentList> htmlFormControls;
3491 if (!parserInserted) {
3492 // Getting these lists is expensive, as we need to keep them up to date
3493 // as the document loads, so we avoid it if we don't need them.
3494 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
3495 getter_AddRefs(htmlFormControls));
3496 }
3497
3498 // Append the control type
3499 KeyAppendInt(int32_t(control->ControlType()), aKey);
3500
3501 // If in a form, add form name / index of form / index in form
3502 HTMLFormElement* formElement = control->GetForm();
3503 if (formElement) {
3504 if (IsAutocompleteOff(formElement)) {
3505 aKey.Truncate();
3506 return;
3507 }
3508
3509 // Append the form number, if this is a parser inserted control, or
3510 // the index of the form in the document otherwise.
3511 bool appendedForm = false;
3512 if (parserInserted) {
3513 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"
, 3515); 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) = 3515; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3514 "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"
, 3515); 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) = 3515; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3515 "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"
, 3515); 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) = 3515; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3516 KeyAppendString("fp"_ns, aKey);
3517 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
3518 appendedForm = true;
3519 } else {
3520 KeyAppendString("fn"_ns, aKey);
3521 int32_t index = htmlForms->IndexOf(formElement, false);
3522 if (index <= -1) {
3523 //
3524 // XXX HACK this uses some state that was dumped into the document
3525 // specifically to fix bug 138892. What we are trying to do is
3526 // *guess* which form this control's state is found in, with the
3527 // highly likely guess that the highest form parsed so far is the
3528 // one. This code should not be on trunk, only branch.
3529 //
3530 index = htmlDoc->GetNumFormsSynchronous() - 1;
3531 }
3532 if (index > -1) {
3533 KeyAppendInt(index, aKey);
3534 appendedForm = true;
3535 }
3536 }
3537
3538 if (appendedForm) {
3539 // Append the index of the control in the form
3540 int32_t index = formElement->IndexOfContent(aContent);
3541
3542 if (index > -1) {
3543 KeyAppendInt(index, aKey);
3544 generatedUniqueKey = true;
3545 }
3546 }
3547
3548 // Append the form name
3549 nsAutoString formName;
3550 formElement->GetAttr(nsGkAtoms::name, formName);
3551 KeyAppendString(formName, aKey);
3552 } else {
3553 // Not in a form. Append the control number, if this is a parser
3554 // inserted control, or the index of the control in the document
3555 // otherwise.
3556 if (parserInserted) {
3557 KeyAppendString("dp"_ns, aKey);
3558 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
3559 aKey);
3560 generatedUniqueKey = true;
3561 } else {
3562 KeyAppendString("dn"_ns, aKey);
3563 int32_t index = htmlFormControls->IndexOf(aContent, true);
3564 if (index > -1) {
3565 KeyAppendInt(index, aKey);
3566 generatedUniqueKey = true;
3567 }
3568 }
3569
3570 // Append the control name
3571 nsAutoString name;
3572 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
3573 KeyAppendString(name, aKey);
3574 }
3575 }
3576 }
3577
3578 if (!generatedUniqueKey) {
3579 // Either we didn't have a form control or we aren't in an HTML document so
3580 // we can't figure out form info. Append the tag name if it's an element
3581 // to avoid restoring state for one type of element on another type.
3582 if (aContent->IsElement()) {
3583 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
3584 aKey);
3585 } else {
3586 // Append a character that is not "d" or "f" to disambiguate from
3587 // the case when we were a form control in an HTML document.
3588 KeyAppendString("o"_ns, aKey);
3589 }
3590
3591 // Now start at aContent and append the indices of it and all its ancestors
3592 // in their containers. That should at least pin down its position in the
3593 // DOM...
3594 nsINode* parent = aContent->GetParentNode();
3595 nsINode* content = aContent;
3596 while (parent) {
3597 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
3598 content = parent;
3599 parent = content->GetParentNode();
3600 }
3601 }
3602}
3603
3604// static
3605nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
3606 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"
, 3606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3607
3608 // As opposed to SubjectPrincipal(), we do in fact assume that
3609 // we're in a realm here; anyone who calls this function in
3610 // situations where that's not the case is doing it wrong.
3611 JS::Realm* realm = js::GetContextRealm(aCx);
3612 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"
, 3612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { *((volatile int*)__null) = 3612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3613
3614 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3615 return nsJSPrincipals::get(principals);
3616}
3617
3618// static
3619nsIPrincipal* nsContentUtils::SubjectPrincipal() {
3620 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"
, 3620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 3620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3621 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"
, 3621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3622 JSContext* cx = GetCurrentJSContext();
3623 if (!cx) {
3624 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"
, 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3625 "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"
, 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3626 "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"
, 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
3627 }
3628
3629 JS::Realm* realm = js::GetContextRealm(cx);
3630
3631 // When an AutoJSAPI is instantiated, we are in a null realm until the
3632 // first JSAutoRealm, which is kind of a purgatory as far as permissions
3633 // go. It would be nice to just hard-abort if somebody does a security check
3634 // in this purgatory zone, but that would be too fragile, since it could be
3635 // triggered by random IsCallerChrome() checks 20-levels deep.
3636 //
3637 // So we want to return _something_ here - and definitely not the System
3638 // Principal, since that would make an AutoJSAPI a very dangerous thing to
3639 // instantiate.
3640 //
3641 // The natural thing to return is a null principal. Ideally, we'd return a
3642 // different null principal each time, to avoid any unexpected interactions
3643 // when the principal accidentally gets inherited somewhere. But
3644 // SubjectPrincipal doesn't return strong references, so there's no way to
3645 // sanely manage the lifetime of multiple null principals.
3646 //
3647 // So we use a singleton null principal. To avoid it being accidentally
3648 // inherited and becoming a "real" subject or object principal, we do a
3649 // release-mode assert during realm creation against using this principal on
3650 // an actual global.
3651 if (!realm) {
3652 return sNullSubjectPrincipal;
3653 }
3654
3655 return SubjectPrincipal(cx);
3656}
3657
3658// static
3659nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
3660#ifdef DEBUG1
3661 JS::AssertObjectBelongsToCurrentThread(aObj);
3662#endif
3663
3664 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"
, 3664); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { *((volatile int*)__null) = 3664; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3665
3666 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
3667 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3668 return nsJSPrincipals::get(principals);
3669}
3670
3671// static
3672nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
3673 const nsAString& aSpec,
3674 Document* aDocument,
3675 nsIURI* aBaseURI) {
3676 if (aDocument) {
3677 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
3678 aBaseURI);
3679 }
3680 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
3681}
3682
3683// static
3684bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
3685 const uint32_t len = aAtom->GetLength();
3686 if (!len) {
3687 return false;
3688 }
3689 const char16_t* name = aAtom->GetUTF16String();
3690 uint32_t i = 0;
3691 while (i < len) {
3692 if (name[i] == aChar) {
3693 return true;
3694 }
3695 i++;
3696 }
3697 return false;
3698}
3699
3700// static
3701bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
3702 // A valid custom element name is a sequence of characters name which
3703 // must match the PotentialCustomElementName production:
3704 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
3705 const char16_t* name = aName->GetUTF16String();
3706 uint32_t len = aName->GetLength();
3707 bool hasDash = false;
3708
3709 if (!len || name[0] < 'a' || name[0] > 'z') {
3710 return false;
3711 }
3712
3713 uint32_t i = 1;
3714 while (i < len) {
3715 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))
) {
3716 // Merged two 16-bit surrogate pairs into code point.
3717 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))
;
3718
3719 if (code < 0x10000 || code > 0xEFFFF) {
3720 return false;
3721 }
3722
3723 i += 2;
3724 } else {
3725 if (name[i] == '-') {
3726 hasDash = true;
3727 }
3728
3729 if (name[i] != '-' && name[i] != '.' && name[i] != '_' &&
3730 name[i] != 0xB7 && (name[i] < '0' || name[i] > '9') &&
3731 (name[i] < 'a' || name[i] > 'z') &&
3732 (name[i] < 0xC0 || name[i] > 0xD6) &&
3733 (name[i] < 0xF8 || name[i] > 0x37D) &&
3734 (name[i] < 0x37F || name[i] > 0x1FFF) &&
3735 (name[i] < 0x200C || name[i] > 0x200D) &&
3736 (name[i] < 0x203F || name[i] > 0x2040) &&
3737 (name[i] < 0x2070 || name[i] > 0x218F) &&
3738 (name[i] < 0x2C00 || name[i] > 0x2FEF) &&
3739 (name[i] < 0x3001 || name[i] > 0xD7FF) &&
3740 (name[i] < 0xF900 || name[i] > 0xFDCF) &&
3741 (name[i] < 0xFDF0 || name[i] > 0xFFFD)) {
3742 return false;
3743 }
3744
3745 i++;
3746 }
3747 }
3748
3749 return hasDash;
3750}
3751
3752// static
3753bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
3754 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
3755 if (aNameSpaceID == kNameSpaceID_XUL8) {
3756 return true;
3757 }
3758
3759 bool hasDash = IsNameWithDash(aName);
3760 if (!hasDash) {
3761 return false;
3762 }
3763
3764 // The custom element name must not be one of the following values:
3765 // annotation-xml
3766 // color-profile
3767 // font-face
3768 // font-face-src
3769 // font-face-uri
3770 // font-face-format
3771 // font-face-name
3772 // missing-glyph
3773 return aName != nsGkAtoms::annotation_xml_ &&
3774 aName != nsGkAtoms::colorProfile && aName != nsGkAtoms::font_face &&
3775 aName != nsGkAtoms::font_face_src &&
3776 aName != nsGkAtoms::font_face_uri &&
3777 aName != nsGkAtoms::font_face_format &&
3778 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
3779}
3780
3781// static
3782nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
3783 bool aNamespaceAware,
3784 const char16_t** aColon) {
3785 const char* colon = nullptr;
3786 const char16_t* begin = aQualifiedName.BeginReading();
3787 const char16_t* end = aQualifiedName.EndReading();
3788
3789 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
3790 reinterpret_cast<const char*>(end),
3791 aNamespaceAware, &colon);
3792
3793 if (!result) {
3794 if (aColon) {
3795 *aColon = reinterpret_cast<const char16_t*>(colon);
3796 }
3797
3798 return NS_OK;
3799 }
3800
3801 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
3802}
3803
3804// static
3805nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
3806 const nsString& aQName, int32_t* aNamespace,
3807 nsAtom** aLocalName) {
3808 const char16_t* colon;
3809 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
3810 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"
, 3810); return rv; } } while (false)
;
3811
3812 if (colon) {
3813 const char16_t* end;
3814 aQName.EndReading(end);
3815 nsAutoString nameSpace;
3816 rv = aNamespaceResolver->LookupNamespaceURIInternal(
3817 Substring(aQName.get(), colon), nameSpace);
3818 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"
, 3818); return rv; } } while (false)
;
3819
3820 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
3821 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
3822 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
3823
3824 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
3825 } else {
3826 *aNamespace = kNameSpaceID_None;
3827 *aLocalName = NS_AtomizeMainThread(aQName).take();
3828 }
3829 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"
, 3829); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3830 return NS_OK;
3831}
3832
3833// static
3834nsresult nsContentUtils::GetNodeInfoFromQName(
3835 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
3836 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
3837 mozilla::dom::NodeInfo** aNodeInfo) {
3838 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
3839 const char16_t* colon;
3840 nsresult rv = nsContentUtils::CheckQName(qName, true, &colon);
3841 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"
, 3841); return rv; } } while (false)
;
3842
3843 int32_t nsID;
3844 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
3845 if (colon) {
3846 const char16_t* end;
3847 qName.EndReading(end);
3848
3849 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
3850
3851 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix, nsID,
3852 aNodeType, aNodeInfo);
3853 } else {
3854 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
3855 aNodeInfo);
3856 }
3857 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"
, 3857); return rv; } } while (false)
;
3858
3859 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
3860 (*aNodeInfo)->GetPrefixAtom(),
3861 (*aNodeInfo)->NamespaceID())
3862 ? NS_OK
3863 : NS_ERROR_DOM_NAMESPACE_ERR;
3864}
3865
3866// static
3867void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
3868 nsAtom** aPrefix, nsAtom** aLocalName,
3869 int32_t* aNameSpaceID) {
3870 /**
3871 * Expat can send the following:
3872 * localName
3873 * namespaceURI<separator>localName
3874 * namespaceURI<separator>localName<separator>prefix
3875 *
3876 * and we use 0xFFFF for the <separator>.
3877 *
3878 */
3879
3880 const char16_t* uriEnd = nullptr;
3881 const char16_t* nameEnd = nullptr;
3882 const char16_t* pos;
3883 for (pos = aExpatName; *pos; ++pos) {
3884 if (*pos == 0xFFFF) {
3885 if (uriEnd) {
3886 nameEnd = pos;
3887 } else {
3888 uriEnd = pos;
3889 }
3890 }
3891 }
3892
3893 const char16_t* nameStart;
3894 if (uriEnd) {
3895 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
3896 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
3897
3898 nameStart = (uriEnd + 1);
3899 if (nameEnd) {
3900 const char16_t* prefixStart = nameEnd + 1;
3901 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
3902 } else {
3903 nameEnd = pos;
3904 *aPrefix = nullptr;
3905 }
3906 } else {
3907 *aNameSpaceID = kNameSpaceID_None;
3908 nameStart = aExpatName;
3909 nameEnd = pos;
3910 *aPrefix = nullptr;
3911 }
3912 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
3913}
3914
3915// static
3916PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
3917 Document* doc = aContent->GetComposedDoc();
3918 if (!doc) {
3919 return nullptr;
3920 }
3921 return doc->GetPresShell();
3922}
3923
3924// static
3925nsPresContext* nsContentUtils::GetContextForContent(
3926 const nsIContent* aContent) {
3927 PresShell* presShell = GetPresShellForContent(aContent);
3928 if (!presShell) {
3929 return nullptr;
3930 }
3931 return presShell->GetPresContext();
3932}
3933
3934// static
3935bool nsContentUtils::CanLoadImage(nsIURI* aURI, nsINode* aNode,
3936 Document* aLoadingDocument,
3937 nsIPrincipal* aLoadingPrincipal) {
3938 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"
, 3938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI" ")"); do { *((volatile int*)__null) = 3938
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3939 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"
, 3939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { *((volatile int*)__null
) = 3939; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3940 MOZ_ASSERT(aLoadingPrincipal, "Must have a loading 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 loading principal" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a loading principal" ")"); do { *((volatile
int*)__null) = 3940; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3941
3942 nsresult rv;
3943
3944 auto appType = nsIDocShell::APP_TYPE_UNKNOWN;
3945
3946 {
3947 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
3948 aLoadingDocument->GetDocShell();
3949 if (docShellTreeItem) {
3950 nsCOMPtr<nsIDocShellTreeItem> root;
3951 docShellTreeItem->GetInProcessRootTreeItem(getter_AddRefs(root));
3952
3953 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
3954
3955 if (docShell) {
3956 appType = docShell->GetAppType();
3957 }
3958 }
3959 }
3960
3961 if (appType != nsIDocShell::APP_TYPE_EDITOR) {
3962 // Editor apps get special treatment here, editors can load images
3963 // from anywhere. This allows editor to insert images from file://
3964 // into documents that are being edited.
3965 rv = sSecurityManager->CheckLoadURIWithPrincipal(
3966 aLoadingPrincipal, aURI, nsIScriptSecurityManager::ALLOW_CHROME,
3967 aLoadingDocument->InnerWindowID());
3968 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3969 return false;
3970 }
3971 }
3972
3973 nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new mozilla::net::LoadInfo(
3974 aLoadingPrincipal,
3975 aLoadingPrincipal, // triggering principal
3976 aNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
3977 nsIContentPolicy::TYPE_INTERNAL_IMAGE);
3978
3979 int16_t decision = nsIContentPolicy::ACCEPT;
3980
3981 rv = NS_CheckContentLoadPolicy(aURI, secCheckLoadInfo, &decision,
3982 GetContentPolicy());
3983
3984 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && NS_CP_ACCEPTED(decision)((decision) == nsIContentPolicy::ACCEPT);
3985}
3986
3987// static
3988bool nsContentUtils::IsInPrivateBrowsing(const Document* aDoc) {
3989 if (!aDoc) {
3990 return false;
3991 }
3992
3993 nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
3994 // See duplicated code below in IsInPrivateBrowsing(nsILoadGroup*)
3995 // and Document::Reset/ResetToURI
3996 if (loadGroup) {
3997 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3998 loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3999 if (callbacks) {
4000 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
4001 if (loadContext) {
4002 return loadContext->UsePrivateBrowsing();
4003 }
4004 }
4005 }
4006
4007 nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
4008 return channel && NS_UsePrivateBrowsing(channel);
4009}
4010
4011// static
4012bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
4013 if (!aLoadGroup) {
4014 return false;
4015 }
4016 bool isPrivate = false;
4017 nsCOMPtr<nsIInterfaceRequestor> callbacks;
4018 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
4019 if (callbacks) {
4020 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
4021 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
4022 }
4023 return isPrivate;
4024}
4025
4026// FIXME(emilio): This is (effectively) almost but not quite the same as
4027// Document::ShouldLoadImages(), which one is right?
4028bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
4029 if (!aDocument) {
4030 return false;
4031 }
4032 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
4033 aDocument->IsStaticDocument()) {
4034 return false;
4035 }
4036 nsCOMPtr<nsPIDOMWindowInner> win =
4037 do_QueryInterface(aDocument->GetScopeObject());
4038 return !win || !win->GetDocShell();
4039}
4040
4041imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
4042 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"
, 4042); return nullptr; } } while (false)
;
4043
4044 if (!aDoc) {
4045 return imgLoader::NormalLoader();
4046 }
4047 bool isPrivate = IsInPrivateBrowsing(aDoc);
4048 return isPrivate ? imgLoader::PrivateBrowsingLoader()
4049 : imgLoader::NormalLoader();
4050}
4051
4052// static
4053imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
4054 Document* aContext) {
4055 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"
, 4055); return nullptr; } } while (false)
;
4056
4057 if (!aChannel) {
4058 return imgLoader::NormalLoader();
4059 }
4060 return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader()
4061 : imgLoader::NormalLoader();
4062}
4063
4064// static
4065int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
4066 switch (aMode) {
4067 case CORS_ANONYMOUS:
4068 return imgILoader::LOAD_CORS_ANONYMOUS;
4069 case CORS_USE_CREDENTIALS:
4070 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
4071 default:
4072 return 0;
4073 }
4074}
4075
4076// static
4077nsresult nsContentUtils::LoadImage(
4078 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
4079 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
4080 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
4081 int32_t aLoadFlags, const nsAString& initiatorType,
4082 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
4083 bool aUseUrgentStartForChannel, bool aLinkPreload,
4084 uint64_t aEarlyHintPreloaderId,
4085 mozilla::dom::FetchPriority aFetchPriority) {
4086 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"
, 4086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI" ")"); do { *((volatile int*)__null) = 4086
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4087 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"
, 4087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") ("
"Must have a context" ")"); do { *((volatile int*)__null) = 4087
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4088 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"
, 4088); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { *((volatile int*)__null
) = 4088; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4089 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"
, 4089); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { *((volatile int*)__null
) = 4089; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4090 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"
, 4090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") ("
"Null out param" ")"); do { *((volatile int*)__null) = 4090;
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4091
4092 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
4093 if (!imgLoader) {
4094 // nothing we can do here
4095 return NS_ERROR_FAILURE;
4096 }
4097
4098 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
4099
4100 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
4101
4102 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"
, 4103); MOZ_PretendNoReturn(); } } while (0)
4103 "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"
, 4103); MOZ_PretendNoReturn(); } } while (0)
;
4104
4105 // XXXbz using "documentURI" for the initialDocumentURI is not quite
4106 // right, but the best we can do here...
4107 return imgLoader->LoadImage(aURI, /* uri to load */
4108 documentURI, /* initialDocumentURI */
4109 aReferrerInfo, /* referrerInfo */
4110 aLoadingPrincipal, /* loading principal */
4111 aRequestContextID, /* request context ID */
4112 loadGroup, /* loadgroup */
4113 aObserver, /* imgINotificationObserver */
4114 aContext, /* loading context */
4115 aLoadingDocument, /* uniquification key */
4116 aLoadFlags, /* load flags */
4117 nullptr, /* cache key */
4118 aContentPolicyType, /* content policy type */
4119 initiatorType, /* the load initiator */
4120 aUseUrgentStartForChannel, /* urgent-start flag */
4121 aLinkPreload, /* <link preload> initiator */
4122 aEarlyHintPreloaderId, aFetchPriority, aRequest);
4123}
4124
4125// static
4126already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
4127 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
4128 if (aRequest) {
4129 *aRequest = nullptr;
4130 }
4131
4132 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"
, 4132); return nullptr; } } while (false)
;
4133
4134 nsCOMPtr<imgIRequest> imgRequest;
4135 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4136 getter_AddRefs(imgRequest));
4137 if (!imgRequest) {
4138 return nullptr;
4139 }
4140
4141 nsCOMPtr<imgIContainer> imgContainer;
4142 imgRequest->GetImage(getter_AddRefs(imgContainer));
4143
4144 if (!imgContainer) {
4145 return nullptr;
4146 }
4147
4148 if (aRequest) {
4149 // If the consumer wants the request, verify it has actually loaded
4150 // successfully.
4151 uint32_t imgStatus;
4152 imgRequest->GetImageStatus(&imgStatus);
4153 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
4154 !(imgStatus & imgIRequest::STATUS_ERROR)) {
4155 imgRequest.swap(*aRequest);
4156 }
4157 }
4158
4159 return imgContainer.forget();
4160}
4161
4162static bool IsLinkWithURI(const nsIContent& aContent) {
4163 const auto* element = Element::FromNode(aContent);
4164 if (!element || !element->IsLink()) {
4165 return false;
4166 }
4167 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
4168 return !!absURI;
4169}
4170
4171static bool HasImageRequest(nsIContent& aContent) {
4172 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
4173 if (!imageContent) {
4174 return false;
4175 }
4176
4177 nsCOMPtr<imgIRequest> imgRequest;
4178 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4179 getter_AddRefs(imgRequest));
4180
4181 // XXXbz It may be draggable even if the request resulted in an error. Why?
4182 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
4183 return !!imgRequest;
4184}
4185
4186static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
4187 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
4188 if (el->Draggable()) {
4189 return Some(true);
4190 }
4191
4192 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
4193 nsGkAtoms::_false, eIgnoreCase)) {
4194 return Some(false);
4195 }
4196 }
4197 if (aContent.IsSVGElement()) {
4198 return Some(false);
4199 }
4200 return Nothing();
4201}
4202
4203// static
4204bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
4205 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"
, 4205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4205; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4206
4207 if (auto draggable = DraggableOverride(*aContent)) {
4208 return *draggable;
4209 }
4210
4211 // special handling for content area image and link dragging
4212 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
4213}
4214
4215// static
4216bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
4217 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"
, 4217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4217; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4218 return HasImageRequest(*aContent) &&
4219 DraggableOverride(*aContent).valueOr(true);
4220}
4221
4222// static
4223bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
4224 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"
, 4224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4225 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
4226}
4227
4228// static
4229nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
4230 nsAtom* aName,
4231 mozilla::dom::NodeInfo** aResult) {
4232 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
4233
4234 *aResult = niMgr
4235 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
4236 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
4237 .take();
4238 return NS_OK;
4239}
4240
4241static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
4242 uint32_t aPerm, bool aExactHostMatch) {
4243 if (!aPrincipal) {
4244 // We always deny (i.e. don't allow) the permission if we don't have a
4245 // principal.
4246 return aPerm != nsIPermissionManager::ALLOW_ACTION;
4247 }
4248
4249 nsCOMPtr<nsIPermissionManager> permMgr =
4250 components::PermissionManager::Service();
4251 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"
, 4251); return false; } } while (false)
;
4252
4253 uint32_t perm;
4254 nsresult rv;
4255 if (aExactHostMatch) {
4256 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
4257 } else {
4258 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4259 }
4260 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"
, 4260); return false; } } while (false)
;
4261
4262 return perm == aPerm;
4263}
4264
4265bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
4266 const nsACString& aType) {
4267 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4268 false);
4269}
4270
4271bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
4272 const nsACString& aType) {
4273 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4274 false);
4275}
4276
4277bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
4278 const nsACString& aType) {
4279 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4280 true);
4281}
4282
4283bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
4284 const nsACString& aType) {
4285 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4286 true);
4287}
4288
4289bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
4290 const nsACString& aType) {
4291 if (!aPrincipal) {
4292 return false;
4293 }
4294
4295 nsCOMPtr<nsIPermissionManager> permMgr =
4296 components::PermissionManager::Service();
4297 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"
, 4297); return false; } } while (false)
;
4298
4299 uint32_t perm;
4300 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4301 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"
, 4301); return false; } } while (false)
;
4302
4303 return perm != nsIPermissionManager::UNKNOWN_ACTION;
4304}
4305
4306static const char* gEventNames[] = {"event"};
4307static const char* gSVGEventNames[] = {"evt"};
4308// for b/w compat, the first name to onerror is still 'event', even though it
4309// is actually the error message
4310static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
4311 "error"};
4312
4313// static
4314void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
4315 bool aIsForWindow, uint32_t* aArgCount,
4316 const char*** aArgArray) {
4317#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
4318 *aArgCount = sizeof(names) / sizeof(names[0]); \
4319 *aArgArray = names;
4320
4321 // JSEventHandler is what does the arg magic for onerror, and it does
4322 // not seem to take the namespace into account. So we let onerror in all
4323 // namespaces get the 3 arg names.
4324 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
4325 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
4326 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
4327 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
4328 } else {
4329 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
4330 }
4331}
4332
4333// Note: The list of content bundles in nsStringBundle.cpp should be updated
4334// whenever entries are added or removed from this list.
4335static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = {
4336 // Must line up with the enum values in |PropertiesFile| enum.
4337 "chrome://global/locale/css.properties",
4338 "chrome://global/locale/xul.properties",
4339 "chrome://global/locale/layout_errors.properties",
4340 "chrome://global/locale/layout/HtmlForm.properties",
4341 "chrome://global/locale/printing.properties",
4342 "chrome://global/locale/dom/dom.properties",
4343 "chrome://global/locale/layout/htmlparser.properties",
4344 "chrome://global/locale/svg/svg.properties",
4345 "chrome://branding/locale/brand.properties",
4346 "chrome://global/locale/commonDialogs.properties",
4347 "chrome://global/locale/mathml/mathml.properties",
4348 "chrome://global/locale/security/security.properties",
4349 "chrome://necko/locale/necko.properties",
4350 "resource://gre/res/locale/layout/HtmlForm.properties",
4351 "resource://gre/res/locale/dom/dom.properties"};
4352
4353/* static */
4354nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
4355 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"
, 4356); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4356; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4356 "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"
, 4356); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4356; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4357 if (!sStringBundles[aFile]) {
4358 if (!sStringBundleService) {
4359 nsresult rv =
4360 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
4361 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"
, 4361); return rv; } } while (false)
;
4362 }
4363 RefPtr<nsIStringBundle> bundle;
4364 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)
4365 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)
;
4366 sStringBundles[aFile] = bundle.forget();
4367 }
4368 return NS_OK;
4369}
4370
4371/* static */
4372void nsContentUtils::AsyncPrecreateStringBundles() {
4373 // We only ever want to pre-create bundles in the parent process.
4374 //
4375 // All nsContentUtils bundles are shared between the parent and child
4376 // precesses, and the shared memory regions that back them *must* be created
4377 // in the parent, and then sent to all children.
4378 //
4379 // If we attempt to create a bundle in the child before its memory region is
4380 // available, we need to create a temporary non-shared bundle, and later
4381 // replace that with the shared memory copy. So attempting to pre-load in the
4382 // child is wasteful and unnecessary.
4383 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"
, 4383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4383; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4384
4385 for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT;
4386 ++bundleIndex) {
4387 nsresult rv = NS_DispatchToCurrentThreadQueue(
4388 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
4389 [bundleIndex]() {
4390 PropertiesFile file =
4391 static_cast<PropertiesFile>(bundleIndex);
4392 EnsureStringBundle(file);
4393 nsIStringBundle* bundle = sStringBundles[file];
4394 bundle->AsyncPreload();
4395 }),
4396 EventQueuePriority::Idle);
4397 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"
, 4397)
;
4398 }
4399}
4400
4401/* static */
4402bool nsContentUtils::SpoofLocaleEnglish() {
4403 // 0 - will prompt
4404 // 1 - don't spoof
4405 // 2 - spoof
4406 return StaticPrefs::privacy_spoof_english() == 2;
4407}
4408
4409static nsContentUtils::PropertiesFile GetMaybeSpoofedPropertiesFile(
4410 nsContentUtils::PropertiesFile aFile, const char* aKey,
4411 Document* aDocument) {
4412 // When we spoof English, use en-US properties in strings that are accessible
4413 // by content.
4414 bool spoofLocale = nsContentUtils::SpoofLocaleEnglish() &&
4415 (!aDocument || !aDocument->AllowsL10n());
4416 if (spoofLocale) {
4417 switch (aFile) {
4418 case nsContentUtils::eFORMS_PROPERTIES:
4419 return nsContentUtils::eFORMS_PROPERTIES_en_US;
4420 case nsContentUtils::eDOM_PROPERTIES:
4421 return nsContentUtils::eDOM_PROPERTIES_en_US;
4422 default:
4423 break;
4424 }
4425 }
4426 return aFile;
4427}
4428
4429/* static */
4430nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
4431 const char* aKey,
4432 Document* aDocument,
4433 nsAString& aResult) {
4434 return GetLocalizedString(
4435 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
4436}
4437
4438/* static */
4439nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
4440 const char* aKey,
4441 nsAString& aResult) {
4442 return FormatLocalizedString(aFile, aKey, {}, aResult);
4443}
4444
4445/* static */
4446nsresult nsContentUtils::FormatMaybeLocalizedString(
4447 PropertiesFile aFile, const char* aKey, Document* aDocument,
4448 const nsTArray<nsString>& aParams, nsAString& aResult) {
4449 return FormatLocalizedString(
4450 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
4451 aResult);
4452}
4453
4454class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
4455 public:
4456 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
4457 nsContentUtils::PropertiesFile aFile,
4458 const char* aKey,
4459 const nsTArray<nsString>& aParams,
4460 nsAString& aLocalizedString)
4461 : WorkerMainThreadRunnable(aWorkerPrivate,
4462 "FormatLocalizedStringRunnable"_ns),
4463 mFile(aFile),
4464 mKey(aKey),
4465 mParams(aParams),
4466 mLocalizedString(aLocalizedString) {
4467 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"
, 4467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWorkerPrivate"
")"); do { *((volatile int*)__null) = 4467; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4468 aWorkerPrivate->AssertIsOnWorkerThread();
4469 }
4470
4471 bool MainThreadRun() override {
4472 AssertIsOnMainThread();
4473
4474 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
4475 mLocalizedString);
4476 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"
, 4476)
;
4477 return true;
4478 }
4479
4480 nsresult GetResult() const { return mResult; }
4481
4482 private:
4483 const nsContentUtils::PropertiesFile mFile;
4484 const char* mKey;
4485 const nsTArray<nsString>& mParams;
4486 nsresult mResult = NS_ERROR_FAILURE;
4487 nsAString& mLocalizedString;
4488};
4489
4490/* static */
4491nsresult nsContentUtils::FormatLocalizedString(
4492 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
4493 nsAString& aResult) {
4494 if (!NS_IsMainThread()) {
4495 // nsIStringBundle is thread-safe but its creation is not, and in particular
4496 // we don't create and store nsIStringBundle objects in a thread-safe way.
4497 //
4498 // TODO(emilio): Maybe if we already have the right bundle created we could
4499 // just call into it, but we should make sure that Shutdown() doesn't get
4500 // called on the main thread when that happens which is a bit tricky to
4501 // prove?
4502 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
4503 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4503)
) {
4504 return NS_ERROR_UNEXPECTED;
4505 }
4506
4507 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
4508 workerPrivate, aFile, aKey, aParams, aResult);
4509
4510 runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors());
4511 return runnable->GetResult();
4512 }
4513
4514 MOZ_TRY(EnsureStringBundle(aFile))do { auto mozTryTempResult_ = ::mozilla::ToResult(EnsureStringBundle
(aFile)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
;
4515 nsIStringBundle* bundle = sStringBundles[aFile];
4516 if (aParams.IsEmpty()) {
4517 return bundle->GetStringFromName(aKey, aResult);
4518 }
4519 return bundle->FormatStringFromName(aKey, aParams, aResult);
4520}
4521
4522/* static */
4523void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
4524 const nsACString& aCategory,
4525 bool aFromPrivateWindow,
4526 bool aFromChromeContext,
4527 uint32_t aErrorFlags) {
4528 nsCOMPtr<nsIScriptError> scriptError =
4529 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
4530 if (scriptError) {
4531 nsCOMPtr<nsIConsoleService> console =
4532 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
4533 if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
4534 aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
4535 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
4536 console->LogMessage(scriptError);
4537 }
4538 }
4539}
4540
4541/* static */
4542nsresult nsContentUtils::ReportToConsole(
4543 uint32_t aErrorFlags, const nsACString& aCategory,
4544 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
4545 const nsTArray<nsString>& aParams, nsIURI* aURI,
4546 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber) {
4547 nsresult rv;
4548 nsAutoString errorText;
4549 if (!aParams.IsEmpty()) {
4550 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
4551 } else {
4552 rv = GetLocalizedString(aFile, aMessageName, errorText);
4553 }
4554 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"
, 4554); return rv; } } while (false)
;
4555
4556 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
4557 aDocument, aURI, aSourceLine, aLineNumber,
4558 aColumnNumber);
4559}
4560
4561/* static */
4562void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
4563 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
4564 nsContentUtils::eDOM_PROPERTIES, "EmptyGetElementByIdParam");
4565}
4566
4567/* static */
4568nsresult nsContentUtils::ReportToConsoleNonLocalized(
4569 const nsAString& aErrorText, uint32_t aErrorFlags,
4570 const nsACString& aCategory, const Document* aDocument, nsIURI* aURI,
4571 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber,
4572 MissingErrorLocationMode aLocationMode) {
4573 uint64_t innerWindowID = 0;
4574 if (aDocument) {
4575 if (!aURI) {
4576 aURI = aDocument->GetDocumentURI();
4577 }
4578 innerWindowID = aDocument->InnerWindowID();
4579 }
4580
4581 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
4582 innerWindowID, aURI, aSourceLine,
4583 aLineNumber, aColumnNumber, aLocationMode);
4584}
4585
4586/* static */
4587nsresult nsContentUtils::ReportToConsoleByWindowID(
4588 const nsAString& aErrorText, uint32_t aErrorFlags,
4589 const nsACString& aCategory, uint64_t aInnerWindowID, nsIURI* aURI,
4590 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber,
4591 MissingErrorLocationMode aLocationMode) {
4592 nsresult rv;
4593 if (!sConsoleService) { // only need to bother null-checking here
4594 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4595 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"
, 4595); return rv; } } while (false)
;
4596 }
4597
4598 nsAutoString spec;
4599 if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
4600 JSContext* cx = GetCurrentJSContext();
4601 if (cx) {
4602 nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
4603 }
4604 }
4605
4606 nsCOMPtr<nsIScriptError> errorObject =
4607 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
4608 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"
, 4608); return rv; } } while (false)
;
4609
4610 if (!spec.IsEmpty()) {
4611 rv = errorObject->InitWithWindowID(aErrorText,
4612 spec, // file name
4613 aSourceLine, aLineNumber, aColumnNumber,
4614 aErrorFlags, aCategory, aInnerWindowID);
4615 } else {
4616 rv = errorObject->InitWithSourceURI(aErrorText, aURI, aSourceLine,
4617 aLineNumber, aColumnNumber, aErrorFlags,
4618 aCategory, aInnerWindowID);
4619 }
4620 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"
, 4620); return rv; } } while (false)
;
4621
4622 return sConsoleService->LogMessage(errorObject);
4623}
4624
4625void nsContentUtils::LogMessageToConsole(const char* aMsg) {
4626 if (!sConsoleService) { // only need to bother null-checking here
4627 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4628 if (!sConsoleService) {
4629 return;
4630 }
4631 }
4632 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
4633}
4634
4635bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
4636 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
4637}
4638
4639bool nsContentUtils::IsAddonDoc(const Document* aDocument) {
4640 return aDocument &&
4641 aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal();
4642}
4643
4644bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
4645 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
4646 return bc->GetParent();
4647 }
4648 return false;
4649}
4650
4651static bool IsJSONType(const nsACString& aContentType) {
4652 return aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
4653 aContentType.EqualsLiteral(APPLICATION_JSON"application/json");
4654}
4655
4656static bool IsNonPlainTextType(const nsACString& aContentType) {
4657 // MIME type suffixes which should not be plain text.
4658 static constexpr std::string_view kNonPlainTextTypes[] = {
4659 "html",
4660 "xml",
4661 "xsl",
4662 "calendar",
4663 "x-calendar",
4664 "x-vcalendar",
4665 "vcalendar",
4666 "vcard",
4667 "x-vcard",
4668 "directory",
4669 "ldif",
4670 "qif",
4671 "x-qif",
4672 "x-csv",
4673 "x-vcf",
4674 "rtf",
4675 "comma-separated-values",
4676 "csv",
4677 "tab-separated-values",
4678 "tsv",
4679 "ofx",
4680 "vnd.sun.j2me.app-descriptor",
4681 "x-ms-iqy",
4682 "x-ms-odc",
4683 "x-ms-rqy",
4684 "x-ms-contact"};
4685
4686 // Trim off the "text/" prefix for comparison.
4687 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"
, 4687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)"
")"); do { *((volatile int*)__null) = 4687; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4688 std::string_view suffix = aContentType;
4689 suffix.remove_prefix(5);
4690
4691 for (std::string_view type : kNonPlainTextTypes) {
4692 if (type == suffix) {
4693 return true;
4694 }
4695 }
4696 return false;
4697}
4698
4699bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
4700 // All `text/*`, any JSON type and any JavaScript type are considered "plain
4701 // text" types for the purposes of how to render them as a document.
4702 return (StringBeginsWith(aContentType, "text/"_ns) &&
4703 !IsNonPlainTextType(aContentType)) ||
4704 IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType);
4705}
4706
4707bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
4708 // NOTE: This must be a subset of the list in IsPlainTextType().
4709 return IsJSONType(aContentType) ||
4710 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
4711 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
4712}
4713
4714bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
4715 return aDocument && aDocument->IsInChromeDocShell();
4716}
4717
4718// static
4719nsIContentPolicy* nsContentUtils::GetContentPolicy() {
4720 if (!sTriedToGetContentPolicy) {
4721 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
4722 // It's OK to not have a content policy service
4723 sTriedToGetContentPolicy = true;
4724 }
4725
4726 return sContentPolicyService;
4727}
4728
4729// static
4730bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
4731 const char16_t* name = aName->GetUTF16String();
4732 if (name[0] != 'o' || name[1] != 'n') {
4733 return false;
4734 }
4735
4736 EventNameMapping mapping;
4737 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
4738}
4739
4740// static
4741EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
4742 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"
, 4742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { *((volatile
int*)__null) = 4742; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4743 if (aName) {
4744 EventNameMapping mapping;
4745 if (sAtomEventTable->Get(aName, &mapping)) {
4746 return mapping.mMessage;
4747 }
4748 }
4749
4750 return eUnidentifiedEvent;
4751}
4752
4753// static
4754mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
4755 EventNameMapping mapping;
4756 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
4757
4758 return eBasicEventClass;
4759}
4760
4761nsAtom* nsContentUtils::GetEventMessageAndAtom(
4762 const nsAString& aName, mozilla::EventClassID aEventClassID,
4763 EventMessage* aEventMessage) {
4764 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"
, 4764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4764; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4765 EventNameMapping mapping;
4766 if (sStringEventTable->Get(aName, &mapping)) {
4767 *aEventMessage = mapping.mEventClassID == aEventClassID
4768 ? mapping.mMessage
4769 : eUnidentifiedEvent;
4770 return mapping.mAtom;
4771 }
4772
4773 // If we have cached lots of user defined event names, clear some of them.
4774 if (sUserDefinedEvents->Length() > 127) {
4775 while (sUserDefinedEvents->Length() > 64) {
4776 nsAtom* first = sUserDefinedEvents->ElementAt(0);
4777 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
4778 sUserDefinedEvents->RemoveElementAt(0);
4779 }
4780 }
4781
4782 *aEventMessage = eUnidentifiedEvent;
4783 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
4784 sUserDefinedEvents->AppendElement(atom);
4785 mapping.mAtom = atom;
4786 mapping.mMessage = eUnidentifiedEvent;
4787 mapping.mType = EventNameType_None;
4788 mapping.mEventClassID = eBasicEventClass;
4789 sStringEventTable->InsertOrUpdate(aName, mapping);
4790 return mapping.mAtom;
4791}
4792
4793// static
4794EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
4795 const nsAString& aName, nsAtom** aOnName) {
4796 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"
, 4796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4796; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4797
4798 // Check sStringEventTable for a matching entry. This will only fail for
4799 // user-defined event types.
4800 EventNameMapping mapping;
4801 if (sStringEventTable->Get(aName, &mapping)) {
4802 RefPtr<nsAtom> atom = mapping.mAtom;
4803 atom.forget(aOnName);
4804 return mapping.mMessage;
4805 }
4806
4807 // sStringEventTable did not contain an entry for this event type string.
4808 // Call GetEventMessageAndAtom, which will create an event type atom and
4809 // cache it in sStringEventTable for future calls.
4810 EventMessage msg = eUnidentifiedEvent;
4811 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
4812 atom.forget(aOnName);
4813 return msg;
4814}
4815
4816static already_AddRefed<Event> GetEventWithTarget(
4817 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4818 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4819 Trusted aTrusted, ErrorResult& aErrorResult) {
4820 RefPtr<Event> event =
4821 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
4822 if (aErrorResult.Failed()) {
4823 return nullptr;
4824 }
4825
4826 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
4827 event->SetTrusted(aTrusted == Trusted::eYes);
4828
4829 event->SetTarget(aTarget);
4830
4831 return event.forget();
4832}
4833
4834// static
4835nsresult nsContentUtils::DispatchTrustedEvent(
4836 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4837 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4838 bool* aDefaultAction) {
4839 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"
, 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4840 !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"
, 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4841 "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"
, 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4842 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4843 aComposed, Trusted::eYes, aDefaultAction);
4844}
4845
4846// static
4847nsresult nsContentUtils::DispatchUntrustedEvent(
4848 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4849 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
4850 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4851 Composed::eDefault, Trusted::eNo, aDefaultAction);
4852}
4853
4854// static
4855nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4856 const nsAString& aEventName,
4857 CanBubble aCanBubble,
4858 Cancelable aCancelable,
4859 Composed aComposed, Trusted aTrusted,
4860 bool* aDefaultAction,
4861 ChromeOnlyDispatch aOnlyChromeDispatch) {
4862 if (!aDoc || !aTarget) {
4863 return NS_ERROR_INVALID_ARG;
4864 }
4865
4866 ErrorResult err;
4867 RefPtr<Event> event =
4868 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4869 aComposed, aTrusted, err);
4870 if (err.Failed()) {
4871 return err.StealNSResult();
4872 }
4873 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
4874 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4875
4876 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
4877 if (aDefaultAction) {
4878 *aDefaultAction = doDefault;
4879 }
4880 return err.StealNSResult();
4881}
4882
4883// static
4884nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4885 WidgetEvent& aEvent,
4886 EventMessage aEventMessage,
4887 CanBubble aCanBubble,
4888 Cancelable aCancelable, Trusted aTrusted,
4889 bool* aDefaultAction,
4890 ChromeOnlyDispatch aOnlyChromeDispatch) {
4891 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"
, 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4892 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"
, 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4893
4894 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
4895 aEvent.SetDefaultComposed();
4896 aEvent.SetDefaultComposedInNativeAnonymousContent();
4897
4898 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
4899 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
4900 aEvent.mFlags.mOnlyChromeDispatch =
4901 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4902
4903 aEvent.mTarget = aTarget;
4904
4905 nsEventStatus status = nsEventStatus_eIgnore;
4906 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
4907 nullptr, &status);
4908 if (aDefaultAction) {
4909 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
4910 }
4911 return rv;
4912}
4913
4914// static
4915nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
4916 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
4917 mozilla::EditorInputType::eUnknown, nullptr,
4918 InputEventOptions());
4919}
4920
4921// static
4922nsresult nsContentUtils::DispatchInputEvent(
4923 Element* aEventTargetElement, EventMessage aEventMessage,
4924 EditorInputType aEditorInputType, EditorBase* aEditorBase,
4925 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
4926 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"
, 4927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4927 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"
, 4927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4928
4929 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4929)
) {
4930 return NS_ERROR_INVALID_ARG;
4931 }
4932
4933 // If this is called from editor, the instance should be set to aEditorBase.
4934 // Otherwise, we need to look for an editor for aEventTargetElement.
4935 // However, we don't need to do it for HTMLEditor since nobody shouldn't
4936 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
4937 // itself.
4938 bool useInputEvent = false;
4939 if (aEditorBase) {
4940 useInputEvent = true;
4941 } else if (HTMLTextAreaElement* textAreaElement =
4942 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
4943 aEditorBase = textAreaElement->GetTextEditorWithoutCreation();
4944 useInputEvent = true;
4945 } else if (HTMLInputElement* inputElement =
4946 HTMLInputElement::FromNode(aEventTargetElement)) {
4947 if (inputElement->IsInputEventTarget()) {
4948 aEditorBase = inputElement->GetTextEditorWithoutCreation();
4949 useInputEvent = true;
4950 }
4951 }
4952#ifdef DEBUG1
4953 else {
4954 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"
, 4955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4955 "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"
, 4955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4956 }
4957#endif // #ifdef DEBUG
4958
4959 if (!useInputEvent) {
4960 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"
, 4960); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { *((volatile int*)__null) = 4960; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4961 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"
, 4961); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { *((volatile int*)__null) = 4961; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4962 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"
, 4962); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4962; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4963 // Dispatch "input" event with Event instance.
4964 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
4965 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
4966 widgetEvent.mFlags.mCancelable = false;
4967 widgetEvent.mFlags.mComposed = true;
4968 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
4969 widgetEvent, aEventStatus);
4970 }
4971
4972 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"
, 4973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4973; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4973 !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"
, 4973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4973; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4974 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"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4975 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"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4976 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"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4977
4978 nsCOMPtr<nsIWidget> widget;
4979 if (aEditorBase) {
4980 widget = aEditorBase->GetWidget();
4981 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4981)
) {
4982 return NS_ERROR_FAILURE;
4983 }
4984 } else {
4985 Document* document = aEventTargetElement->OwnerDoc();
4986 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4986)
) {
4987 return NS_ERROR_FAILURE;
4988 }
4989 // If we're running xpcshell tests, we fail to get presShell here.
4990 // Even in such case, we need to dispatch "input" event without widget.
4991 PresShell* presShell = document->GetPresShell();
4992 if (presShell) {
4993 nsPresContext* presContext = presShell->GetPresContext();
4994 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4994)
) {
4995 return NS_ERROR_FAILURE;
4996 }
4997 widget = presContext->GetRootWidget();
4998 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4998)
) {
4999 return NS_ERROR_FAILURE;
5000 }
5001 }
5002 }
5003
5004 // Dispatch "input" event with InputEvent instance.
5005 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
5006
5007 inputEvent.mFlags.mCancelable =
5008 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
5009 IsCancelableBeforeInputEvent(aEditorInputType);
5010 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"
, 5010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { *((volatile int*)__null) = 5010; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5011
5012 // If there is an editor, set isComposing to true when it has composition.
5013 // Note that EditorBase::IsIMEComposing() may return false even when we
5014 // need to set it to true.
5015 // Otherwise, i.e., editor hasn't been created for the element yet,
5016 // we should set isComposing to false since the element can never has
5017 // composition without editor.
5018 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
5019
5020 if (!aEditorBase || aEditorBase->IsTextEditor()) {
5021 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
5022 inputEvent.mData = std::move(aOptions.mData);
5023 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"
, 5024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 5024; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5024 "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"
, 5024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 5024; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5025 }
5026#ifdef DEBUG1
5027 else {
5028 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"
, 5028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 5028; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5029 }
5030#endif // #ifdef DEBUG
5031 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"
, 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5032 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"
, 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5033 "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"
, 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5034 } else {
5035 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"
, 5035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { *((volatile int*)__null) = 5035; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5036 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
5037 inputEvent.mData = std::move(aOptions.mData);
5038 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"
, 5039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 5039; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5039 "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"
, 5039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 5039; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5040 } else {
5041 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"
, 5041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 5041; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5042 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
5043 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
5044 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"
, 5045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 5045; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5045 "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"
, 5045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 5045; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5046 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"
, 5047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 5047; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5047 "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"
, 5047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 5047; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5048 }
5049#ifdef DEBUG1
5050 else {
5051 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"
, 5052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 5052; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5052 "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"
, 5052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 5052; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5053 }
5054#endif // #ifdef DEBUG
5055 }
5056 if (aEventMessage == eEditorBeforeInput &&
5057 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
5058 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
5059 }
5060#ifdef DEBUG1
5061 else {
5062 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"
, 5063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 5063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5063 "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"
, 5063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 5063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5064 }
5065#endif // #ifdef DEBUG
5066 }
5067
5068 inputEvent.mInputType = aEditorInputType;
5069
5070 // If we cannot dispatch an event right now, we cannot make it cancelable.
5071 if (!nsContentUtils::IsSafeToRunScript()) {
5072 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"
, 5074); MOZ_PretendNoReturn(); } } while (0)
5073 !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"
, 5074); MOZ_PretendNoReturn(); } } while (0)
5074 "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"
, 5074); MOZ_PretendNoReturn(); } } while (0)
;
5075 inputEvent.mFlags.mCancelable = false;
5076 }
5077 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
5078 inputEvent, aEventStatus);
5079}
5080
5081nsresult nsContentUtils::DispatchChromeEvent(
5082 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
5083 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
5084 if (!aDoc || !aTarget) {
5085 return NS_ERROR_INVALID_ARG;
5086 }
5087
5088 if (!aDoc->GetWindow()) {
5089 return NS_ERROR_INVALID_ARG;
5090 }
5091
5092 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
5093 if (!piTarget) {
5094 return NS_ERROR_INVALID_ARG;
5095 }
5096
5097 ErrorResult err;
5098 RefPtr<Event> event =
5099 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
5100 Composed::eDefault, Trusted::eYes, err);
5101 if (err.Failed()) {
5102 return err.StealNSResult();
5103 }
5104
5105 bool defaultActionEnabled =
5106 piTarget->DispatchEvent(*event, CallerType::System, err);
5107 if (aDefaultAction) {
5108 *aDefaultAction = defaultActionEnabled;
5109 }
5110 return err.StealNSResult();
5111}
5112
5113void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
5114 CallerType aCallerType) {
5115 RefPtr<Element> target = &aFrameElement;
5116 bool defaultAction = true;
5117 if (aCanRaise) {
5118 DispatchEventOnlyToChrome(target->OwnerDoc(), target,
5119 u"framefocusrequested"_ns, CanBubble::eYes,
5120 Cancelable::eYes, &defaultAction);
5121 }
5122 if (!defaultAction) {
5123 return;
5124 }
5125
5126 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
5127 if (!fm) {
5128 return;
5129 }
5130
5131 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
5132 if (aCanRaise) {
5133 flags |= nsIFocusManager::FLAG_RAISE;
5134 }
5135
5136 if (aCallerType == CallerType::NonSystem) {
5137 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
5138 }
5139
5140 fm->SetFocus(target, flags);
5141}
5142
5143nsresult nsContentUtils::DispatchEventOnlyToChrome(
5144 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
5145 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
5146 bool* aDefaultAction) {
5147 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
5148 aComposed, Trusted::eYes, aDefaultAction,
5149 ChromeOnlyDispatch::eYes);
5150}
5151
5152/* static */
5153Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5154 const nsAtom* aId) {
5155 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
5156 if (aId == cur->GetID()) {
5157 return cur->AsElement();
5158 }
5159 }
5160
5161 return nullptr;
5162}
5163
5164/* static */
5165Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5166 const nsAString& aId) {
5167 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"
, 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { *((volatile int
*)__null) = 5167; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5168
5169 // ID attrs are generally stored as atoms, so just atomize this up front
5170 RefPtr<nsAtom> id(NS_Atomize(aId));
5171 if (!id) {
5172 // OOM, so just bail
5173 return nullptr;
5174 }
5175
5176 return MatchElementId(aContent, id);
5177}
5178
5179/* static */
5180void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
5181 nsCOMPtr<nsIObserverService> observerService =
5182 mozilla::services::GetObserverService();
5183 if (observerService) {
5184 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
5185 false);
5186 }
5187}
5188
5189/* static */
5190void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
5191 nsCOMPtr<nsIObserverService> observerService =
5192 mozilla::services::GetObserverService();
5193 if (observerService) {
5194 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
5195 }
5196}
5197
5198/* static */
5199bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
5200 int32_t aNameSpaceID, nsAtom* aName) {
5201 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
5202 return aContent->IsElement() &&
5203 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
5204 eCaseMatters) ==
5205 AttrArray::ATTR_VALUE_NO_MATCH;
5206}
5207
5208/* static */
5209bool nsContentUtils::WantMutationEvents(nsINode* aNode, uint32_t aType,
5210 nsINode* aTargetForSubtreeModified) {
5211 Document* doc = aNode->OwnerDoc();
5212 if (!doc->FireMutationEvents()) {
5213 return false;
5214 }
5215
5216 // global object will be null for documents that don't have windows.
5217 nsPIDOMWindowInner* window = doc->GetInnerWindow();
5218 // This relies on EventListenerManager::AddEventListener, which sets
5219 // all mutation bits when there is a listener for DOMSubtreeModified event.
5220 if (window && !window->HasMutationListeners(aType)) {
5221 return false;
5222 }
5223
5224 if (aNode->ChromeOnlyAccess() || aNode->IsInShadowTree()) {
5225 return false;
5226 }
5227
5228 doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
5229
5230 // If we have a window, we can check it for mutation listeners now.
5231 if (aNode->IsInUncomposedDoc()) {
5232 nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
5233 if (piTarget) {
5234 EventListenerManager* manager = piTarget->GetExistingListenerManager();
5235 if (manager && manager->HasMutationListeners()) {
5236 return true;
5237 }
5238 }
5239 }
5240
5241 // If we have a window, we know a mutation listener is registered, but it
5242 // might not be in our chain. If we don't have a window, we might have a
5243 // mutation listener. Check quickly to see.
5244 while (aNode) {
5245 EventListenerManager* manager = aNode->GetExistingListenerManager();
5246 if (manager && manager->HasMutationListeners()) {
5247 return true;
5248 }
5249
5250 aNode = aNode->GetParentNode();
5251 }
5252
5253 return false;
5254}
5255
5256/* static */
5257bool nsContentUtils::HasMutationListeners(Document* aDocument, uint32_t aType) {
5258 nsPIDOMWindowInner* window =
5259 aDocument ? aDocument->GetInnerWindow() : nullptr;
5260
5261 // This relies on EventListenerManager::AddEventListener, which sets
5262 // all mutation bits when there is a listener for DOMSubtreeModified event.
5263 return !window || window->HasMutationListeners(aType);
5264}
5265
5266void nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent) {
5267 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"
, 5267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") ("
"Missing child" ")"); do { *((volatile int*)__null) = 5267; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5268 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"
, 5268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode() == aParent"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5268
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5269 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"
, 5269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->OwnerDoc() == aParent->OwnerDoc()"
") (" "Wrong owner-doc" ")"); do { *((volatile int*)__null) =
5269; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5270
5271 // Having an explicit check here since it's an easy mistake to fall into,
5272 // and there might be existing code with problems. We'd rather be safe
5273 // than fire DOMNodeRemoved in all corner cases. We also rely on it for
5274 // nsAutoScriptBlockerSuppressNodeRemoved.
5275 if (!IsSafeToRunScript()) {
5276 // This checks that IsSafeToRunScript is true since we don't want to fire
5277 // events when that is false. We can't rely on EventDispatcher to assert
5278 // this in this situation since most of the time there are no mutation
5279 // event listeners, in which case we won't even attempt to dispatch events.
5280 // However this also allows for two exceptions. First off, we don't assert
5281 // if the mutation happens to native anonymous content since we never fire
5282 // mutation events on such content anyway.
5283 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
5284 // that is a know case when we'd normally fire a mutation event, but can't
5285 // make that safe and so we suppress it at this time. Ideally this should
5286 // go away eventually.
5287 if (!aChild->IsInNativeAnonymousSubtree() &&
5288 !sDOMNodeRemovedSuppressCount) {
5289 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"
, 5289); MOZ_PretendNoReturn(); } while (0)
;
5290 WarnScriptWasIgnored(aChild->OwnerDoc());
5291 }
5292 return;
5293 }
5294
5295 {
5296 Document* doc = aParent->OwnerDoc();
5297 if (MOZ_UNLIKELY(doc->DevToolsWatchingDOMMutations())(__builtin_expect(!!(doc->DevToolsWatchingDOMMutations()),
0))
&&
5298 aChild->IsInComposedDoc() && !aChild->ChromeOnlyAccess()) {
5299 DispatchChromeEvent(doc, aChild, u"devtoolschildremoved"_ns,
5300 CanBubble::eNo, Cancelable::eNo);
5301 }
5302 }
5303
5304 if (WantMutationEvents(aChild, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04, aParent)) {
5305 InternalMutationEvent mutation(true, eLegacyNodeRemoved);
5306 mutation.mRelatedNode = aParent;
5307
5308 mozAutoSubtreeModified subtree(aParent->OwnerDoc(), aParent);
5309 EventDispatcher::Dispatch(aChild, nullptr, &mutation);
5310 }
5311}
5312
5313void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() {
5314 if (!sEventListenerManagersHash) {
5315 return;
5316 }
5317
5318 for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
5319 auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
5320 nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
5321 if (n && n->IsInComposedDoc() &&
5322 nsCCUncollectableMarker::InGeneration(
5323 n->OwnerDoc()->GetMarkedCCGeneration())) {
5324 entry->mListenerManager->MarkForCC();
5325 }
5326 }
5327}
5328
5329/* static */
5330void nsContentUtils::TraverseListenerManager(
5331 nsINode* aNode, nsCycleCollectionTraversalCallback& cb) {
5332 if (!sEventListenerManagersHash) {
5333 // We're already shut down, just return.
5334 return;
5335 }
5336
5337 auto entry = static_cast<EventListenerManagerMapEntry*>(
5338 sEventListenerManagersHash->Search(aNode));
5339 if (entry) {
5340 CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
5341 "[via hash] mListenerManager");
5342 }
5343}
5344
5345EventListenerManager* nsContentUtils::GetListenerManagerForNode(
5346 nsINode* aNode) {
5347 if (!sEventListenerManagersHash) {
5348 // We're already shut down, don't bother creating an event listener
5349 // manager.
5350
5351 return nullptr;
5352 }
5353
5354 auto entry = static_cast<EventListenerManagerMapEntry*>(
5355 sEventListenerManagersHash->Add(aNode, fallible));
5356
5357 if (!entry) {
5358 return nullptr;
5359 }
5360
5361 if (!entry->mListenerManager) {
5362 entry->mListenerManager = new EventListenerManager(aNode);
5363
5364 aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
5365 }
5366
5367 return entry->mListenerManager;
5368}
5369
5370EventListenerManager* nsContentUtils::GetExistingListenerManagerForNode(
5371 const nsINode* aNode) {
5372 if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
5373 return nullptr;
5374 }
5375
5376 if (!sEventListenerManagersHash) {
5377 // We're already shut down, don't bother creating an event listener
5378 // manager.
5379
5380 return nullptr;
5381 }
5382
5383 auto entry = static_cast<EventListenerManagerMapEntry*>(
5384 sEventListenerManagersHash->Search(aNode));
5385 if (entry) {
5386 return entry->mListenerManager;
5387 }
5388
5389 return nullptr;
5390}
5391
5392void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
5393 DOMArena* aDOMArena) {
5394 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"
, 5394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5394; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5395 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"
, 5395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5396 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"
, 5396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)"
")"); do { *((volatile int*)__null) = 5396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5397 if (!sDOMArenaHashtable) {
5398 sDOMArenaHashtable =
5399 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
5400 }
5401 aNode->SetFlags(NODE_KEEPS_DOMARENA);
5402 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
5403}
5404
5405already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
5406 const nsINode* aNode) {
5407 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"
, 5407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5407; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5408 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"
, 5408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5409 RefPtr<DOMArena> arena;
5410 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
5411 return arena.forget();
5412}
5413
5414/* static */
5415void nsContentUtils::RemoveListenerManager(nsINode* aNode) {
5416 if (sEventListenerManagersHash) {
5417 auto entry = static_cast<EventListenerManagerMapEntry*>(
5418 sEventListenerManagersHash->Search(aNode));
5419 if (entry) {
5420 RefPtr<EventListenerManager> listenerManager;
5421 listenerManager.swap(entry->mListenerManager);
5422 // Remove the entry and *then* do operations that could cause further
5423 // modification of sEventListenerManagersHash. See bug 334177.
5424 sEventListenerManagersHash->RawRemove(entry);
5425 if (listenerManager) {
5426 listenerManager->Disconnect();
5427 }
5428 }
5429 }
5430}
5431
5432/* static */
5433bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
5434 int32_t aNamespaceID) {
5435 if (aNamespaceID == kNameSpaceID_Unknown-1) {
5436 return false;
5437 }
5438
5439 if (!aPrefix) {
5440 // If the prefix is null, then either the QName must be xmlns or the
5441 // namespace must not be XMLNS.
5442 return (aLocalName == nsGkAtoms::xmlns) ==
5443 (aNamespaceID == kNameSpaceID_XMLNS1);
5444 }
5445
5446 // If the prefix is non-null then the namespace must not be null.
5447 if (aNamespaceID == kNameSpaceID_None) {
5448 return false;
5449 }
5450
5451 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
5452 // but the localname must not be xmlns.
5453 if (aNamespaceID == kNameSpaceID_XMLNS1) {
5454 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
5455 }
5456
5457 // If the namespace is not the XMLNS namespace then the prefix must not be
5458 // xmlns.
5459 // If the namespace is the XML namespace then the prefix can be anything.
5460 // If the namespace is not the XML namespace then the prefix must not be xml.
5461 return aPrefix != nsGkAtoms::xmlns &&
5462 (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml);
5463}
5464
5465already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment(
5466 nsINode* aContextNode, const nsAString& aFragment,
5467 bool aPreventScriptExecution, ErrorResult& aRv) {
5468 if (!aContextNode) {
5469 aRv.Throw(NS_ERROR_INVALID_ARG);
5470 return nullptr;
5471 }
5472
5473 // If we don't have a document here, we can't get the right security context
5474 // for compiling event handlers... so just bail out.
5475 RefPtr<Document> document = aContextNode->OwnerDoc();
5476 bool isHTML = document->IsHTMLDocument();
5477
5478 if (isHTML) {
5479 RefPtr<DocumentFragment> frag = new (document->NodeInfoManager())
5480 DocumentFragment(document->NodeInfoManager());
5481
5482 Element* element = aContextNode->GetAsElementOrParentElement();
5483 if (element && !element->IsHTMLElement(nsGkAtoms::html)) {
5484 aRv = ParseFragmentHTML(
5485 aFragment, frag, element->NodeInfo()->NameAtom(),
5486 element->GetNameSpaceID(),
5487 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
5488 aPreventScriptExecution);
5489 } else {
5490 aRv = ParseFragmentHTML(
5491 aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3,
5492 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
5493 aPreventScriptExecution);
5494 }
5495
5496 return frag.forget();
5497 }
5498
5499 AutoTArray<nsString, 32> tagStack;
5500 nsAutoString uriStr, nameStr;
5501 for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) {
5502 nsString& tagName = *tagStack.AppendElement();
5503 // It mostly doesn't actually matter what tag name we use here: XML doesn't
5504 // have parsing that depends on the open tag stack, apart from namespace
5505 // declarations. So this whole tagStack bit is just there to get the right
5506 // namespace declarations to the XML parser. That said, the parser _is_
5507 // going to create elements with the tag names we provide here, so we need
5508 // to make sure they are not names that can trigger custom element
5509 // constructors. Just make up a name that is never going to be a valid
5510 // custom element name.
5511 //
5512 // The principled way to do this would probably be to add a new FromParser
5513 // value and make sure we use it when creating the context elements, then
5514 // make sure we teach all FromParser consumers (and in particular the custom
5515 // element code) about it as needed. But right now the XML parser never
5516 // actually uses FromParser values other than NOT_FROM_PARSER, and changing
5517 // that is pretty complicated.
5518 tagName.AssignLiteral("notacustomelement");
5519
5520 // see if we need to add xmlns declarations
5521 uint32_t count = element->GetAttrCount();
5522 bool setDefaultNamespace = false;
5523 if (count > 0) {
5524 uint32_t index;
5525
5526 for (index = 0; index < count; index++) {
5527 const BorrowedAttrInfo info = element->GetAttrInfoAt(index);
5528 const nsAttrName* name = info.mName;
5529 if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) {
5530 info.mValue->ToString(uriStr);
5531
5532 // really want something like nsXMLContentSerializer::SerializeAttr
5533 tagName.AppendLiteral(" xmlns"); // space important
5534 if (name->GetPrefix()) {
5535 tagName.Append(char16_t(':'));
5536 name->LocalName()->ToString(nameStr);
5537 tagName.Append(nameStr);
5538 } else {
5539 setDefaultNamespace = true;
5540 }
5541 tagName.AppendLiteral(R"(=")");
5542 tagName.Append(uriStr);
5543 tagName.Append('"');
5544 }
5545 }
5546 }
5547
5548 if (!setDefaultNamespace) {
5549 mozilla::dom::NodeInfo* info = element->NodeInfo();
5550 if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) {
5551 // We have no namespace prefix, but have a namespace ID. Push
5552 // default namespace attr in, so that our kids will be in our
5553 // namespace.
5554 info->GetNamespaceURI(uriStr);
5555 tagName.AppendLiteral(R"( xmlns=")");
5556 tagName.Append(uriStr);
5557 tagName.Append('"');
5558 }
5559 }
5560 }
5561
5562 RefPtr<DocumentFragment> frag;
5563 aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution,
5564 -1, getter_AddRefs(frag));
5565 return frag.forget();
5566}
5567
5568/* static */
5569void nsContentUtils::DropFragmentParsers() {
5570 NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release
(); (sHTMLFragmentParser) = 0; } } while (0)
;
5571 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
5572 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
5573}
5574
5575/* static */
5576void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); }
5577
5578/* Helper function to compuate Sanitization Flags for ParseFramentHTML/XML */
5579uint32_t computeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) {
5580 uint32_t sanitizationFlags = 0;
5581 if (aPrincipal->IsSystemPrincipal()) {
5582 if (aFlags < 0) {
5583 // if this is a chrome-privileged document and no explicit flags
5584 // were passed, then use this sanitization flags.
5585 sanitizationFlags = nsIParserUtils::SanitizerAllowStyle |
5586 nsIParserUtils::SanitizerAllowComments |
5587 nsIParserUtils::SanitizerDropForms |
5588 nsIParserUtils::SanitizerLogRemovals;
5589 } else {
5590 // if the caller explicitly passes flags, then we use those
5591 // flags but additionally drop forms.
5592 sanitizationFlags = aFlags | nsIParserUtils::SanitizerDropForms;
5593 }
5594 } else if (aFlags >= 0) {
5595 // aFlags by default is -1 and is only ever non equal to -1 if the
5596 // caller of ParseFragmentHTML/ParseFragmentXML is
5597 // ParserUtils::ParseFragment(). Only in that case we should use
5598 // the sanitization flags passed within aFlags.
5599 sanitizationFlags = aFlags;
5600 }
5601 return sanitizationFlags;
5602}
5603
5604/* static */
5605void nsContentUtils::SetHTMLUnsafe(FragmentOrElement* aTarget,
5606 Element* aContext,
5607 const nsAString& aSource) {
5608 RefPtr<DocumentFragment> fragment;
5609 {
5610 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"
, 5611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { *(
(volatile int*)__null) = 5611; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
5611 "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"
, 5611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { *(
(volatile int*)__null) = 5611; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
5612 mozilla::AutoRestore<bool> guard(sFragmentParsingActive);
5613 sFragmentParsingActive = true;
5614 if (!sHTMLFragmentParser) {
5615 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5616 // Now sHTMLFragmentParser owns the object
5617 }
5618
5619 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
5620 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
5621
5622 RefPtr<Document> doc = aTarget->OwnerDoc();
5623 fragment = doc->CreateDocumentFragment();
5624 nsresult rv = sHTMLFragmentParser->ParseFragment(
5625 aSource, fragment, contextLocalName, contextNameSpaceID,
5626 fragment->OwnerDoc()->GetCompatibilityMode() ==
5627 eCompatibility_NavQuirks,
5628 true, true);
5629 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5630 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"
, 5630)
;
5631 }
5632 }
5633
5634 aTarget->ReplaceChildren(fragment, IgnoreErrors());
5635}
5636
5637/* static */
5638nsresult nsContentUtils::ParseFragmentHTML(
5639 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
5640 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
5641 bool aPreventScriptExecution, int32_t aFlags) {
5642 if (nsContentUtils::sFragmentParsingActive) {
5643 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"
, 5643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5643; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5644 return NS_ERROR_DOM_INVALID_STATE_ERR;
5645 }
5646 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5647 nsContentUtils::sFragmentParsingActive = true;
5648 if (!sHTMLFragmentParser) {
5649 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5650 // Now sHTMLFragmentParser owns the object
5651 }
5652
5653 nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal();
5654
5655#ifdef DEBUG1
5656 // aFlags should always be -1 unless the caller of ParseFragmentHTML
5657 // is ParserUtils::ParseFragment() which is the only caller that intends
5658 // sanitization. For all other callers we need to ensure to call
5659 // AuditParsingOfHTMLXMLFragments.
5660 if (aFlags < 0) {
5661 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
5662 aSourceBuffer);
5663 }
5664#endif
5665
5666 nsIContent* target = aTargetNode;
5667
5668 RefPtr<Document> doc = aTargetNode->OwnerDoc();
5669 RefPtr<DocumentFragment> fragment;
5670 // We sanitize if the fragment occurs in a system privileged
5671 // context, an about: page, or if there are explicit sanitization flags.
5672 // Please note that about:blank and about:srcdoc inherit the security
5673 // context from the embedding context and hence are not loaded using
5674 // an about: scheme principal.
5675 bool shouldSanitize = nodePrincipal->IsSystemPrincipal() ||
5676 nodePrincipal->SchemeIs("about") || aFlags >= 0;
5677 if (shouldSanitize) {
5678 if (!doc->IsLoadedAsData()) {
5679 doc = nsContentUtils::CreateInertHTMLDocument(doc);
5680 if (!doc) {
5681 return NS_ERROR_FAILURE;
5682 }
5683 }
5684 fragment =
5685 new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager());
5686 target = fragment;
5687 }
5688
5689 nsresult rv = sHTMLFragmentParser->ParseFragment(
5690 aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks,
5691 aPreventScriptExecution, false);
5692 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"
, 5692); return rv; } } while (false)
;
5693
5694 if (fragment) {
5695 uint32_t sanitizationFlags =
5696 computeSanitizationFlags(nodePrincipal, aFlags);
5697 // Don't fire mutation events for nodes removed by the sanitizer.
5698 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
5699 nsTreeSanitizer sanitizer(sanitizationFlags);
5700 sanitizer.Sanitize(fragment);
5701
5702 ErrorResult error;
5703 aTargetNode->AppendChild(*fragment, error);
5704 rv = error.StealNSResult();
5705 }
5706
5707 return rv;
5708}
5709
5710/* static */
5711nsresult nsContentUtils::ParseDocumentHTML(
5712 const nsAString& aSourceBuffer, Document* aTargetDocument,
5713 bool aScriptingEnabledForNoscriptParsing) {
5714 if (nsContentUtils::sFragmentParsingActive) {
5715 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"
, 5715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5716 return NS_ERROR_DOM_INVALID_STATE_ERR;
5717 }
5718 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5719 nsContentUtils::sFragmentParsingActive = true;
5720 if (!sHTMLFragmentParser) {
5721 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
5722 // Now sHTMLFragmentParser owns the object
5723 }
5724 nsresult rv = sHTMLFragmentParser->ParseDocument(
5725 aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing);
5726 return rv;
5727}
5728
5729/* static */
5730nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
5731 Document* aDocument,
5732 nsTArray<nsString>& aTagStack,
5733 bool aPreventScriptExecution,
5734 int32_t aFlags,
5735 DocumentFragment** aReturn) {
5736 if (nsContentUtils::sFragmentParsingActive) {
5737 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"
, 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { *((volatile int*)__null) = 5737; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5738 return NS_ERROR_DOM_INVALID_STATE_ERR;
5739 }
5740 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5741 nsContentUtils::sFragmentParsingActive = true;
5742 if (!sXMLFragmentParser) {
5743 RefPtr<nsParser> parser = new nsParser();
5744 parser.forget(&sXMLFragmentParser);
5745 // sXMLFragmentParser now owns the parser
5746 }
5747 if (!sXMLFragmentSink) {
5748 NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
5749 // sXMLFragmentSink now owns the sink
5750 }
5751 nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
5752 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"
, 5752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink"
") (" "Sink doesn't QI to nsIContentSink!" ")"); do { *((volatile
int*)__null) = 5752; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5753 sXMLFragmentParser->SetContentSink(contentsink);
5754
5755 RefPtr<Document> doc;
5756 nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal();
5757
5758#ifdef DEBUG1
5759 // aFlags should always be -1 unless the caller of ParseFragmentXML
5760 // is ParserUtils::ParseFragment() which is the only caller that intends
5761 // sanitization. For all other callers we need to ensure to call
5762 // AuditParsingOfHTMLXMLFragments.
5763 if (aFlags < 0) {
5764 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
5765 aSourceBuffer);
5766 }
5767#endif
5768
5769 // We sanitize if the fragment occurs in a system privileged
5770 // context, an about: page, or if there are explicit sanitization flags.
5771 // Please note that about:blank and about:srcdoc inherit the security
5772 // context from the embedding context and hence are not loaded using
5773 // an about: scheme principal.
5774 bool shouldSanitize = nodePrincipal->IsSystemPrincipal() ||
5775 nodePrincipal->SchemeIs("about") || aFlags >= 0;
5776 if (shouldSanitize && !aDocument->IsLoadedAsData()) {
5777 doc = nsContentUtils::CreateInertXMLDocument(aDocument);
5778 } else {
5779 doc = aDocument;
5780 }
5781
5782 sXMLFragmentSink->SetTargetDocument(doc);
5783 sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
5784
5785 nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack);
5786 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5787 // Drop the fragment parser and sink that might be in an inconsistent state
5788 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
5789 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
5790 return rv;
5791 }
5792
5793 rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
5794
5795 sXMLFragmentParser->Reset();
5796 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"
, 5796); return rv; } } while (false)
;
5797
5798 if (shouldSanitize) {
5799 uint32_t sanitizationFlags =
5800 computeSanitizationFlags(nodePrincipal, aFlags);
5801 // Don't fire mutation events for nodes removed by the sanitizer.
5802 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
5803 nsTreeSanitizer sanitizer(sanitizationFlags);
5804 sanitizer.Sanitize(*aReturn);
5805 }
5806
5807 return rv;
5808}
5809
5810/* static */
5811nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
5812 nsAString& aResultBuffer,
5813 uint32_t aFlags,
5814 uint32_t aWrapCol) {
5815 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
5816 if (!document) {
5817 return NS_ERROR_FAILURE;
5818 }
5819
5820 nsresult rv = nsContentUtils::ParseDocumentHTML(
5821 aSourceBuffer, document,
5822 !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
5823 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"
, 5823); return rv; } } while (false)
;
5824
5825 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain");
5826
5827 rv = encoder->Init(document, u"text/plain"_ns, aFlags);
5828 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"
, 5828); return rv; } } while (false)
;
5829
5830 encoder->SetWrapColumn(aWrapCol);
5831
5832 return encoder->EncodeToString(aResultBuffer);
5833}
5834
5835static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate,
5836 DocumentFlavor aFlavor) {
5837 if (aTemplate) {
5838 bool hasHad = true;
5839 nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
5840 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"
, 5840); return nullptr; } } while (false)
;
5841
5842 nsCOMPtr<Document> doc;
5843 nsresult rv = NS_NewDOMDocument(
5844 getter_AddRefs(doc), u""_ns, u""_ns, nullptr,
5845 aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(),
5846 aTemplate->NodePrincipal(), true, sgo, aFlavor);
5847 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5848 return nullptr;
5849 }
5850 return doc.forget();
5851 }
5852 nsCOMPtr<nsIURI> uri;
5853 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
5854 if (!uri) {
5855 return nullptr;
5856 }
5857
5858 RefPtr<NullPrincipal> nullPrincipal =
5859 NullPrincipal::CreateWithoutOriginAttributes();
5860 if (!nullPrincipal) {
5861 return nullptr;
5862 }
5863
5864 nsCOMPtr<Document> doc;
5865 nsresult rv =
5866 NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri,
5867 nullPrincipal, true, nullptr, aFlavor);
5868 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5869 return nullptr;
5870 }
5871 return doc.forget();
5872}
5873
5874/* static */
5875already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument(
5876 const Document* aTemplate) {
5877 return CreateInertDocument(aTemplate, DocumentFlavorXML);
5878}
5879
5880/* static */
5881already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
5882 const Document* aTemplate) {
5883 return CreateInertDocument(aTemplate, DocumentFlavorHTML);
5884}
5885
5886/* static */
5887nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent,
5888 const nsAString& aValue,
5889 bool aTryReuse) {
5890 // Fire DOMNodeRemoved mutation events before we do anything else.
5891 nsCOMPtr<nsIContent> owningContent;
5892
5893 // Batch possible DOMSubtreeModified events.
5894 mozAutoSubtreeModified subtree(nullptr, nullptr);
5895
5896 // Scope firing mutation events so that we don't carry any state that
5897 // might be stale
5898 {
5899 // We're relying on mozAutoSubtreeModified to keep a strong reference if
5900 // needed.
5901 Document* doc = aContent->OwnerDoc();
5902
5903 // Optimize the common case of there being no observers
5904 if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04)) {
5905 subtree.UpdateTarget(doc, nullptr);
5906 owningContent = aContent;
5907 nsCOMPtr<nsINode> child;
5908 bool skipFirst = aTryReuse;
5909 for (child = aContent->GetFirstChild();
5910 child && child->GetParentNode() == aContent;
5911 child = child->GetNextSibling()) {
5912 if (skipFirst && child->IsText()) {
5913 skipFirst = false;
5914 continue;
5915 }
5916 nsContentUtils::MaybeFireNodeRemoved(child, aContent);
5917 }
5918 }
5919 }
5920
5921 // Might as well stick a batch around this since we're performing several
5922 // mutations.
5923 mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true);
5924 nsAutoMutationBatch mb;
5925
5926 if (aTryReuse && !aValue.IsEmpty()) {
5927 // Let's remove nodes until we find a eTEXT.
5928 while (aContent->HasChildren()) {
5929 nsIContent* child = aContent->GetFirstChild();
5930 if (child->IsText()) {
5931 break;
5932 }
5933 aContent->RemoveChildNode(child, true);
5934 }
5935
5936 // If we have a node, it must be a eTEXT and we reuse it.
5937 if (aContent->HasChildren()) {
5938 nsIContent* child = aContent->GetFirstChild();
5939 nsresult rv = child->AsText()->SetText(aValue, true);
5940 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"
, 5940); return rv; } } while (false)
;
5941
5942 // All the following nodes, if they exist, must be deleted.
5943 while (nsIContent* nextChild = child->GetNextSibling()) {
5944 aContent->RemoveChildNode(nextChild, true);
5945 }
5946 }
5947
5948 if (aContent->HasChildren()) {
5949 return NS_OK;
5950 }
5951 } else {
5952 mb.Init(aContent, true, false);
5953 while (aContent->HasChildren()) {
5954 aContent->RemoveChildNode(aContent->GetFirstChild(), true);
5955 }
5956 }
5957 mb.RemovalDone();
5958
5959 if (aValue.IsEmpty()) {
5960 return NS_OK;
5961 }
5962
5963 RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager())
5964 nsTextNode(aContent->NodeInfo()->NodeInfoManager());
5965
5966 textContent->SetText(aValue, true);
5967
5968 ErrorResult rv;
5969 aContent->AppendChildTo(textContent, true, rv);
5970 mb.NodesAdded();
5971 return rv.StealNSResult();
5972}
5973
5974static bool AppendNodeTextContentsRecurse(const nsINode* aNode,
5975 nsAString& aResult,
5976 const fallible_t& aFallible) {
5977 for (nsIContent* child = aNode->GetFirstChild(); child;
5978 child = child->GetNextSibling()) {
5979 if (child->IsElement()) {
5980 bool ok = AppendNodeTextContentsRecurse(child, aResult, aFallible);
5981 if (!ok) {
5982 return false;
5983 }
5984 } else if (Text* text = child->GetAsText()) {
5985 bool ok = text->AppendTextTo(aResult, aFallible);
5986 if (!ok) {
5987 return false;
5988 }
5989 }
5990 }
5991
5992 return true;
5993}
5994
5995/* static */
5996bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
5997 nsAString& aResult,
5998 const fallible_t& aFallible) {
5999 if (const Text* text = aNode->GetAsText()) {
6000 return text->AppendTextTo(aResult, aFallible);
6001 }
6002 if (aDeep) {
6003 return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
6004 }
6005
6006 for (nsIContent* child = aNode->GetFirstChild(); child;
6007 child = child->GetNextSibling()) {
6008 if (Text* text = child->GetAsText()) {
6009 bool ok = text->AppendTextTo(aResult, fallible);
6010 if (!ok) {
6011 return false;
6012 }
6013 }
6014 }
6015 return true;
6016}
6017
6018bool nsContentUtils::HasNonEmptyTextContent(
6019 nsINode* aNode, TextContentDiscoverMode aDiscoverMode) {
6020 for (nsIContent* child = aNode->GetFirstChild(); child;
6021 child = child->GetNextSibling()) {
6022 if (child->IsText() && child->TextLength() > 0) {
6023 return true;
6024 }
6025
6026 if (aDiscoverMode == eRecurseIntoChildren &&
6027 HasNonEmptyTextContent(child, aDiscoverMode)) {
6028 return true;
6029 }
6030 }
6031
6032 return false;
6033}
6034
6035/* static */
6036bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
6037 const nsINode* aOtherNode) {
6038 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"
, 6038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") ("
"Must have a node to work with" ")"); do { *((volatile int*)
__null) = 6038; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6039 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"
, 6039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode"
") (" "Must have a content to work with" ")"); do { *((volatile
int*)__null) = 6039; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6040
6041 const bool anon = aNode->IsInNativeAnonymousSubtree();
6042 if (anon != aOtherNode->IsInNativeAnonymousSubtree()) {
6043 return false;
6044 }
6045
6046 if (anon) {
6047 return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() ==
6048 aNode->GetClosestNativeAnonymousSubtreeRoot();
6049 }
6050
6051 // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
6052 // use to either. Maybe that's fine.
6053 return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow();
6054}
6055
6056/* static */
6057bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement,
6058 const Element* aStop) {
6059 const Element* element = aElement;
6060 while (element && element != aStop) {
6061 if (element->IsInteractiveHTMLContent()) {
6062 return true;
6063 }
6064 element = element->GetFlattenedTreeParentElement();
6065 }
6066 return false;
6067}
6068
6069/* static */
6070void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) {
6071 IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
6072}
6073
6074/* static */
6075bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) {
6076 nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
6077 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"
, 6077); return false; } } while (false)
;
6078 return baseURI->SchemeIs(aScheme);
6079}
6080
6081bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
6082 return aPrincipal && aPrincipal->GetIsExpandedPrincipal();
6083}
6084
6085bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) {
6086 return (aPrincipal && aPrincipal->IsSystemPrincipal()) ||
6087 IsExpandedPrincipal(aPrincipal);
6088}
6089
6090nsIPrincipal* nsContentUtils::GetSystemPrincipal() {
6091 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"
, 6091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 6091; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6092 return sSystemPrincipal;
6093}
6094
6095bool nsContentUtils::CombineResourcePrincipals(
6096 nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) {
6097 if (!aExtraPrincipal) {
6098 return false;
6099 }
6100 if (!*aResourcePrincipal) {
6101 *aResourcePrincipal = aExtraPrincipal;
6102 return true;
6103 }
6104 if (*aResourcePrincipal == aExtraPrincipal) {
6105 return false;
6106 }
6107 bool subsumes;
6108 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
6109 (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
&&
6110 subsumes) {
6111 return false;
6112 }
6113 *aResourcePrincipal = sSystemPrincipal;
6114 return true;
6115}
6116
6117/* static */
6118void nsContentUtils::TriggerLink(nsIContent* aContent, nsIURI* aLinkURI,
6119 const nsString& aTargetSpec, bool aClick,
6120 bool aIsTrusted) {
6121 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"
, 6121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") ("
"No link URI" ")"); do { *((volatile int*)__null) = 6121; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6122
6123 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
6124 return;
6125 }
6126
6127 nsCOMPtr<nsIDocShell> docShell = aContent->OwnerDoc()->GetDocShell();
6128 if (!docShell) {
6129 return;
6130 }
6131
6132 if (!aClick) {
6133 nsDocShell::Cast(docShell)->OnOverLink(aContent, aLinkURI, aTargetSpec);
6134 return;
6135 }
6136
6137 // Check that this page is allowed to load this URI.
6138 nsresult proceed = NS_OK;
6139
6140 if (sSecurityManager) {
6141 uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
6142 proceed = sSecurityManager->CheckLoadURIWithPrincipal(
6143 aContent->NodePrincipal(), aLinkURI, flag,
6144 aContent->OwnerDoc()->InnerWindowID());
6145 }
6146
6147 // Only pass off the click event if the script security manager says it's ok.
6148 // We need to rest aTargetSpec for forced downloads.
6149 if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) {
6150 // A link/area element with a download attribute is allowed to set
6151 // a pseudo Content-Disposition header.
6152 // For security reasons we only allow websites to declare same-origin
6153 // resources as downloadable. If this check fails we will just do the normal
6154 // thing (i.e. navigate to the resource).
6155 nsAutoString fileName;
6156 if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
6157 !aContent->IsHTMLElement(nsGkAtoms::area) &&
6158 !aContent->IsSVGElement(nsGkAtoms::a)) ||
6159 !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) ||
6160 NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal
()->CheckMayLoad(aLinkURI, true))), 0)))
) {
6161 fileName.SetIsVoid(true); // No actionable download attribute was found.
6162 }
6163
6164 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
6165 nsCOMPtr<nsIContentSecurityPolicy> csp = aContent->GetCsp();
6166
6167 // Sanitize fileNames containing null characters by replacing them with
6168 // underscores.
6169 if (!fileName.IsVoid()) {
6170 fileName.ReplaceChar(char16_t(0), '_');
6171 }
6172 nsDocShell::Cast(docShell)->OnLinkClick(
6173 aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName,
6174 nullptr, nullptr, UserActivation::IsHandlingUserInput(), aIsTrusted,
6175 triggeringPrincipal, csp);
6176 }
6177}
6178
6179/* static */
6180void nsContentUtils::GetLinkLocation(Element* aElement,
6181 nsString& aLocationString) {
6182 nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
6183 if (hrefURI) {
6184 nsAutoCString specUTF8;
6185 nsresult rv = hrefURI->GetSpec(specUTF8);
6186 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString);
6187 }
6188}
6189
6190/* static */
6191nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) {
6192 if (!aWidget) return nullptr;
6193
6194 return aWidget->GetTopLevelWidget();
6195}
6196
6197/* static */
6198const nsDependentString nsContentUtils::GetLocalizedEllipsis() {
6199 static char16_t sBuf[4] = {0, 0, 0, 0};
6200 if (!sBuf[0]) {
6201 if (!SpoofLocaleEnglish()) {
6202 nsAutoString tmp;
6203 Preferences::GetLocalizedString("intl.ellipsis", tmp);
6204 uint32_t len =
6205 std::min(uint32_t(tmp.Length()), uint32_t(ArrayLength(sBuf) - 1));
6206 CopyUnicodeTo(tmp, 0, sBuf, len);
6207 }
6208 if (!sBuf[0]) sBuf[0] = char16_t(0x2026);
6209 }
6210 return nsDependentString(sBuf);
6211}
6212
6213/* static */
6214void nsContentUtils::AddScriptBlocker() {
6215 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"
, 6215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6215; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6216 if (!sScriptBlockerCount) {
6217 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"
, 6218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { *((volatile
int*)__null) = 6218; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6218 "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"
, 6218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { *((volatile
int*)__null) = 6218; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6219 sRunnersCountAtFirstBlocker =
6220 sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
6221 }
6222 ++sScriptBlockerCount;
6223}
6224
6225#ifdef DEBUG1
6226static bool sRemovingScriptBlockers = false;
6227#endif
6228
6229/* static */
6230void nsContentUtils::RemoveScriptBlocker() {
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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6231; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6232 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"
, 6232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sRemovingScriptBlockers"
")"); do { *((volatile int*)__null) = 6232; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6233 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"
, 6233); MOZ_PretendNoReturn(); } } while (0)
;
6234 --sScriptBlockerCount;
6235 if (sScriptBlockerCount) {
6236 return;
6237 }
6238
6239 if (!sBlockedScriptRunners) {
6240 return;
6241 }
6242
6243 uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
6244 uint32_t lastBlocker = sBlockedScriptRunners->Length();
6245 uint32_t originalFirstBlocker = firstBlocker;
6246 uint32_t blockersCount = lastBlocker - firstBlocker;
6247 sRunnersCountAtFirstBlocker = 0;
6248 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"
, 6248); MOZ_PretendNoReturn(); } } while (0)
;
6249
6250 while (firstBlocker < lastBlocker) {
6251 nsCOMPtr<nsIRunnable> runnable;
6252 runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
6253 ++firstBlocker;
6254
6255 // Calling the runnable can reenter us
6256 {
6257 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_being_profiled_for_markers()) { raiiRunnableMarker
.emplace(runnable); }
;
6258 runnable->Run();
6259 }
6260 // So can dropping the reference to the runnable
6261 runnable = nullptr;
6262
6263 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"
, 6263); MOZ_PretendNoReturn(); } } while (0)
;
6264 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"
, 6264); MOZ_PretendNoReturn(); } } while (0)
;
6265 }
6266#ifdef DEBUG1
6267 AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
6268 sRemovingScriptBlockers = true;
6269#endif
6270 sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
6271}
6272
6273/* static */
6274already_AddRefed<nsPIDOMWindowOuter>
6275nsContentUtils::GetMostRecentNonPBWindow() {
6276 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
6277
6278 nsCOMPtr<mozIDOMWindowProxy> window;
6279 wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window));
6280 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
6281 pwindow = do_QueryInterface(window);
6282
6283 return pwindow.forget();
6284}
6285
6286/* static */
6287void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
6288 nsAutoString msg;
6289 bool privateBrowsing = false;
6290 bool chromeContext = false;
6291
6292 if (aDocument) {
6293 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
6294 if (uri) {
6295 msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
6296 msg.AppendLiteral(" : ");
6297 }
6298 privateBrowsing =
6299 aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
6300 chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal();
6301 }
6302
6303 msg.AppendLiteral(
6304 "Unable to run script because scripts are blocked internally.");
6305 LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext);
6306}
6307
6308/* static */
6309void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) {
6310 nsCOMPtr<nsIRunnable> runnable = aRunnable;
6311 if (!runnable) {
6312 return;
6313 }
6314
6315 if (sScriptBlockerCount) {
6316 sBlockedScriptRunners->AppendElement(runnable.forget());
6317 return;
6318 }
6319
6320 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_being_profiled_for_markers()) { raiiRunnableMarker
.emplace(runnable); }
;
6321 runnable->Run();
6322}
6323
6324/* static */
6325void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
6326 nsCOMPtr<nsIRunnable> runnable = aRunnable;
6327 AddScriptRunner(runnable.forget());
6328}
6329
6330/* static */ bool nsContentUtils::IsSafeToRunScript() {
6331 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"
, 6332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { *((volatile int*)__null) = 6332; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6332 "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"
, 6332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { *((volatile int*)__null) = 6332; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6333 return sScriptBlockerCount == 0;
6334}
6335
6336/* static */
6337void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) {
6338 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"
, 6338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6338; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6339 CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable));
6340}
6341
6342/* static */
6343void nsContentUtils::AddPendingIDBTransaction(
6344 already_AddRefed<nsIRunnable> aTransaction) {
6345 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"
, 6345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6345; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6346 CycleCollectedJSContext::Get()->AddPendingIDBTransaction(
6347 std::move(aTransaction));
6348}
6349
6350/* static */
6351bool nsContentUtils::IsInStableOrMetaStableState() {
6352 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"
, 6352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { *((volatile int
*)__null) = 6352; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6353 return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
6354}
6355
6356/* static */
6357void nsContentUtils::HidePopupsInDocument(Document* aDocument) {
6358 RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance();
6359 if (!pm || !aDocument) {
6360 return;
6361 }
6362 nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
6363 if (docShellToHide) {
6364 pm->HidePopupsInDocShell(docShellToHide);
6365 }
6366}
6367
6368/* static */
6369already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
6370 nsIWidget* aWidget) {
6371 nsCOMPtr<nsIDragSession> dragSession;
6372 nsCOMPtr<nsIDragService> dragService =
6373 do_GetService("@mozilla.org/widget/dragservice;1");
6374 if (dragService) {
6375 dragSession = dragService->GetCurrentSession(aWidget);
6376 }
6377 return dragSession.forget();
6378}
6379
6380/* static */
6381already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
6382 nsPresContext* aPC) {
6383 return GetDragSession(aPC->GetRootWidget());
6384}
6385
6386/* static */
6387nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) {
6388 if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
6389 return NS_OK;
6390 }
6391
6392 // For dragstart events, the data transfer object is
6393 // created before the event fires, so it should already be set. For other
6394 // drag events, get the object from the drag session.
6395 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"
, 6396); MOZ_PretendNoReturn(); } } while (0)
6396 "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"
, 6396); MOZ_PretendNoReturn(); } } while (0)
;
6397
6398 nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget);
6399 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"
, 6399); return NS_OK; } } while (false)
; // no drag in progress
6400
6401 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
6402 if (!initialDataTransfer) {
6403 // A dataTransfer won't exist when a drag was started by some other
6404 // means, for instance calling the drag service directly, or a drag
6405 // from another application. In either case, a new dataTransfer should
6406 // be created that reflects the data.
6407 initialDataTransfer =
6408 new DataTransfer(aDragEvent->mTarget, aDragEvent->mMessage, true, -1);
6409
6410 // now set it in the drag session so we don't need to create it again
6411 dragSession->SetDataTransfer(initialDataTransfer);
6412 }
6413
6414 bool isCrossDomainSubFrameDrop = false;
6415 if (aDragEvent->mMessage == eDrop) {
6416 isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
6417 }
6418
6419 // each event should use a clone of the original dataTransfer.
6420 initialDataTransfer->Clone(
6421 aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled,
6422 isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer));
6423 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"
, 6423)
) {
6424 return NS_ERROR_OUT_OF_MEMORY;
6425 }
6426
6427 // for the dragenter and dragover events, initialize the drop effect
6428 // from the drop action, which platform specific widget code sets before
6429 // the event is fired based on the keyboard state.
6430 if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
6431 uint32_t action;
6432 dragSession->GetDragAction(&action);
6433 uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt();
6434 aDragEvent->mDataTransfer->SetDropEffectInt(
6435 FilterDropEffect(action, effectAllowed));
6436 } else if (aDragEvent->mMessage == eDrop ||
6437 aDragEvent->mMessage == eDragEnd) {
6438 // For the drop and dragend events, set the drop effect based on the
6439 // last value that the dropEffect had. This will have been set in
6440 // EventStateManager::PostHandleEvent for the last dragenter or
6441 // dragover event.
6442 aDragEvent->mDataTransfer->SetDropEffectInt(
6443 initialDataTransfer->DropEffectInt());
6444 }
6445
6446 return NS_OK;
6447}
6448
6449/* static */
6450uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction,
6451 uint32_t aEffectAllowed) {
6452 // It is possible for the drag action to include more than one action, but
6453 // the widget code which sets the action from the keyboard state should only
6454 // be including one. If multiple actions were set, we just consider them in
6455 // the following order:
6456 // copy, link, move
6457 if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
6458 aAction = nsIDragService::DRAGDROP_ACTION_COPY;
6459 else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
6460 aAction = nsIDragService::DRAGDROP_ACTION_LINK;
6461 else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
6462 aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
6463
6464 // Filter the action based on the effectAllowed. If the effectAllowed
6465 // doesn't include the action, then that action cannot be done, so adjust
6466 // the action to something that is allowed. For a copy, adjust to move or
6467 // link. For a move, adjust to copy or link. For a link, adjust to move or
6468 // link. Otherwise, use none.
6469 if (aAction & aEffectAllowed ||
6470 aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
6471 return aAction;
6472 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
6473 return nsIDragService::DRAGDROP_ACTION_MOVE;
6474 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
6475 return nsIDragService::DRAGDROP_ACTION_COPY;
6476 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
6477 return nsIDragService::DRAGDROP_ACTION_LINK;
6478 return nsIDragService::DRAGDROP_ACTION_NONE;
6479}
6480
6481/* static */
6482bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
6483 WidgetDragEvent* aDropEvent) {
6484 nsCOMPtr<nsIContent> target =
6485 nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget);
6486 if (!target) {
6487 return true;
6488 }
6489
6490 // Always allow dropping onto chrome shells.
6491 BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext();
6492 if (targetBC->IsChrome()) {
6493 return false;
6494 }
6495
6496 WindowContext* targetWC = target->OwnerDoc()->GetWindowContext();
6497
6498 // If there is no source browsing context, then this is a drag from another
6499 // application, which should be allowed.
6500 RefPtr<WindowContext> sourceWC;
6501 aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
6502 if (sourceWC) {
6503 // Get each successive parent of the source document and compare it to
6504 // the drop document. If they match, then this is a drag from a child frame.
6505 for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC;
6506 sourceWC = sourceWC->GetParentWindowContext()) {
6507 // If the source and the target match, then the drag started in a
6508 // descendant frame. If the source is discarded, err on the side of
6509 // caution and treat it as a subframe drag.
6510 if (sourceWC == targetWC || sourceWC->IsDiscarded()) {
6511 return true;
6512 }
6513 }
6514 }
6515
6516 return false;
6517}
6518
6519/* static */
6520bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) {
6521 bool isFile;
6522 nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service();
6523
6524 // Important: we do NOT test the entire URI chain here!
6525 return util &&
6526 NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
6527 aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
&&
6528 isFile;
6529}
6530
6531/* static */
6532JSContext* nsContentUtils::GetCurrentJSContext() {
6533 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"
, 6533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 6533; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6534 if (!IsJSAPIActive()) {
6535 return nullptr;
6536 }
6537 return danger::GetJSContext();
6538}
6539
6540template <typename StringType, typename CharType>
6541void _ASCIIToLowerInSitu(StringType& aStr) {
6542 CharType* iter = aStr.BeginWriting();
6543 CharType* end = aStr.EndWriting();
6544 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"
, 6544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end"
")"); do { *((volatile int*)__null) = 6544; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6545
6546 while (iter != end) {
6547 CharType c = *iter;
6548 if (c >= 'A' && c <= 'Z') {
6549 *iter = c + ('a' - 'A');
6550 }
6551 ++iter;
6552 }
6553}
6554
6555/* static */
6556void nsContentUtils::ASCIIToLower(nsAString& aStr) {
6557 return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
6558}
6559
6560/* static */
6561void nsContentUtils::ASCIIToLower(nsACString& aStr) {
6562 return _ASCIIToLowerInSitu<nsACString, char>(aStr);
6563}
6564
6565template <typename StringType, typename CharType>
6566void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) {
6567 uint32_t len = aSource.Length();
6568 aDest.SetLength(len);
6569 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"
, 6569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len"
")"); do { *((volatile int*)__null) = 6569; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6570
6571 CharType* dest = aDest.BeginWriting();
6572 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"
, 6572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { *((volatile int*)__null) = 6572; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6573
6574 const CharType* iter = aSource.BeginReading();
6575 const CharType* end = aSource.EndReading();
6576 while (iter != end) {
6577 CharType c = *iter;
6578 *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
6579 ++iter;
6580 ++dest;
6581 }
6582}
6583
6584/* static */
6585void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
6586 return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
6587}
6588
6589/* static */
6590void nsContentUtils::ASCIIToLower(const nsACString& aSource,
6591 nsACString& aDest) {
6592 return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
6593}
6594
6595template <typename StringType, typename CharType>
6596void _ASCIIToUpperInSitu(StringType& aStr) {
6597 CharType* iter = aStr.BeginWriting();
6598 CharType* end = aStr.EndWriting();
6599 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"
, 6599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end"
")"); do { *((volatile int*)__null) = 6599; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6600
6601 while (iter != end) {
6602 CharType c = *iter;
6603 if (c >= 'a' && c <= 'z') {
6604 *iter = c + ('A' - 'a');
6605 }
6606 ++iter;
6607 }
6608}
6609
6610/* static */
6611void nsContentUtils::ASCIIToUpper(nsAString& aStr) {
6612 return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
6613}
6614
6615/* static */
6616void nsContentUtils::ASCIIToUpper(nsACString& aStr) {
6617 return _ASCIIToUpperInSitu<nsACString, char>(aStr);
6618}
6619
6620template <typename StringType, typename CharType>
6621void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) {
6622 uint32_t len = aSource.Length();
6623 aDest.SetLength(len);
6624 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"
, 6624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len"
")"); do { *((volatile int*)__null) = 6624; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6625
6626 CharType* dest = aDest.BeginWriting();
6627 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"
, 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { *((volatile int*)__null) = 6627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6628
6629 const CharType* iter = aSource.BeginReading();
6630 const CharType* end = aSource.EndReading();
6631 while (iter != end) {
6632 CharType c = *iter;
6633 *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c;
6634 ++iter;
6635 ++dest;
6636 }
6637}
6638
6639/* static */
6640void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) {
6641 return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
6642}
6643
6644/* static */
6645void nsContentUtils::ASCIIToUpper(const nsACString& aSource,
6646 nsACString& aDest) {
6647 return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
6648}
6649
6650/* static */
6651bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) {
6652 if (aAtom1 == aAtom2) {
6653 return true;
6654 }
6655
6656 // If both are ascii lowercase already, we know that the slow comparison
6657 // below is going to return false.
6658 if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) {
6659 return false;
6660 }
6661
6662 return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1),
6663 nsDependentAtomString(aAtom2));
6664}
6665
6666/* static */
6667bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
6668 const nsAString& aStr2) {
6669 uint32_t len = aStr1.Length();
6670 if (len != aStr2.Length()) {
6671 return false;
6672 }
6673
6674 const char16_t* str1 = aStr1.BeginReading();
6675 const char16_t* str2 = aStr2.BeginReading();
6676 const char16_t* end = str1 + len;
6677
6678 while (str1 < end) {
6679 char16_t c1 = *str1++;
6680 char16_t c2 = *str2++;
6681
6682 // First check if any bits other than the 0x0020 differs
6683 if ((c1 ^ c2) & 0xffdf) {
6684 return false;
6685 }
6686
6687 // We know they can only differ in the 0x0020 bit.
6688 // Likely the two chars are the same, so check that first
6689 if (c1 != c2) {
6690 // They do differ, but since it's only in the 0x0020 bit, check if it's
6691 // the same ascii char, but just differing in case
6692 char16_t c1Upper = c1 & 0xffdf;
6693 if (!('A' <= c1Upper && c1Upper <= 'Z')) {
6694 return false;
6695 }
6696 }
6697 }
6698
6699 return true;
6700}
6701
6702/* static */
6703bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) {
6704 const char16_t* iter = aStr.BeginReading();
6705 const char16_t* end = aStr.EndReading();
6706 while (iter != end) {
6707 char16_t c = *iter;
6708 if (c >= 'A' && c <= 'Z') {
6709 return true;
6710 }
6711 ++iter;
6712 }
6713
6714 return false;
6715}
6716
6717/* static */
6718nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() {
6719 if (!sSameOriginChecker) {
6720 sSameOriginChecker = new SameOriginCheckerImpl();
6721 NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef();
6722 }
6723 return sSameOriginChecker;
6724}
6725
6726/* static */
6727nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel,
6728 nsIChannel* aNewChannel) {
6729 if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE;
6730
6731 nsCOMPtr<nsIPrincipal> oldPrincipal;
6732 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
6733 aOldChannel, getter_AddRefs(oldPrincipal));
6734
6735 nsCOMPtr<nsIURI> newURI;
6736 aNewChannel->GetURI(getter_AddRefs(newURI));
6737 nsCOMPtr<nsIURI> newOriginalURI;
6738 aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
6739
6740 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"
, 6740); return NS_ERROR_UNEXPECTED; } } while (false)
;
6741
6742 nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
6743 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) {
6744 rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
6745 }
6746
6747 return rv;
6748}
6749
6750NS_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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
6751; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6751; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 6751
; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6751; __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"
, 6751); 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((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
6751 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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
6751; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6751; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 6751
; __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"
, 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 6751; __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"
, 6751); 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((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
6752
6753NS_IMETHODIMPnsresult
6754SameOriginCheckerImpl::AsyncOnChannelRedirect(
6755 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
6756 nsIAsyncVerifyRedirectCallback* cb) {
6757 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"
, 6757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel"
") (" "Redirecting to null channel?" ")"); do { *((volatile int
*)__null) = 6757; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6758
6759 nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
6760 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6761 cb->OnRedirectVerifyCallback(NS_OK);
6762 }
6763
6764 return rv;
6765}
6766
6767NS_IMETHODIMPnsresult
6768SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) {
6769 return QueryInterface(aIID, aResult);
6770}
6771
6772/* static */
6773nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
6774 nsACString& aOrigin) {
6775 nsresult rv;
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
6778 // For Blob URI, the path is the URL of the owning page.
6779 if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) {
6780 nsAutoCString path;
6781 rv = aURI->GetPathQueryRef(path);
6782 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"
, 6782); return rv; } } while (false)
;
6783
6784 nsCOMPtr<nsIURI> uri;
6785 rv = NS_NewURI(getter_AddRefs(uri), path);
6786 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6787 aOrigin.AssignLiteral("null");
6788 return NS_OK;
6789 }
6790
6791 if (
6792 // Schemes in spec. https://url.spec.whatwg.org/#origin
6793 !uri->SchemeIs("http") && !uri->SchemeIs("https") &&
6794 !uri->SchemeIs("file") && !uri->SchemeIs("resource") &&
6795 // Our own schemes.
6796 !uri->SchemeIs("moz-extension")) {
6797 aOrigin.AssignLiteral("null");
6798 return NS_OK;
6799 }
6800
6801 return GetWebExposedOriginSerialization(uri, aOrigin);
6802 }
6803
6804 nsAutoCString scheme;
6805 aURI->GetScheme(scheme);
6806
6807 // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then
6808 // return "null" as the origin serialization.
6809 // We make an exception for "ftp" since we don't have a protocol handler
6810 // for this scheme
6811 uint32_t flags = 0;
6812 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
6813 if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
6814 NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
6815 if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) {
6816 aOrigin.AssignLiteral("null");
6817 return NS_OK;
6818 }
6819 }
6820
6821 aOrigin.Truncate();
6822
6823 nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
6824 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"
, 6824); return NS_ERROR_UNEXPECTED; } } while (false)
;
6825
6826 nsAutoCString host;
6827 rv = uri->GetAsciiHost(host);
6828
6829 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) {
6830 nsAutoCString userPass;
6831 uri->GetUserPass(userPass);
6832
6833 nsAutoCString prePath;
6834 if (!userPass.IsEmpty()) {
6835 rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri);
6836 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"
, 6836); return rv; } } while (false)
;
6837 }
6838
6839 rv = uri->GetPrePath(prePath);
6840 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"
, 6840); return rv; } } while (false)
;
6841
6842 aOrigin = prePath;
6843 } else {
6844 aOrigin.AssignLiteral("null");
6845 }
6846
6847 return NS_OK;
6848}
6849
6850/* static */
6851nsresult nsContentUtils::GetWebExposedOriginSerialization(
6852 nsIPrincipal* aPrincipal, nsAString& aOrigin) {
6853 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"
, 6853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
") (" "missing principal" ")"); do { *((volatile int*)__null
) = 6853; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
6854
6855 aOrigin.Truncate();
6856 nsAutoCString webExposedOriginSerialization;
6857
6858 nsresult rv = aPrincipal->GetWebExposedOriginSerialization(
6859 webExposedOriginSerialization);
6860 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6861 webExposedOriginSerialization.AssignLiteral("null");
6862 }
6863
6864 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
6865 return NS_OK;
6866}
6867
6868/* static */
6869nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
6870 nsAString& aOrigin) {
6871 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"
, 6871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { *((volatile int*)__null) = 6871; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6872 nsresult rv;
6873
6874#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
6875 // Check if either URI has a special origin.
6876 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
6877 do_QueryInterface(aURI);
6878 if (uriWithSpecialOrigin) {
6879 nsCOMPtr<nsIURI> origin;
6880 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
6881 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"
, 6881); return rv; } } while (false)
;
6882
6883 return GetWebExposedOriginSerialization(origin, aOrigin);
6884 }
6885#endif
6886
6887 nsAutoCString webExposedOriginSerialization;
6888 rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization);
6889 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"
, 6889); return rv; } } while (false)
;
6890
6891 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
6892 return NS_OK;
6893}
6894
6895/* static */
6896bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
6897 nsIChannel* aChannel,
6898 bool aAllowIfInheritsPrincipal) {
6899 nsCOMPtr<nsIURI> channelURI;
6900 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
6901 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"
, 6901); return false; } } while (false)
;
6902
6903 return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
6904 aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
;
6905}
6906
6907/* static */
6908bool nsContentUtils::CanAccessNativeAnon() {
6909 return LegacyIsCallerChromeOrNativeCode();
6910}
6911
6912/* static */
6913nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted,
6914 Event* aSourceEvent,
6915 PresShell* aPresShell, bool aCtrl,
6916 bool aAlt, bool aShift, bool aMeta,
6917 uint16_t aInputSource,
6918 int16_t aButton) {
6919 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"
, 6919); return NS_ERROR_UNEXPECTED; } } while (false)
;
6920 Document* doc = aTarget->OwnerDoc();
6921 nsPresContext* presContext = doc->GetPresContext();
6922
6923 RefPtr<XULCommandEvent> xulCommand =
6924 new XULCommandEvent(doc, presContext, nullptr);
6925 xulCommand->InitCommandEvent(u"command"_ns, true, true,
6926 nsGlobalWindowInner::Cast(doc->GetInnerWindow()),
6927 0, aCtrl, aAlt, aShift, aMeta, aButton,
6928 aSourceEvent, aInputSource, IgnoreErrors());
6929
6930 if (aPresShell) {
6931 nsEventStatus status = nsEventStatus_eIgnore;
6932 return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
6933 }
6934
6935 ErrorResult rv;
6936 aTarget->DispatchEvent(*xulCommand, rv);
6937 return rv.StealNSResult();
6938}
6939
6940// static
6941nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native,
6942 nsWrapperCache* cache, const nsIID* aIID,
6943 JS::MutableHandle<JS::Value> vp,
6944 bool aAllowWrapping) {
6945 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"
, 6945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()"
")"); do { *((volatile int*)__null) = 6945; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6946
6947 if (!native) {
6948 vp.setNull();
6949
6950 return NS_OK;
6951 }
6952
6953 JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
6954 if (wrapper) {
6955 return NS_OK;
6956 }
6957
6958 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"
, 6958); return NS_ERROR_UNEXPECTED; } } while (false)
;
6959
6960 if (!NS_IsMainThread()) {
6961 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 6961); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 6961; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
6962 }
6963
6964 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
6965 nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
6966 aAllowWrapping, vp);
6967 return rv;
6968}
6969
6970void nsContentUtils::StripNullChars(const nsAString& aInStr,
6971 nsAString& aOutStr) {
6972 // In common cases where we don't have nulls in the
6973 // string we can simple simply bypass the checking code.
6974 int32_t firstNullPos = aInStr.FindChar('\0');
6975 if (firstNullPos == kNotFound) {
6976 aOutStr.Assign(aInStr);
6977 return;
6978 }
6979
6980 aOutStr.SetCapacity(aInStr.Length() - 1);
6981 nsAString::const_iterator start, end;
6982 aInStr.BeginReading(start);
6983 aInStr.EndReading(end);
6984 while (start != end) {
6985 if (*start != '\0') aOutStr.Append(*start);
6986 ++start;
6987 }
6988}
6989
6990struct ClassMatchingInfo {
6991 AtomArray mClasses;
6992 nsCaseTreatment mCaseTreatment;
6993};
6994
6995// static
6996bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
6997 nsAtom* aAtom, void* aData) {
6998 // We can't match if there are no class names
6999 const nsAttrValue* classAttr = aElement->GetClasses();
7000 if (!classAttr) {
7001 return false;
7002 }
7003
7004 // need to match *all* of the classes
7005 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
7006 uint32_t length = info->mClasses.Length();
7007 if (!length) {
7008 // If we actually had no classes, don't match.
7009 return false;
7010 }
7011 uint32_t i;
7012 for (i = 0; i < length; ++i) {
7013 if (!classAttr->Contains(info->mClasses[i], info->mCaseTreatment)) {
7014 return false;
7015 }
7016 }
7017
7018 return true;
7019}
7020
7021// static
7022void nsContentUtils::DestroyClassNameArray(void* aData) {
7023 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
7024 delete info;
7025}
7026
7027// static
7028void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
7029 const nsString* aClasses) {
7030 nsAttrValue attrValue;
7031 attrValue.ParseAtomArray(*aClasses);
7032 // nsAttrValue::Equals is sensitive to order, so we'll send an array
7033 auto* info = new ClassMatchingInfo;
7034 if (attrValue.Type() == nsAttrValue::eAtomArray) {
7035 info->mClasses = attrValue.GetAtomArrayValue()->mArray.Clone();
7036 } else if (attrValue.Type() == nsAttrValue::eAtom) {
7037 info->mClasses.AppendElement(attrValue.GetAtomValue());
7038 }
7039
7040 info->mCaseTreatment =
7041 aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
7042 ? eIgnoreCase
7043 : eCaseMatters;
7044 return info;
7045}
7046
7047// static
7048bool nsContentUtils::IsFocusedContent(const nsIContent* aContent) {
7049 nsFocusManager* fm = nsFocusManager::GetFocusManager();
7050
7051 return fm && fm->GetFocusedElement() == aContent;
7052}
7053
7054bool nsContentUtils::HasScrollgrab(nsIContent* aContent) {
7055 // If we ever standardize this feature we'll want to hook this up properly
7056 // again. For now we're removing all the DOM-side code related to it but
7057 // leaving the layout and APZ handling for it in place.
7058 return false;
7059}
7060
7061void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
7062 if (!aWindow) {
7063 return;
7064 }
7065
7066 // Note that because FlushPendingNotifications flushes parents, this
7067 // is O(N^2) in docshell tree depth. However, the docshell tree is
7068 // usually pretty shallow.
7069
7070 if (RefPtr<Document> doc = aWindow->GetDoc()) {
7071 doc->FlushPendingNotifications(FlushType::Layout);
7072 }
7073
7074 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
7075 int32_t i = 0, i_end;
7076 docShell->GetInProcessChildCount(&i_end);
7077 for (; i < i_end; ++i) {
7078 nsCOMPtr<nsIDocShellTreeItem> item;
7079 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
7080 item) {
7081 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
7082 FlushLayoutForTree(win);
7083 }
7084 }
7085 }
7086 }
7087}
7088
7089void nsContentUtils::RemoveNewlines(nsString& aString) { aString.StripCRLF(); }
7090
7091void nsContentUtils::PlatformToDOMLineBreaks(nsString& aString) {
7092 if (!PlatformToDOMLineBreaks(aString, fallible)) {
7093 aString.AllocFailed(aString.Length());
7094 }
7095}
7096
7097bool nsContentUtils::PlatformToDOMLineBreaks(nsString& aString,
7098 const fallible_t& aFallible) {
7099 if (aString.FindChar(char16_t('\r')) != -1) {
7100 // Windows linebreaks: Map CRLF to LF:
7101 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
7102 return false;
7103 }
7104
7105 // Mac linebreaks: Map any remaining CR to LF:
7106 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
7107 return false;
7108 }
7109 }
7110
7111 return true;
7112}
7113
7114already_AddRefed<nsContentList> nsContentUtils::GetElementsByClassName(
7115 nsINode* aRootNode, const nsAString& aClasses) {
7116 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"
, 7116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") ("
"Must have root node" ")"); do { *((volatile int*)__null) = 7116
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7117
7118 return GetFuncStringContentList<nsCacheableFuncStringHTMLCollection>(
7119 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
7120 aClasses);
7121}
7122
7123PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
7124 const Document* doc = aDocument;
7125 Document* displayDoc = doc->GetDisplayDocument();
7126 if (displayDoc) {
7127 doc = displayDoc;
7128 }
7129
7130 PresShell* presShell = doc->GetPresShell();
7131 if (presShell) {
7132 return presShell;
7133 }
7134
7135 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
7136 while (docShellTreeItem) {
7137 // We may be in a display:none subdocument, or we may not have a presshell
7138 // created yet.
7139 // Walk the docshell tree to find the nearest container that has a
7140 // presshell, and return that.
7141 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
7142 if (PresShell* presShell = docShell->GetPresShell()) {
7143 return presShell;
7144 }
7145 nsCOMPtr<nsIDocShellTreeItem> parent;
7146 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
7147 docShellTreeItem = parent;
7148 }
7149
7150 return nullptr;
7151}
7152
7153/* static */
7154nsPresContext* nsContentUtils::FindPresContextForDocument(
7155 const Document* aDocument) {
7156 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
7157 return presShell->GetPresContext();
7158 }
7159 return nullptr;
7160}
7161
7162nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
7163 PresShell* presShell = FindPresShellForDocument(aDocument);
7164 if (!presShell) {
7165 return nullptr;
7166 }
7167 nsViewManager* vm = presShell->GetViewManager();
7168 if (!vm) {
7169 return nullptr;
7170 }
7171 nsView* rootView = vm->GetRootView();
7172 if (!rootView) {
7173 return nullptr;
7174 }
7175 nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView);
7176 if (!displayRoot) {
7177 return nullptr;
7178 }
7179 return displayRoot->GetNearestWidget(nullptr);
7180}
7181
7182nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
7183 nsIFrame* frame = aContent->GetPrimaryFrame();
7184 if (frame) {
7185 frame = nsLayoutUtils::GetDisplayRootFrame(frame);
7186
7187 nsView* view = frame->GetView();
7188 if (view) {
7189 return view->GetWidget();
7190 }
7191 }
7192
7193 return nullptr;
7194}
7195
7196WindowRenderer* nsContentUtils::WindowRendererForContent(
7197 const nsIContent* aContent) {
7198 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
7199 if (widget) {
7200 return widget->GetWindowRenderer();
7201 }
7202
7203 return nullptr;
7204}
7205
7206WindowRenderer* nsContentUtils::WindowRendererForDocument(
7207 const Document* aDoc) {
7208 nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc);
7209 if (widget) {
7210 return widget->GetWindowRenderer();
7211 }
7212
7213 return nullptr;
7214}
7215
7216bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
7217 if (!aPrincipal) {
7218 return false;
7219 }
7220
7221 if (aPrincipal->IsSystemPrincipal()) {
7222 return true;
7223 }
7224
7225 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
7226}
7227
7228bool nsContentUtils::IsPDFJSEnabled() {
7229 nsCOMPtr<nsIStreamConverter> conv = do_CreateInstance(
7230 "@mozilla.org/streamconv;1?from=application/pdf&to=text/html");
7231 return conv;
7232}
7233
7234bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
7235 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
7236 return false;
7237 }
7238 nsAutoCString spec;
7239 nsresult rv = aPrincipal->GetAsciiSpec(spec);
7240 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"
, 7240); return false; } } while (false)
;
7241 return spec.EqualsLiteral("resource://pdf.js/web/viewer.html");
7242}
7243
7244bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
7245 nsIPrincipal* principal = SubjectPrincipal(aCx);
7246 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
7247}
7248
7249bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
7250 JSObject* aGlobal) {
7251 nsIPrincipal* principal = SubjectPrincipal(aCx);
7252 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
7253 aGlobal) ||
7254 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
7255}
7256
7257already_AddRefed<nsIDocumentLoaderFactory>
7258nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
7259 DocumentViewerType* aLoaderType) {
7260 if (aLoaderType) {
7261 *aLoaderType = TYPE_UNSUPPORTED;
7262 }
7263
7264 // one helper factory, please
7265 nsCOMPtr<nsICategoryManager> catMan(
7266 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
7267 if (!catMan) return nullptr;
7268
7269 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
7270
7271 nsCString contractID;
7272 nsresult rv =
7273 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
7274 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7275 docFactory = do_GetService(contractID.get());
7276 if (docFactory && aLoaderType) {
7277 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
7278 *aLoaderType = TYPE_CONTENT;
7279 else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID"@mozilla.org/content/plugin/document-loader-factory;1"))
7280 *aLoaderType = TYPE_FALLBACK;
7281 else
7282 *aLoaderType = TYPE_UNKNOWN;
7283 }
7284 return docFactory.forget();
7285 }
7286
7287 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
7288 // another type which we may dynamically support, such as `text/*` types or
7289 // video document types. These types are all backed by the nsContentDLF.
7290 if (IsPlainTextType(aType) ||
7291 DecoderTraits::IsSupportedInVideoDocument(aType)) {
7292 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
7293 if (docFactory && aLoaderType) {
7294 *aLoaderType = TYPE_CONTENT;
7295 }
7296 return docFactory.forget();
7297 }
7298
7299 return nullptr;
7300}
7301
7302static void ReportPatternCompileFailure(nsAString& aPattern,
7303 const JS::RegExpFlags& aFlags,
7304 const Document* aDocument,
7305 JS::MutableHandle<JS::Value> error,
7306 JSContext* cx) {
7307 AutoTArray<nsString, 3> strings;
7308
7309 strings.AppendElement(aPattern);
7310
7311 std::stringstream flag_ss;
7312 flag_ss << aFlags;
7313 nsString* flagstr = strings.AppendElement();
7314 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
7315
7316 JS::AutoSaveExceptionState savedExc(cx);
7317 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
7318 JS::Rooted<JS::Value> messageVal(cx);
7319 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
7320 return;
7321 }
7322 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
7323 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"
, 7323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { *((volatile int*)__null) = 7323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7324 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
7325 return;
7326 }
7327
7328 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
7329 aDocument, nsContentUtils::eDOM_PROPERTIES,
7330 "PatternAttributeCompileFailurev2", strings);
7331 savedExc.drop();
7332}
7333
7334// static
7335Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
7336 nsString&& aPattern,
7337 const Document* aDocument,
7338 bool aHasMultiple,
7339 JS::RegExpFlags aFlags) {
7340 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"
, 7340); MOZ_PretendNoReturn(); } } while (0)
;
7341
7342 // The fact that we're using a JS regexp under the hood should not be visible
7343 // to things like window onerror handlers, so we don't initialize our JSAPI
7344 // with the document's window (which may not exist anyway).
7345 AutoJSAPI jsapi;
7346 jsapi.Init();
7347 JSContext* cx = jsapi.cx();
7348 AutoDisableJSInterruptCallback disabler(cx);
7349
7350 // We can use the junk scope here, because we're just using it for regexp
7351 // evaluation, not actual script execution, and we disable statics so that the
7352 // evaluation does not interact with the execution global.
7353 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
7354
7355 // Check if the pattern by itself is valid first, and not that it only becomes
7356 // valid once we add ^(?: and )$.
7357 JS::Rooted<JS::Value> error(cx);
7358 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
7359 aFlags, &error)) {
7360 return Nothing();
7361 }
7362
7363 if (!error.isUndefined()) {
7364 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
7365 return Some(true);
7366 }
7367
7368 // The pattern has to match the entire value.
7369 aPattern.InsertLiteral(u"^(?:", 0);
7370 aPattern.AppendLiteral(")$");
7371
7372 JS::Rooted<JSObject*> re(
7373 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
7374 aFlags));
7375 if (!re) {
7376 return Nothing();
7377 }
7378
7379 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
7380 if (!aHasMultiple) {
7381 size_t idx = 0;
7382 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
7383 aValue.Length(), &idx, true, &rval)) {
7384 return Nothing();
7385 }
7386 return Some(!rval.isNull());
7387 }
7388
7389 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
7390 while (tokenizer.hasMoreTokens()) {
7391 const nsAString& value = tokenizer.nextToken();
7392 size_t idx = 0;
7393 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
7394 value.Length(), &idx, true, &rval)) {
7395 return Nothing();
7396 }
7397 if (rval.isNull()) {
7398 return Some(false);
7399 }
7400 }
7401 return Some(true);
7402}
7403
7404// static
7405nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
7406 bool* aResult) {
7407 // Note: about:blank URIs do NOT inherit the security context from the
7408 // current document, which is what this function tests for...
7409 return NS_URIChainHasFlags(
7410 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
7411}
7412
7413// static
7414bool nsContentUtils::ChannelShouldInheritPrincipal(
7415 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
7416 bool aForceInherit) {
7417 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"
, 7418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7418; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7418 "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"
, 7418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7418; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7419
7420 // Only tell the channel to inherit if it can't provide its own security
7421 // context.
7422 //
7423 // XXX: If this is ever changed, check all callers for what owners
7424 // they're passing in. In particular, see the code and
7425 // comments in nsDocShell::LoadURI where we fall back on
7426 // inheriting the owner if called from chrome. That would be
7427 // very wrong if this code changed anything but channels that
7428 // can't provide their own security context!
7429 //
7430 // If aForceInherit is true, we will inherit, even for a channel that
7431 // can provide its own security context. This is used for srcdoc loads.
7432 bool inherit = aForceInherit;
7433 if (!inherit) {
7434 bool uriInherits;
7435 // We expect URIInheritsSecurityContext to return success for an
7436 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
7437 // This condition needs to match the one in nsDocShell::InternalLoad where
7438 // we're checking for things that will use the owner.
7439 inherit =
7440 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
7441 (uriInherits || (aInheritForAboutBlank &&
7442 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
7443 //
7444 // file: uri special-casing
7445 //
7446 // If this is a file: load opened from another file: then it may need
7447 // to inherit the owner from the referrer so they can script each other.
7448 // If we don't set the owner explicitly then each file: gets an owner
7449 // based on its own codebase later.
7450 //
7451 (URIIsLocalFile(aURI) &&
7452 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
7453 // One more check here. CheckMayLoad will always return true for the
7454 // system principal, but we do NOT want to inherit in that case.
7455 !aLoadingPrincipal->IsSystemPrincipal());
7456 }
7457 return inherit;
7458}
7459
7460/* static */
7461bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
7462 nsIPrincipal& aSubjectPrincipal) {
7463 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
7464 aDocument->HasValidTransientUserGestureActivation()) {
7465 return true;
7466 }
7467
7468 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
7469}
7470
7471/* static */
7472bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
7473 if (!aDoc1 || !aDoc2) {
7474 return false;
7475 }
7476 bool principalsEqual = false;
7477 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
7478 return principalsEqual;
7479}
7480
7481/* static */
7482void nsContentUtils::FireMutationEventsForDirectParsing(
7483 Document* aDoc, nsIContent* aDest, int32_t aOldChildCount) {
7484 // Fire mutation events. Optimize for the case when there are no listeners
7485 int32_t newChildCount = aDest->GetChildCount();
7486 if (newChildCount && nsContentUtils::HasMutationListeners(
7487 aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED0x02)) {
7488 AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
7489 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"
, 7490); MOZ_PretendNoReturn(); } } while (0)
7490 "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"
, 7490); MOZ_PretendNoReturn(); } } while (0)
;
7491 childNodes.SetCapacity(newChildCount - aOldChildCount);
7492 for (nsIContent* child = aDest->GetFirstChild(); child;
7493 child = child->GetNextSibling()) {
7494 childNodes.AppendElement(child);
7495 }
7496 FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes);
7497 }
7498}
7499
7500/* static */
7501const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
7502 const Document* aDoc) {
7503 if (!aDoc) {
7504 return nullptr;
7505 }
7506 const Document* doc = aDoc;
7507 while (doc->GetInProcessParentDocument()) {
7508 doc = doc->GetInProcessParentDocument();
7509 }
7510 return doc;
7511}
7512
7513// static
7514int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
7515 int32_t aOffset) {
7516 // The structure of the anonymous frames within a text control frame is
7517 // an optional block frame, followed by an optional br frame.
7518
7519 // If the offset frame has a child, then this frame is the block which
7520 // has the text frames (containing the content) as its children. This will
7521 // be the case if we click to the right of any of the text frames, or at the
7522 // bottom of the text area.
7523 nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
7524 if (firstChild) {
7525 // In this case, the passed-in offset is incorrect, and we want the length
7526 // of the entire content in the text control frame.
7527 return firstChild->GetContent()->Length();
7528 }
7529
7530 if (aOffsetFrame->GetPrevSibling() && !aOffsetFrame->GetNextSibling()) {
7531 // In this case, we're actually within the last frame, which is a br
7532 // frame. Our offset should therefore be the length of the first child of
7533 // our parent.
7534 int32_t aOutOffset = aOffsetFrame->GetParent()
7535 ->PrincipalChildList()
7536 .FirstChild()
7537 ->GetContent()
7538 ->Length();
7539 return aOutOffset;
7540 }
7541
7542 // Otherwise, we're within one of the text frames, in which case our offset
7543 // has already been correctly calculated.
7544 return aOffset;
7545}
7546
7547// static
7548bool nsContentUtils::IsPointInSelection(
7549 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
7550 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
7551 const bool selectionIsCollapsed =
7552 !aAllowCrossShadowBoundary
7553 ? aSelection.IsCollapsed()
7554 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
7555 if (selectionIsCollapsed) {
7556 return false;
7557 }
7558
7559 const uint32_t rangeCount = aSelection.RangeCount();
7560 for (const uint32_t i : IntegerRange(rangeCount)) {
7561 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"
, 7561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount"
")"); do { *((volatile int*)__null) = 7561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7562 RefPtr<const nsRange> range = aSelection.GetRangeAt(i);
7563 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7563)
) {
7564 // Don't bail yet, iterate through them all
7565 continue;
7566 }
7567
7568 // Done when we find a range that we are in
7569 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
7570 aAllowCrossShadowBoundary)) {
7571 return true;
7572 }
7573 }
7574
7575 return false;
7576}
7577
7578// static
7579void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
7580 Element* aRoot,
7581 uint32_t& aOutStartOffset,
7582 uint32_t& aOutEndOffset) {
7583 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"
, 7583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection && aRoot"
")"); do { *((volatile int*)__null) = 7583; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7584
7585 // We don't care which end of this selection is anchor and which is focus. In
7586 // fact, we explicitly want to know which is the _start_ and which is the
7587 // _end_, not anchor vs focus.
7588 const nsRange* range = aSelection->GetAnchorFocusRange();
7589 if (!range) {
7590 // Nothing selected
7591 aOutStartOffset = aOutEndOffset = 0;
7592 return;
7593 }
7594
7595 // All the node pointers here are raw pointers for performance. We shouldn't
7596 // be doing anything in this function that invalidates the node tree.
7597 nsINode* startContainer = range->GetStartContainer();
7598 uint32_t startOffset = range->StartOffset();
7599 nsINode* endContainer = range->GetEndContainer();
7600 uint32_t endOffset = range->EndOffset();
7601
7602 // We have at most two children, consisting of an optional text node followed
7603 // by an optional <br>.
7604 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"
, 7604); MOZ_PretendNoReturn(); } } while (0)
;
7605 nsIContent* firstChild = aRoot->GetFirstChild();
7606#ifdef DEBUG1
7607 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
7608 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"
, 7610); MOZ_PretendNoReturn(); } } while (0)
7609 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"
, 7610); MOZ_PretendNoReturn(); } } while (0)
7610 "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"
, 7610); MOZ_PretendNoReturn(); } } while (0)
;
7611 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"
, 7613); MOZ_PretendNoReturn(); } } while (0)
7612 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"
, 7613); MOZ_PretendNoReturn(); } } while (0)
7613 "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"
, 7613); MOZ_PretendNoReturn(); } } while (0)
;
7614 // firstChild is either text or a <br> (hence an element).
7615 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"
, 7615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { *((volatile int*)__null) = 7615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7616#endif
7617 if (!firstChild || firstChild->IsElement()) {
7618 // No text node, so everything is 0
7619 startOffset = endOffset = 0;
7620 } else {
7621 // First child is text. If the start/end is already in the text node,
7622 // or the start of the root node, no change needed. If it's in the root
7623 // node but not the start, or in the trailing <br>, we need to set the
7624 // offset to the end.
7625 if ((startContainer == aRoot && startOffset != 0) ||
7626 (startContainer != aRoot && startContainer != firstChild)) {
7627 startOffset = firstChild->Length();
7628 }
7629 if ((endContainer == aRoot && endOffset != 0) ||
7630 (endContainer != aRoot && endContainer != firstChild)) {
7631 endOffset = firstChild->Length();
7632 }
7633 }
7634
7635 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"
, 7635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startOffset <= endOffset"
")"); do { *((volatile int*)__null) = 7635; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7636 aOutStartOffset = startOffset;
7637 aOutEndOffset = endOffset;
7638}
7639
7640// static
7641HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
7642 if (!aPresContext) {
7643 return nullptr;
7644 }
7645 return GetHTMLEditor(aPresContext->GetDocShell());
7646}
7647
7648// static
7649HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
7650 bool isEditable;
7651 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
7652 !isEditable) {
7653 return nullptr;
7654 }
7655 return aDocShell->GetHTMLEditor();
7656}
7657
7658// static
7659EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
7660 if (!aPresContext) {
7661 return nullptr;
7662 }
7663
7664 return GetActiveEditor(aPresContext->Document()->GetWindow());
7665}
7666
7667// static
7668EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
7669 if (!aWindow || !aWindow->GetExtantDoc()) {
7670 return nullptr;
7671 }
7672
7673 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
7674 // handles all events. I.e., it's focused editor in this case.
7675 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
7676 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7677 }
7678
7679 // If focused element is associated with TextEditor, it must be <input>
7680 // element or <textarea> element. Let's return it even if it's in a
7681 // contenteditable element.
7682 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
7683 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
7684 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
7685 getter_AddRefs(focusedWindow))) {
7686 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
7687 return textEditor;
7688 }
7689 }
7690
7691 // Otherwise, HTMLEditor may handle inputs even non-editable element has
7692 // focus or nobody has focus.
7693 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7694}
7695
7696// static
7697TextEditor* nsContentUtils::GetTextEditorFromAnonymousNodeWithoutCreation(
7698 const nsIContent* aAnonymousContent) {
7699 if (!aAnonymousContent) {
7700 return nullptr;
7701 }
7702 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
7703 if (!parent || parent == aAnonymousContent) {
7704 return nullptr;
7705 }
7706 if (HTMLInputElement* inputElement =
7707 HTMLInputElement::FromNodeOrNull(parent)) {
7708 return inputElement->GetTextEditorWithoutCreation();
7709 }
7710 if (HTMLTextAreaElement* textareaElement =
7711 HTMLTextAreaElement::FromNodeOrNull(parent)) {
7712 return textareaElement->GetTextEditorWithoutCreation();
7713 }
7714 return nullptr;
7715}
7716
7717// static
7718bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
7719 while (aNode) {
7720 if (aNode->IsEditable()) {
7721 return true;
7722 }
7723 aNode = aNode->GetParent();
7724 }
7725 return false;
7726}
7727
7728// static
7729bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
7730 const nsACString& aValue) {
7731 if (IsForbiddenSystemRequestHeader(aHeader)) {
7732 return true;
7733 }
7734
7735 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
7736 nsContentUtils::ContainsForbiddenMethod(aValue))) {
7737 return true;
7738 }
7739
7740 if (StringBeginsWith(aHeader, "proxy-"_ns,
7741 nsCaseInsensitiveCStringComparator) ||
7742 StringBeginsWith(aHeader, "sec-"_ns,
7743 nsCaseInsensitiveCStringComparator)) {
7744 return true;
7745 }
7746
7747 return false;
7748}
7749
7750// static
7751bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
7752 static const char* kInvalidHeaders[] = {"accept-charset",
7753 "accept-encoding",
7754 "access-control-request-headers",
7755 "access-control-request-method",
7756 "connection",
7757 "content-length",
7758 "cookie",
7759 "cookie2",
7760 "date",
7761 "dnt",
7762 "expect",
7763 "host",
7764 "keep-alive",
7765 "origin",
7766 "referer",
7767 "set-cookie",
7768 "te",
7769 "trailer",
7770 "transfer-encoding",
7771 "upgrade",
7772 "via"};
7773 for (auto& kInvalidHeader : kInvalidHeaders) {
7774 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
7775 return true;
7776 }
7777 }
7778 return false;
7779}
7780
7781// static
7782bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
7783 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
7784 aHeader.LowerCaseEqualsASCII("set-cookie2"));
7785}
7786
7787// static
7788bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
7789 return headerName.EqualsIgnoreCase("x-http-method-override") ||
7790 headerName.EqualsIgnoreCase("x-http-method") ||
7791 headerName.EqualsIgnoreCase("x-method-override");
7792}
7793
7794// static
7795bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
7796 bool hasInsecureMethod = false;
7797 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
7798
7799 while (tokenizer.hasMoreTokens()) {
7800 const nsDependentCSubstring& value = tokenizer.nextToken();
7801
7802 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
7803 value.EqualsIgnoreCase("track")) {
7804 hasInsecureMethod = true;
7805 break;
7806 }
7807 }
7808
7809 return hasInsecureMethod;
7810}
7811
7812Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
7813 const nsACString& aHeaderValue, bool aAllowWhitespace) {
7814 // See https://fetch.spec.whatwg.org/#simple-range-header-value
7815 mozilla::Tokenizer p(aHeaderValue);
7816 Maybe<uint64_t> rangeStart;
7817 Maybe<uint64_t> rangeEnd;
7818
7819 // Step 2 and 3
7820 if (!p.CheckWord("bytes")) {
7821 return Nothing();
7822 }
7823
7824 // Step 4
7825 if (aAllowWhitespace) {
7826 p.SkipWhites();
7827 }
7828
7829 // Step 5 and 6
7830 if (!p.CheckChar('=')) {
7831 return Nothing();
7832 }
7833
7834 // Step 7
7835 if (aAllowWhitespace) {
7836 p.SkipWhites();
7837 }
7838
7839 // Step 8 and 9
7840 uint64_t res;
7841 if (p.ReadInteger(&res)) {
7842 rangeStart = Some(res);
7843 }
7844
7845 // Step 10
7846 if (aAllowWhitespace) {
7847 p.SkipWhites();
7848 }
7849
7850 // Step 11
7851 if (!p.CheckChar('-')) {
7852 return Nothing();
7853 }
7854
7855 // Step 13
7856 if (aAllowWhitespace) {
7857 p.SkipWhites();
7858 }
7859
7860 // Step 14 and 15
7861 if (p.ReadInteger(&res)) {
7862 rangeEnd = Some(res);
7863 }
7864
7865 // Step 16
7866 if (!p.CheckEOF()) {
7867 return Nothing();
7868 }
7869
7870 // Step 17
7871 if (!rangeStart && !rangeEnd) {
7872 return Nothing();
7873 }
7874
7875 // Step 18
7876 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
7877 return Nothing();
7878 }
7879
7880 return Some(ParsedRange(rangeStart, rangeEnd));
7881}
7882
7883// static
7884bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
7885 const nsACString& aHeaderValue) {
7886 const char* cur = aHeaderValue.BeginReading();
7887 const char* end = aHeaderValue.EndReading();
7888
7889 while (cur != end) {
7890 // Implementation of
7891 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
7892 // than a space but not a horizontal tab
7893 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
7894 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
7895 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
7896 *cur == ']' || *cur == '{' || *cur == '}' ||
7897 *cur == 0x7F) { // 0x75 is DEL
7898 return true;
7899 }
7900 cur++;
7901 }
7902 return false;
7903}
7904
7905// static
7906bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
7907 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7908 return false;
7909 }
7910 return true;
7911}
7912
7913// static
7914bool nsContentUtils::IsAllowedNonCorsContentType(
7915 const nsACString& aHeaderValue) {
7916 nsAutoCString contentType;
7917 nsAutoCString unused;
7918
7919 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7920 return false;
7921 }
7922
7923 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
7924 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7925 return false;
7926 }
7927
7928 return contentType.LowerCaseEqualsLiteral("text/plain") ||
7929 contentType.LowerCaseEqualsLiteral(
7930 "application/x-www-form-urlencoded") ||
7931 contentType.LowerCaseEqualsLiteral("multipart/form-data");
7932}
7933
7934// static
7935bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
7936 const char* cur = aHeaderValue.BeginReading();
7937 const char* end = aHeaderValue.EndReading();
7938
7939 while (cur != end) {
7940 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
7941 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
7942 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
7943 *cur == '=') {
7944 cur++;
7945 continue;
7946 }
7947 return false;
7948 }
7949 return true;
7950}
7951
7952bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
7953 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
7954 if (!parsedRange) {
7955 return false;
7956 }
7957
7958 if (!parsedRange->Start()) {
7959 return false;
7960 }
7961
7962 return true;
7963}
7964
7965// static
7966bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
7967 const nsACString& aValue) {
7968 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
7969 if (aValue.Length() > 128) {
7970 return false;
7971 }
7972 return (aName.LowerCaseEqualsLiteral("accept") &&
7973 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
7974 (aName.LowerCaseEqualsLiteral("accept-language") &&
7975 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7976 (aName.LowerCaseEqualsLiteral("content-language") &&
7977 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7978 (aName.LowerCaseEqualsLiteral("content-type") &&
7979 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
7980 (aName.LowerCaseEqualsLiteral("range") &&
7981 nsContentUtils::IsAllowedNonCorsRange(aValue));
7982}
7983
7984mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
7985 return gResistFingerprintingLog;
7986}
7987mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
7988
7989bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7990 nsAString& aResult,
7991 const fallible_t& aFallible) {
7992 aResult.Truncate();
7993 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7994}
7995
7996void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7997 nsAString& aResult) {
7998 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
7999 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
8000 }
8001}
8002
8003void nsContentUtils::DestroyMatchString(void* aData) {
8004 if (aData) {
8005 nsString* matchString = static_cast<nsString*>(aData);
8006 delete matchString;
8007 }
8008}
8009
8010// Table ordered from most to least likely JS MIME types.
8011static constexpr std::string_view kJavascriptMIMETypes[] = {
8012 "text/javascript",
8013 "text/ecmascript",
8014 "application/javascript",
8015 "application/ecmascript",
8016 "application/x-javascript",
8017 "application/x-ecmascript",
8018 "text/javascript1.0",
8019 "text/javascript1.1",
8020 "text/javascript1.2",
8021 "text/javascript1.3",
8022 "text/javascript1.4",
8023 "text/javascript1.5",
8024 "text/jscript",
8025 "text/livescript",
8026 "text/x-ecmascript",
8027 "text/x-javascript"};
8028
8029bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
8030 for (std::string_view type : kJavascriptMIMETypes) {
8031 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
8032 return true;
8033 }
8034 }
8035 return false;
8036}
8037
8038bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
8039 for (std::string_view type : kJavascriptMIMETypes) {
8040 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
8041 return true;
8042 }
8043 }
8044 return false;
8045}
8046
8047bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
8048 //
8049 // SECURITY CHECK: disable prefetching and preloading from mailnews!
8050 //
8051 // walk up the docshell tree to see if any containing
8052 // docshell are of type MAIL.
8053 //
8054
8055 if (!aDocShell) {
8056 return false;
8057 }
8058
8059 nsCOMPtr<nsIDocShell> docshell = aDocShell;
8060 nsCOMPtr<nsIDocShellTreeItem> parentItem;
8061
8062 do {
8063 auto appType = docshell->GetAppType();
8064 if (appType == nsIDocShell::APP_TYPE_MAIL) {
8065 return false; // do not prefetch, preload, preconnect from mailnews
8066 }
8067
8068 docshell->GetInProcessParent(getter_AddRefs(parentItem));
8069 if (parentItem) {
8070 docshell = do_QueryInterface(parentItem);
8071 if (!docshell) {
8072 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"
, 8072); MOZ_PretendNoReturn(); } while (0)
;
8073 return false;
8074 }
8075 }
8076 } while (parentItem);
8077
8078 return true;
8079}
8080
8081uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
8082 // can't do anything if there's no nsIRequest!
8083 if (!aRequest) {
8084 return 0;
8085 }
8086
8087 nsCOMPtr<nsILoadGroup> loadGroup;
8088 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
8089
8090 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
8091 return 0;
8092 }
8093
8094 return GetInnerWindowID(loadGroup);
8095}
8096
8097uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
8098 if (!aLoadGroup) {
8099 return 0;
8100 }
8101
8102 nsCOMPtr<nsIInterfaceRequestor> callbacks;
8103 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
8104 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
8105 return 0;
8106 }
8107
8108 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
8109 if (!loadContext) {
8110 return 0;
8111 }
8112
8113 nsCOMPtr<mozIDOMWindowProxy> window;
8114 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
8115 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
8116 return 0;
8117 }
8118
8119 auto* pwindow = nsPIDOMWindowOuter::From(window);
8120 if (!pwindow) {
8121 return 0;
8122 }
8123
8124 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
8125 return inner ? inner->WindowID() : 0;
8126}
8127
8128// static
8129void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
8130 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
8131 MOZ_ASSERT(!aHost.Length() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aHost.Length() || (aHost[0] != '[' && aHost
[aHost.Length() - 1] != ']'))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aHost.Length() || (aHost[0]
!= '[' && aHost[aHost.Length() - 1] != ']')))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
")"); do { *((volatile int*)__null) = 8132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8132 (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']'))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aHost.Length() || (aHost[0] != '[' && aHost
[aHost.Length() - 1] != ']'))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aHost.Length() || (aHost[0]
!= '[' && aHost[aHost.Length() - 1] != ']')))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
")"); do { *((volatile int*)__null) = 8132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8133 aHost.Insert('[', 0);
8134 aHost.Append(']');
8135 }
8136}
8137
8138nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8139 nsACString& aHost) {
8140 aHost.Truncate();
8141 nsresult rv = aURI->GetHost(aHost);
8142 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8143 return rv;
8144 }
8145
8146 MaybeFixIPv6Host(aHost);
8147
8148 return NS_OK;
8149}
8150
8151nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8152 nsAString& aHost) {
8153 nsAutoCString hostname;
8154 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
8155 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8156 return rv;
8157 }
8158 CopyUTF8toUTF16(hostname, aHost);
8159 return NS_OK;
8160}
8161
8162nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
8163 nsACString& aHost) {
8164 nsresult rv = aPrincipal->GetAsciiHost(aHost);
8165 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8166 return rv;
8167 }
8168
8169 MaybeFixIPv6Host(aHost);
8170 return NS_OK;
8171}
8172
8173CallState nsContentUtils::CallOnAllRemoteChildren(
8174 MessageBroadcaster* aManager,
8175 const std::function<CallState(BrowserParent*)>& aCallback) {
8176 uint32_t browserChildCount = aManager->ChildCount();
8177 for (uint32_t j = 0; j < browserChildCount; ++j) {
8178 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
8179 if (!childMM) {
8180 continue;
8181 }
8182
8183 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
8184 if (nonLeafMM) {
8185 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
8186 return CallState::Stop;
8187 }
8188 continue;
8189 }
8190
8191 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
8192 if (cb) {
8193 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
8194 BrowserParent* remote = BrowserParent::GetFrom(fl);
8195 if (remote && aCallback) {
8196 if (aCallback(remote) == CallState::Stop) {
8197 return CallState::Stop;
8198 }
8199 }
8200 }
8201 }
8202
8203 return CallState::Continue;
8204}
8205
8206void nsContentUtils::CallOnAllRemoteChildren(
8207 nsPIDOMWindowOuter* aWindow,
8208 const std::function<CallState(BrowserParent*)>& aCallback) {
8209 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
8210 if (window->IsChromeWindow()) {
8211 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
8212 if (windowMM) {
8213 CallOnAllRemoteChildren(windowMM, aCallback);
8214 }
8215 }
8216}
8217
8218bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
8219 const IPCTransferableDataItem& aItem) {
8220 // Unknown types are converted to kCustomTypesMime.
8221 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
8222 return true;
8223 }
8224
8225 for (const char* format : DataTransfer::kKnownFormats) {
8226 if (aItem.flavor().EqualsASCII(format)) {
8227 return true;
8228 }
8229 }
8230
8231 return false;
8232}
8233
8234nsresult nsContentUtils::IPCTransferableDataToTransferable(
8235 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
8236 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8237 nsresult rv;
8238 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
8239 for (const auto& item : items) {
8240 if (aFilterUnknownFlavors && !IPCTransferableDataItemHasKnownFlavor(item)) {
8241 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"
, 8243)
8242 "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"
, 8243)
8243 "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"
, 8243)
;
8244 continue;
8245 }
8246
8247 if (aAddDataFlavor) {
8248 aTransferable->AddDataFlavor(item.flavor().get());
8249 }
8250
8251 nsCOMPtr<nsISupports> transferData;
8252 switch (item.data().type()) {
8253 case IPCTransferableDataType::TIPCTransferableDataString: {
8254 const auto& data = item.data().get_IPCTransferableDataString();
8255 nsCOMPtr<nsISupportsString> dataWrapper =
8256 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
8257 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"
, 8257); return rv; } } while (false)
;
8258 rv = dataWrapper->SetData(nsDependentSubstring(
8259 reinterpret_cast<const char16_t*>(data.data().Data()),
8260 data.data().Size() / sizeof(char16_t)));
8261 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"
, 8261); return rv; } } while (false)
;
8262 transferData = dataWrapper;
8263 break;
8264 }
8265 case IPCTransferableDataType::TIPCTransferableDataCString: {
8266 const auto& data = item.data().get_IPCTransferableDataCString();
8267 nsCOMPtr<nsISupportsCString> dataWrapper =
8268 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
8269 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"
, 8269); return rv; } } while (false)
;
8270 rv = dataWrapper->SetData(nsDependentCSubstring(
8271 reinterpret_cast<const char*>(data.data().Data()),
8272 data.data().Size()));
8273 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"
, 8273); return rv; } } while (false)
;
8274 transferData = dataWrapper;
8275 break;
8276 }
8277 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8278 const auto& data = item.data().get_IPCTransferableDataInputStream();
8279 nsCOMPtr<nsIInputStream> stream;
8280 rv = NS_NewByteInputStream(getter_AddRefs(stream),
8281 AsChars(data.data().AsSpan()),
8282 NS_ASSIGNMENT_COPY);
8283 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"
, 8283); return rv; } } while (false)
;
8284 transferData = stream.forget();
8285 break;
8286 }
8287 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8288 const auto& data = item.data().get_IPCTransferableDataImageContainer();
8289 nsCOMPtr<imgIContainer> container;
8290 rv = DeserializeTransferableDataImageContainer(
8291 data, getter_AddRefs(container));
8292 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"
, 8292); return rv; } } while (false)
;
8293 transferData = container;
8294 break;
8295 }
8296 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8297 const auto& data = item.data().get_IPCTransferableDataBlob();
8298 transferData = IPCBlobUtils::Deserialize(data.blob());
8299 break;
8300 }
8301 case IPCTransferableDataType::T__None:
8302 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"
, 8302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8302; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8303 return NS_ERROR_FAILURE;
8304 }
8305
8306 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
8307 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"
, 8307); return rv; } } while (false)
;
8308 }
8309 return NS_OK;
8310}
8311
8312nsresult nsContentUtils::IPCTransferableToTransferable(
8313 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
8314 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8315 // Note that we need to set privacy status of transferable before adding any
8316 // data into it.
8317 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
8318
8319 nsresult rv =
8320 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
8321 aTransferable, aFilterUnknownFlavors);
8322 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"
, 8322); return rv; } } while (false)
;
8323
8324 if (aIPCTransferable.cookieJarSettings().isSome()) {
8325 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
8326 net::CookieJarSettings::Deserialize(
8327 aIPCTransferable.cookieJarSettings().ref(),
8328 getter_AddRefs(cookieJarSettings));
8329 aTransferable->SetCookieJarSettings(cookieJarSettings);
8330 }
8331 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
8332 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
8333 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
8334
8335 return NS_OK;
8336}
8337
8338nsresult nsContentUtils::IPCTransferableDataItemToVariant(
8339 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
8340 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"
, 8340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { *((volatile int*)__null) = 8340; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8341
8342 switch (aItem.data().type()) {
8343 case IPCTransferableDataType::TIPCTransferableDataString: {
8344 const auto& data = aItem.data().get_IPCTransferableDataString();
8345 return aVariant->SetAsAString(nsDependentSubstring(
8346 reinterpret_cast<const char16_t*>(data.data().Data()),
8347 data.data().Size() / sizeof(char16_t)));
8348 }
8349 case IPCTransferableDataType::TIPCTransferableDataCString: {
8350 const auto& data = aItem.data().get_IPCTransferableDataCString();
8351 return aVariant->SetAsACString(nsDependentCSubstring(
8352 reinterpret_cast<const char*>(data.data().Data()),
8353 data.data().Size()));
8354 }
8355 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8356 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
8357 nsCOMPtr<nsIInputStream> stream;
8358 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
8359 AsChars(data.data().AsSpan()),
8360 NS_ASSIGNMENT_COPY);
8361 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"
, 8361); return rv; } } while (false)
;
8362 return aVariant->SetAsISupports(stream);
8363 }
8364 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8365 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
8366 nsCOMPtr<imgIContainer> container;
8367 nsresult rv = DeserializeTransferableDataImageContainer(
8368 data, getter_AddRefs(container));
8369 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"
, 8369); return rv; } } while (false)
;
8370 return aVariant->SetAsISupports(container);
8371 }
8372 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8373 const auto& data = aItem.data().get_IPCTransferableDataBlob();
8374 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
8375 return aVariant->SetAsISupports(blobImpl);
8376 }
8377 case IPCTransferableDataType::T__None:
8378 break;
8379 }
8380
8381 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"
, 8381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8381; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8382 return NS_ERROR_UNEXPECTED;
8383}
8384
8385void nsContentUtils::TransferablesToIPCTransferableDatas(
8386 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
8387 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8388 aIPC.Clear();
8389 if (aTransferables) {
8390 uint32_t transferableCount = 0;
8391 aTransferables->GetLength(&transferableCount);
8392 for (uint32_t i = 0; i < transferableCount; ++i) {
8393 IPCTransferableData* dt = aIPC.AppendElement();
8394 nsCOMPtr<nsITransferable> transferable =
8395 do_QueryElementAt(aTransferables, i);
8396 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
8397 aParent);
8398 }
8399 }
8400}
8401
8402nsresult nsContentUtils::CalculateBufferSizeForImage(
8403 const uint32_t& aStride, const IntSize& aImageSize,
8404 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
8405 size_t* aUsedBufferSize) {
8406 CheckedInt32 requiredBytes =
8407 CheckedInt32(aStride) * CheckedInt32(aImageSize.height);
8408
8409 CheckedInt32 usedBytes =
8410 requiredBytes - aStride +
8411 (CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat));
8412 if (!usedBytes.isValid()) {
8413 return NS_ERROR_FAILURE;
8414 }
8415
8416 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"
, 8416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "requiredBytes.isValid()"
") (" "usedBytes valid but not required?" ")"); do { *((volatile
int*)__null) = 8416; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8417 *aMaxBufferSize = requiredBytes.value();
8418 *aUsedBufferSize = usedBytes.value();
8419 return NS_OK;
8420}
8421
8422static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
8423 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
8424 SurfaceFormat aFormat) {
8425 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
8426 return nullptr;
8427 }
8428
8429 // Validate shared memory buffer size
8430 size_t imageBufLen = 0;
8431 size_t maxBufLen = 0;
8432 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
8433 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
8434 return nullptr;
8435 }
8436 if (imageBufLen > aData.Size()) {
8437 return nullptr;
8438 }
8439 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
8440 aStride);
8441}
8442
8443nsresult nsContentUtils::DeserializeTransferableDataImageContainer(
8444 const IPCTransferableDataImageContainer& aData,
8445 imgIContainer** aContainer) {
8446 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aData.image());
8447 if (!surface) {
8448 return NS_ERROR_FAILURE;
8449 }
8450
8451 RefPtr<gfxDrawable> drawable =
8452 new gfxSurfaceDrawable(surface, surface->GetSize());
8453 nsCOMPtr<imgIContainer> imageContainer =
8454 image::ImageOps::CreateFromDrawable(drawable);
8455 imageContainer.forget(aContainer);
8456
8457 return NS_OK;
8458}
8459
8460bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
8461 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
8462 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
8463 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
8464 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
8465 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
8466}
8467
8468// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
8469// will be implicitly serialized in shmem when sent over IPDL directly.
8470static IPCTransferableDataString AsIPCTransferableDataString(
8471 Span<const char16_t> aInput) {
8472 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
8473}
8474
8475// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
8476// will be implicitly serialized in shmem when sent over IPDL directly.
8477static IPCTransferableDataCString AsIPCTransferableDataCString(
8478 Span<const char> aInput) {
8479 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
8480}
8481
8482void nsContentUtils::TransferableToIPCTransferableData(
8483 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
8484 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8485 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"
, 8485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { *((volatile int*)__null) = 8485; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8486
8487 if (aTransferable) {
8488 nsTArray<nsCString> flavorList;
8489 aTransferable->FlavorsTransferableCanExport(flavorList);
8490
8491 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
8492 nsCString& flavorStr = flavorList[j];
8493 if (!flavorStr.Length()) {
8494 continue;
8495 }
8496
8497 nsCOMPtr<nsISupports> data;
8498 nsresult rv =
8499 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
8500
8501 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
8502 if (aInSyncMessage) {
8503 // Can't do anything.
8504 // FIXME: This shouldn't be the case anymore!
8505 continue;
8506 }
8507
8508 // This is a hack to support kFilePromiseMime.
8509 // On Windows there just needs to be an entry for it,
8510 // and for OSX we need to create
8511 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
8512 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
8513 IPCTransferableDataItem* item =
8514 aTransferableData->items().AppendElement();
8515 item->flavor() = flavorStr;
8516 item->data() =
8517 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
8518 continue;
8519 }
8520
8521 // Empty element, transfer only the flavor
8522 IPCTransferableDataItem* item =
8523 aTransferableData->items().AppendElement();
8524 item->flavor() = flavorStr;
8525 item->data() = AsIPCTransferableDataString(EmptyString());
8526 continue;
8527 }
8528
8529 // We need to handle nsIInputStream before nsISupportsCString, otherwise
8530 // nsStringInputStream would be converted into a wrong type.
8531 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
8532 IPCTransferableDataItem* item =
8533 aTransferableData->items().AppendElement();
8534 item->flavor() = flavorStr;
8535 nsCString imageData;
8536 DebugOnly<nsresult> rv =
8537 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
8538 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"
, 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8539 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"
, 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8540 "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"
, 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8541 // FIXME: This can probably be simplified once bug 1783240 lands, as
8542 // `nsCString` will be implicitly serialized in shmem when sent over
8543 // IPDL directly.
8544 item->data() =
8545 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
8546 continue;
8547 }
8548
8549 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
8550 nsAutoString dataAsString;
8551 MOZ_ALWAYS_SUCCEEDS(text->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(text->GetData(dataAsString))), 1)))), 1))) { } else { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8551); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"); do
{ *((volatile int*)__null) = 8551; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
8552
8553 IPCTransferableDataItem* item =
8554 aTransferableData->items().AppendElement();
8555 item->flavor() = flavorStr;
8556 item->data() = AsIPCTransferableDataString(dataAsString);
8557 continue;
8558 }
8559
8560 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
8561 nsAutoCString dataAsString;
8562 MOZ_ALWAYS_SUCCEEDS(ctext->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(ctext->GetData(dataAsString))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8562); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(ctext->GetData(dataAsString))" ")"); do
{ *((volatile int*)__null) = 8562; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
8563
8564 IPCTransferableDataItem* item =
8565 aTransferableData->items().AppendElement();
8566 item->flavor() = flavorStr;
8567 item->data() = AsIPCTransferableDataCString(dataAsString);
8568 continue;
8569 }
8570
8571 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
8572 // Images to be placed on the clipboard are imgIContainers.
8573 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
8574 imgIContainer::FRAME_CURRENT,
8575 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
8576 if (!surface) {
8577 continue;
8578 }
8579 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
8580 surface->GetDataSurface();
8581 if (!dataSurface) {
8582 continue;
8583 }
8584
8585 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
8586 if (!imageData) {
8587 continue;
8588 }
8589
8590 IPCTransferableDataItem* item =
8591 aTransferableData->items().AppendElement();
8592 item->flavor() = flavorStr;
8593 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
8594 continue;
8595 }
8596
8597 // Otherwise, handle this as a file.
8598 nsCOMPtr<BlobImpl> blobImpl;
8599 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
8600 if (aParent) {
8601 bool isDir = false;
8602 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
8603 nsAutoString path;
8604 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"
, 8604)
) {
8605 continue;
8606 }
8607
8608 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
8609 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
8610 }
8611 }
8612
8613 blobImpl = new FileBlobImpl(file);
8614
8615 IgnoredErrorResult rv;
8616
8617 // Ensure that file data is cached no that the content process
8618 // has this data available to it when passed over:
8619 blobImpl->GetSize(rv);
8620 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"
, 8620)
) {
8621 continue;
8622 }
8623
8624 blobImpl->GetLastModified(rv);
8625 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"
, 8625)
) {
8626 continue;
8627 }
8628 } else {
8629 if (aInSyncMessage) {
8630 // Can't do anything.
8631 // FIXME: This shouldn't be the case anymore!
8632 continue;
8633 }
8634
8635 blobImpl = do_QueryInterface(data);
8636 }
8637
8638 if (blobImpl) {
8639 // If we failed to create the blob actor, then this blob probably
8640 // can't get the file size for the underlying file, ignore it for
8641 // now. TODO pass this through anyway.
8642 IPCBlob ipcBlob;
8643 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
8644 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"
, 8644)
) {
8645 continue;
8646 }
8647
8648 IPCTransferableDataItem* item =
8649 aTransferableData->items().AppendElement();
8650 item->flavor() = flavorStr;
8651 item->data() = IPCTransferableDataBlob(ipcBlob);
8652 }
8653 }
8654 }
8655}
8656
8657void nsContentUtils::TransferableToIPCTransferable(
8658 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
8659 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8660 IPCTransferableData ipcTransferableData;
8661 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
8662 aInSyncMessage, aParent);
8663
8664 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
8665 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
8666 aTransferable->GetCookieJarSettings()) {
8667 net::CookieJarSettingsArgs args;
8668 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
8669 cookieJarSettingsArgs = Some(std::move(args));
8670 }
8671
8672 aIPCTransferable->data() = std::move(ipcTransferableData);
8673 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
8674 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
8675 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
8676 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
8677 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
8678}
8679
8680Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
8681 size_t* aLength,
8682 int32_t* aStride) {
8683 mozilla::gfx::DataSourceSurface::MappedSurface map;
8684 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
8685 return Nothing();
8686 }
8687
8688 size_t bufLen = 0;
8689 size_t maxBufLen = 0;
8690 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
8691 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
8692 &bufLen);
8693 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8694 aSurface.Unmap();
8695 return Nothing();
8696 }
8697
8698 BigBuffer surfaceData(maxBufLen);
8699 memcpy(surfaceData.Data(), map.mData, bufLen);
8700 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
8701
8702 *aLength = maxBufLen;
8703 *aStride = map.mStride;
8704
8705 aSurface.Unmap();
8706 return Some(std::move(surfaceData));
8707}
8708
8709Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
8710 size_t len = 0;
8711 int32_t stride = 0;
8712 auto mem = GetSurfaceData(aSurface, &len, &stride);
8713 if (!mem) {
8714 return Nothing();
8715 }
8716 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
8717 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
8718}
8719
8720already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
8721 const IPCImage& aImage) {
8722 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
8723 aImage.size().ToUnknownSize(), aImage.format());
8724}
8725
8726Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
8727 Modifiers result = 0;
8728 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
8729 result |= mozilla::MODIFIER_SHIFT;
8730 }
8731 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
8732 result |= mozilla::MODIFIER_CONTROL;
8733 }
8734 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
8735 result |= mozilla::MODIFIER_ALT;
8736 }
8737 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
8738 result |= mozilla::MODIFIER_META;
8739 }
8740 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
8741 result |= mozilla::MODIFIER_ALTGRAPH;
8742 }
8743 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
8744 result |= mozilla::MODIFIER_CAPSLOCK;
8745 }
8746 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
8747 result |= mozilla::MODIFIER_FN;
8748 }
8749 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
8750 result |= mozilla::MODIFIER_FNLOCK;
8751 }
8752 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
8753 result |= mozilla::MODIFIER_NUMLOCK;
8754 }
8755 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
8756 result |= mozilla::MODIFIER_SCROLLLOCK;
8757 }
8758 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
8759 result |= mozilla::MODIFIER_SYMBOL;
8760 }
8761 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
8762 result |= mozilla::MODIFIER_SYMBOLLOCK;
8763 }
8764 return result;
8765}
8766
8767nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
8768 if (!aPresShell) {
8769 return nullptr;
8770 }
8771 nsIFrame* frame = aPresShell->GetRootFrame();
8772 if (!frame) {
8773 return nullptr;
8774 }
8775 return frame->GetView()->GetNearestWidget(aOffset);
8776}
8777
8778int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
8779 switch (aButton) {
8780 case -1:
8781 return MouseButtonsFlag::eNoButtons;
8782 case MouseButton::ePrimary:
8783 return MouseButtonsFlag::ePrimaryFlag;
8784 case MouseButton::eMiddle:
8785 return MouseButtonsFlag::eMiddleFlag;
8786 case MouseButton::eSecondary:
8787 return MouseButtonsFlag::eSecondaryFlag;
8788 case 3:
8789 return MouseButtonsFlag::e4thFlag;
8790 case 4:
8791 return MouseButtonsFlag::e5thFlag;
8792 case MouseButton::eEraser:
8793 return MouseButtonsFlag::eEraserFlag;
8794 default:
8795 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"
, 8795); MOZ_PretendNoReturn(); } while (0)
;
8796 return 0;
8797 }
8798}
8799
8800LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
8801 const CSSPoint& aPoint, const nsPoint& aOffset,
8802 nsPresContext* aPresContext) {
8803 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
8804 nsPoint visualRelative =
8805 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
8806 return LayoutDeviceIntPoint::FromAppUnitsRounded(
8807 visualRelative, aPresContext->AppUnitsPerDevPixel());
8808}
8809
8810nsView* nsContentUtils::GetViewToDispatchEvent(nsPresContext* aPresContext,
8811 PresShell** aPresShell) {
8812 if (!aPresContext || !aPresShell) {
8813 return nullptr;
8814 }
8815 RefPtr<PresShell> presShell = aPresContext->PresShell();
8816 if (NS_WARN_IF(!presShell)NS_warn_if_impl(!presShell, "!presShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8816)
) {
8817 *aPresShell = nullptr;
8818 return nullptr;
8819 }
8820 nsViewManager* viewManager = presShell->GetViewManager();
8821 if (!viewManager) {
8822 presShell.forget(aPresShell); // XXX Is this intentional?
8823 return nullptr;
8824 }
8825 presShell.forget(aPresShell);
8826 return viewManager->GetRootView();
8827}
8828
8829nsresult nsContentUtils::SendMouseEvent(
8830 mozilla::PresShell* aPresShell, const nsAString& aType, float aX, float aY,
8831 int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers,
8832 bool aIgnoreRootScrollFrame, float aPressure,
8833 unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
8834 PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
8835 bool aIsWidgetEventSynthesized) {
8836 nsPoint offset;
8837 nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
8838 if (!widget) return NS_ERROR_FAILURE;
8839
8840 EventMessage msg;
8841 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
8842 bool contextMenuKey = false;
8843 if (aType.EqualsLiteral("mousedown")) {
8844 msg = eMouseDown;
8845 } else if (aType.EqualsLiteral("mouseup")) {
8846 msg = eMouseUp;
8847 } else if (aType.EqualsLiteral("mousemove")) {
8848 msg = eMouseMove;
8849 } else if (aType.EqualsLiteral("mouseover")) {
8850 msg = eMouseEnterIntoWidget;
8851 } else if (aType.EqualsLiteral("mouseout")) {
8852 msg = eMouseExitFromWidget;
8853 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
8854 } else if (aType.EqualsLiteral("mousecancel")) {
8855 msg = eMouseExitFromWidget;
8856 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
8857 : WidgetMouseEvent::ePuppet);
8858 } else if (aType.EqualsLiteral("mouselongtap")) {
8859 msg = eMouseLongTap;
8860 } else if (aType.EqualsLiteral("contextmenu")) {
8861 msg = eContextMenu;
8862 contextMenuKey = (aButton == 0);
8863 } else if (aType.EqualsLiteral("MozMouseHittest")) {
8864 msg = eMouseHitTest;
8865 } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
8866 msg = eMouseExploreByTouch;
8867 } else {
8868 return NS_ERROR_FAILURE;
8869 }
8870
8871 if (aInputSourceArg == MouseEvent_Binding::MOZ_SOURCE_UNKNOWN) {
8872 aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
8873 }
8874
8875 Maybe<WidgetPointerEvent> pointerEvent;
8876 Maybe<WidgetMouseEvent> mouseEvent;
8877 if (IsPointerEventMessage(msg)) {
8878 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"
, 8879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8879 "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"
, 8879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8880 if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)(__builtin_expect(!!(aIsWidgetEventSynthesized), 0))) {
8881 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
8882 // synthesized event.
8883 return NS_ERROR_INVALID_ARG;
8884 }
8885 pointerEvent.emplace(true, msg, widget,
8886 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8887 : WidgetMouseEvent::eNormal);
8888 } else {
8889 mouseEvent.emplace(true, msg, widget,
8890 aIsWidgetEventSynthesized
8891 ? WidgetMouseEvent::eSynthesized
8892 : WidgetMouseEvent::eReal,
8893 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8894 : WidgetMouseEvent::eNormal);
8895 }
8896 WidgetMouseEvent& mouseOrPointerEvent =
8897 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
8898 mouseOrPointerEvent.pointerId = aIdentifier;
8899 mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers);
8900 mouseOrPointerEvent.mButton = aButton;
8901 mouseOrPointerEvent.mButtons =
8902 aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ? aButtons
8903 : msg == eMouseUp ? 0
8904 : GetButtonsFlagForButton(aButton);
8905 mouseOrPointerEvent.mPressure = aPressure;
8906 mouseOrPointerEvent.mInputSource = aInputSourceArg;
8907 mouseOrPointerEvent.mClickCount = aClickCount;
8908 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
8909 mouseOrPointerEvent.mExitFrom = exitFrom;
8910
8911 nsPresContext* presContext = aPresShell->GetPresContext();
8912 if (!presContext) return NS_ERROR_FAILURE;
8913
8914 mouseOrPointerEvent.mRefPoint =
8915 ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
8916 mouseOrPointerEvent.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
8917
8918 nsEventStatus status = nsEventStatus_eIgnore;
8919 if (aToWindow) {
8920 RefPtr<PresShell> presShell;
8921 nsView* view =
8922 GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
8923 if (!presShell || !view) {
8924 return NS_ERROR_FAILURE;
8925 }
8926 return presShell->HandleEvent(view->GetFrame(), &mouseOrPointerEvent, false,
8927 &status);
8928 }
8929 if (StaticPrefs::test_events_async_enabled()) {
8930 status = widget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
8931 } else {
8932 nsresult rv = widget->DispatchEvent(&mouseOrPointerEvent, status);
8933 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"
, 8933); return rv; } } while (false)
;
8934 }
8935 if (aPreventDefault) {
8936 if (status == nsEventStatus_eConsumeNoDefault) {
8937 if (mouseOrPointerEvent.mFlags.mDefaultPreventedByContent) {
8938 *aPreventDefault = PreventDefaultResult::ByContent;
8939 } else {
8940 *aPreventDefault = PreventDefaultResult::ByChrome;
8941 }
8942 } else {
8943 *aPreventDefault = PreventDefaultResult::No;
8944 }
8945 }
8946
8947 return NS_OK;
8948}
8949
8950/* static */
8951void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
8952 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8953 bool aOnlySystemGroup) {
8954 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"
, 8954); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { *((volatile int*)__null) = 8954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8955 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"
, 8955); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler"
")"); do { *((volatile int*)__null) = 8955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8956
8957 RefPtr<Document> doc = aItem->GetDocument();
8958 NS_ASSERTION(doc, "What happened here?")do { if (!(doc)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "What happened here?"
, "doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8958); MOZ_PretendNoReturn(); } } while (0)
;
8959 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
8960
8961 int32_t childCount = 0;
8962 aItem->GetInProcessChildCount(&childCount);
8963 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8964 kids.AppendElements(childCount);
8965 for (int32_t i = 0; i < childCount; ++i) {
8966 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8967 }
8968
8969 for (uint32_t i = 0; i < kids.Length(); ++i) {
8970 if (kids[i]) {
8971 FirePageHideEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8972 aOnlySystemGroup);
8973 }
8974 }
8975}
8976
8977// The pageshow event is fired for a given document only if IsShowing() returns
8978// the same thing as aFireIfShowing. This gives us a way to fire pageshow only
8979// on documents that are still loading or only on documents that are already
8980// loaded.
8981/* static */
8982void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
8983 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8984 bool aFireIfShowing, bool aOnlySystemGroup) {
8985 int32_t childCount = 0;
8986 aItem->GetInProcessChildCount(&childCount);
8987 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8988 kids.AppendElements(childCount);
8989 for (int32_t i = 0; i < childCount; ++i) {
8990 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8991 }
8992
8993 for (uint32_t i = 0; i < kids.Length(); ++i) {
8994 if (kids[i]) {
8995 FirePageShowEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8996 aFireIfShowing, aOnlySystemGroup);
8997 }
8998 }
8999
9000 RefPtr<Document> doc = aItem->GetDocument();
9001 if (doc && doc->IsShowing() == aFireIfShowing) {
9002 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
9003 }
9004}
9005
9006/* static */
9007already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
9008 if (aDoc) {
9009 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
9010 return win->GetTopWindowRoot();
9011 }
9012 }
9013 return nullptr;
9014}
9015
9016/* static */
9017bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
9018 nsIURI* aDocURI) {
9019 if (aAnchor.IsEmpty()) {
9020 // anchor parameter not present or empty -> same document reference
9021 return true;
9022 }
9023
9024 // the document URI might contain a fragment identifier ("#...')
9025 // we want to ignore that because it's invisible to the server
9026 // and just affects the local interpretation in the recipient
9027 nsCOMPtr<nsIURI> contextUri;
9028 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
9029
9030 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9031 // copying failed
9032 return false;
9033 }
9034
9035 // resolve anchor against context
9036 nsCOMPtr<nsIURI> resolvedUri;
9037 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
9038
9039 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9040 // resolving failed
9041 return false;
9042 }
9043
9044 bool same;
9045 rv = contextUri->Equals(resolvedUri, &same);
9046 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9047 // comparison failed
9048 return false;
9049 }
9050
9051 return same;
9052}
9053
9054/* static */
9055bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
9056 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
9057 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
9058 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
9059 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
9060 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
9061 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
9062}
9063
9064// static
9065ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
9066 nsIChannel* aChannel) {
9067 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
9068 if (!httpChannel) {
9069 return ReferrerPolicy::_empty;
9070 }
9071
9072 nsresult rv;
9073 nsAutoCString headerValue;
9074 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
9075 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
9076 return ReferrerPolicy::_empty;
9077 }
9078
9079 return ReferrerInfo::ReferrerPolicyFromHeaderString(
9080 NS_ConvertUTF8toUTF16(headerValue));
9081}
9082
9083// static
9084bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
9085 nsLoadFlags loadFlags = 0;
9086 aChannel->GetLoadFlags(&loadFlags);
9087 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
9088 return true;
9089 }
9090
9091 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9092 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
9093 return IsNonSubresourceInternalPolicyType(type);
9094}
9095
9096// static
9097bool nsContentUtils::IsNonSubresourceInternalPolicyType(
9098 nsContentPolicyType aType) {
9099 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
9100 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
9101 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
9102 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
9103 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
9104}
9105
9106// static public
9107bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
9108 nsPIDOMWindowInner* aWindow) {
9109 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"
, 9109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9109; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9110
9111 Document* document = aWindow->GetExtantDoc();
9112 if (!document) {
9113 return false;
9114 }
9115
9116 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9117 do_QueryInterface(document->GetChannel());
9118 if (!classifiedChannel) {
9119 return false;
9120 }
9121
9122 return classifiedChannel->IsThirdPartyTrackingResource();
9123}
9124
9125// static public
9126bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
9127 nsPIDOMWindowInner* aWindow) {
9128 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"
, 9128); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9128; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9129
9130 Document* document = aWindow->GetExtantDoc();
9131 if (!document) {
9132 return false;
9133 }
9134
9135 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9136 do_QueryInterface(document->GetChannel());
9137 if (!classifiedChannel) {
9138 return false;
9139 }
9140
9141 uint32_t classificationFlags =
9142 classifiedChannel->GetFirstPartyClassificationFlags();
9143
9144 return mozilla::net::UrlClassifierCommon::IsTrackingClassificationFlag(
9145 classificationFlags, NS_UsePrivateBrowsing(document->GetChannel()));
9146}
9147
9148namespace {
9149
9150// We put StringBuilder in the anonymous namespace to prevent anything outside
9151// this file from accidentally being linked against it.
9152class BulkAppender {
9153 using size_type = typename nsAString::size_type;
9154
9155 public:
9156 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
9157 : mHandle(std::move(aHandle)), mPosition(0) {}
9158 ~BulkAppender() = default;
9159
9160 template <int N>
9161 void AppendLiteral(const char16_t (&aStr)[N]) {
9162 size_t len = N - 1;
9163 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"
, 9163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9163; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9164 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
9165 mPosition += len;
9166 }
9167
9168 void Append(Span<const char16_t> aStr) {
9169 size_t len = aStr.Length();
9170 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"
, 9170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9171 // Both mHandle.Elements() and aStr.Elements() are guaranteed
9172 // to be non-null (by the string implementation and by Span,
9173 // respectively), so not checking the pointers for null before
9174 // memcpy does not lead to UB even if len was zero.
9175 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
9176 len * sizeof(char16_t));
9177 mPosition += len;
9178 }
9179
9180 void Append(Span<const char> aStr) {
9181 size_t len = aStr.Length();
9182 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"
, 9182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9183 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
9184 mPosition += len;
9185 }
9186
9187 void Finish() { mHandle.Finish(mPosition, false); }
9188
9189 private:
9190 BulkWriteHandle<char16_t> mHandle;
9191 size_type mPosition;
9192};
9193
9194class StringBuilder {
9195 private:
9196 class Unit {
9197 public:
9198 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)
; }
9199 ~Unit() {
9200 if (mType == Type::String || mType == Type::StringWithEncode) {
9201 mString.~nsString();
9202 }
9203 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)
;
9204 }
9205
9206 enum class Type : uint8_t {
9207 Unknown,
9208 Atom,
9209 String,
9210 StringWithEncode,
9211 Literal,
9212 TextFragment,
9213 TextFragmentWithEncode,
9214 };
9215
9216 struct LiteralSpan {
9217 const char16_t* mData;
9218 uint32_t mLength;
9219
9220 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
9221 };
9222
9223 union {
9224 nsAtom* mAtom;
9225 LiteralSpan mLiteral;
9226 nsString mString;
9227 const nsTextFragment* mTextFragment;
9228 };
9229 Type mType = Type::Unknown;
9230 };
9231
9232 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
9233 "Unit should remain small");
9234
9235 public:
9236 // Try to keep the size of StringBuilder close to a jemalloc bucket size (the
9237 // 16kb one in this case).
9238 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
9239
9240 // The number of units we need to remove from the inline buffer so that the
9241 // rest of the builder members fit. A more precise approach would be to
9242 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) / sizeof(Unit)
9243 // or so, but this is simpler.
9244 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
9245
9246 static constexpr uint32_t STRING_BUFFER_UNITS =
9247 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
9248
9249 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)
; }
9250
9251 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); }
9252
9253 void Append(nsAtom* aAtom) {
9254 Unit* u = AddUnit();
9255 u->mAtom = aAtom;
9256 u->mType = Unit::Type::Atom;
9257 uint32_t len = aAtom->GetLength();
9258 mLength += len;
9259 }
9260
9261 template <int N>
9262 void Append(const char16_t (&aLiteral)[N]) {
9263 constexpr uint32_t len = N - 1;
9264 Unit* u = AddUnit();
9265 u->mLiteral = {aLiteral, len};
9266 u->mType = Unit::Type::Literal;
9267 mLength += len;
9268 }
9269
9270 void Append(nsString&& aString) {
9271 Unit* u = AddUnit();
9272 uint32_t len = aString.Length();
9273 new (&u->mString) nsString(std::move(aString));
9274 u->mType = Unit::Type::String;
9275 mLength += len;
9276 }
9277
9278 // aLen can be !isValid(), which will get propagated into mLength.
9279 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
9280 Unit* u = AddUnit();
9281 new (&u->mString) nsString(std::move(aString));
9282 u->mType = Unit::Type::StringWithEncode;
9283 mLength += aLen;
9284 }
9285
9286 void Append(const nsTextFragment* aTextFragment) {
9287 Unit* u = AddUnit();
9288 u->mTextFragment = aTextFragment;
9289 u->mType = Unit::Type::TextFragment;
9290 uint32_t len = aTextFragment->GetLength();
9291 mLength += len;
9292 }
9293
9294 // aLen can be !isValid(), which will get propagated into mLength.
9295 void AppendWithEncode(const nsTextFragment* aTextFragment,
9296 CheckedInt<uint32_t> aLen) {
9297 Unit* u = AddUnit();
9298 u->mTextFragment = aTextFragment;
9299 u->mType = Unit::Type::TextFragmentWithEncode;
9300 mLength += aLen;
9301 }
9302
9303 bool ToString(nsAString& aOut) {
9304 if (!mLength.isValid()) {
9305 return false;
9306 }
9307 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
9308 if (appenderOrErr.isErr()) {
9309 return false;
9310 }
9311
9312 BulkAppender appender{appenderOrErr.unwrap()};
9313
9314 for (StringBuilder* current = this; current;
9315 current = current->mNext.get()) {
9316 uint32_t len = current->mUnits.Length();
9317 for (uint32_t i = 0; i < len; ++i) {
9318 Unit& u = current->mUnits[i];
9319 switch (u.mType) {
9320 case Unit::Type::Atom:
9321 appender.Append(*(u.mAtom));
9322 break;
9323 case Unit::Type::String:
9324 appender.Append(u.mString);
9325 break;
9326 case Unit::Type::StringWithEncode:
9327 EncodeAttrString(u.mString, appender);
9328 break;
9329 case Unit::Type::Literal:
9330 appender.Append(u.mLiteral.AsSpan());
9331 break;
9332 case Unit::Type::TextFragment:
9333 if (u.mTextFragment->Is2b()) {
9334 appender.Append(
9335 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()));
9336 } else {
9337 appender.Append(
9338 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()));
9339 }
9340 break;
9341 case Unit::Type::TextFragmentWithEncode:
9342 if (u.mTextFragment->Is2b()) {
9343 EncodeTextFragment(
9344 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()),
9345 appender);
9346 } else {
9347 EncodeTextFragment(
9348 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()),
9349 appender);
9350 }
9351 break;
9352 default:
9353 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"
, 9353); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown unit type?"
")"); do { *((volatile int*)__null) = 9353; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9354 }
9355 }
9356 }
9357 appender.Finish();
9358 return true;
9359 }
9360
9361 private:
9362 Unit* AddUnit() {
9363 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
9364 new StringBuilder(this);
9365 }
9366 return mLast->mUnits.AppendElement();
9367 }
9368
9369 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
9370 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)
;
9371 aFirst->mLast->mNext = WrapUnique(this);
9372 aFirst->mLast = this;
9373 }
9374
9375 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
9376 size_t flushedUntil = 0;
9377 size_t currentPosition = 0;
9378 for (char16_t c : aStr) {
9379 switch (c) {
9380 case '"':
9381 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9382 aAppender.AppendLiteral(u"&quot;");
9383 flushedUntil = currentPosition + 1;
9384 break;
9385 case '&':
9386 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9387 aAppender.AppendLiteral(u"&amp;");
9388 flushedUntil = currentPosition + 1;
9389 break;
9390 case 0x00A0:
9391 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9392 aAppender.AppendLiteral(u"&nbsp;");
9393 flushedUntil = currentPosition + 1;
9394 break;
9395 default:
9396 break;
9397 }
9398 currentPosition++;
9399 }
9400 if (currentPosition > flushedUntil) {
9401 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9402 }
9403 }
9404
9405 template <class T>
9406 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
9407 size_t flushedUntil = 0;
9408 size_t currentPosition = 0;
9409 for (T c : aStr) {
9410 switch (c) {
9411 case '<':
9412 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9413 aAppender.AppendLiteral(u"&lt;");
9414 flushedUntil = currentPosition + 1;
9415 break;
9416 case '>':
9417 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9418 aAppender.AppendLiteral(u"&gt;");
9419 flushedUntil = currentPosition + 1;
9420 break;
9421 case '&':
9422 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9423 aAppender.AppendLiteral(u"&amp;");
9424 flushedUntil = currentPosition + 1;
9425 break;
9426 case T(0xA0):
9427 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9428 aAppender.AppendLiteral(u"&nbsp;");
9429 flushedUntil = currentPosition + 1;
9430 break;
9431 default:
9432 break;
9433 }
9434 currentPosition++;
9435 }
9436 if (currentPosition > flushedUntil) {
9437 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9438 }
9439 }
9440
9441 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
9442 UniquePtr<StringBuilder> mNext;
9443 StringBuilder* mLast;
9444 // mLength is used only in the first StringBuilder object in the linked list.
9445 CheckedInt<uint32_t> mLength;
9446};
9447
9448static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
9449 "StringBuilder should fit in the target bucket");
9450
9451} // namespace
9452
9453static void AppendEncodedCharacters(const nsTextFragment* aText,
9454 StringBuilder& aBuilder) {
9455 uint32_t numEncodedChars = 0;
9456 uint32_t len = aText->GetLength();
9457 if (aText->Is2b()) {
9458 const char16_t* data = aText->Get2b();
9459 for (uint32_t i = 0; i < len; ++i) {
9460 const char16_t c = data[i];
9461 switch (c) {
9462 case '<':
9463 case '>':
9464 case '&':
9465 case 0x00A0:
9466 ++numEncodedChars;
9467 break;
9468 default:
9469 break;
9470 }
9471 }
9472 } else {
9473 const char* data = aText->Get1b();
9474 for (uint32_t i = 0; i < len; ++i) {
9475 const unsigned char c = data[i];
9476 switch (c) {
9477 case '<':
9478 case '>':
9479 case '&':
9480 case 0x00A0:
9481 ++numEncodedChars;
9482 break;
9483 default:
9484 break;
9485 }
9486 }
9487 }
9488
9489 if (numEncodedChars) {
9490 // For simplicity, conservatively estimate the size of the string after
9491 // encoding. This will result in reserving more memory than we actually
9492 // need, but that should be fine unless the string has an enormous number of
9493 // eg < in it. We subtract 1 for the null terminator, then 1 more for the
9494 // existing character that will be replaced.
9495 constexpr uint32_t maxCharExtraSpace =
9496 std::max({ArrayLength("&lt;"), ArrayLength("&gt;"),
9497 ArrayLength("&amp;"), ArrayLength("&nbsp;")}) -
9498 2;
9499 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9500 CheckedInt<uint32_t> maxExtraSpace =
9501 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9502 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
9503 } else {
9504 aBuilder.Append(aText);
9505 }
9506}
9507
9508static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
9509 const nsAString& aValue) {
9510 const char16_t* c = aValue.BeginReading();
9511 const char16_t* end = aValue.EndReading();
9512
9513 uint32_t numEncodedChars = 0;
9514 while (c < end) {
9515 switch (*c) {
9516 case '"':
9517 case '&':
9518 case 0x00A0:
9519 ++numEncodedChars;
9520 break;
9521 default:
9522 break;
9523 }
9524 ++c;
9525 }
9526
9527 if (!numEncodedChars) {
9528 return 0;
9529 }
9530
9531 // For simplicity, conservatively estimate the size of the string after
9532 // encoding. This will result in reserving more memory than we actually
9533 // need, but that should be fine unless the string has an enormous number of
9534 // & in it. We subtract 1 for the null terminator, then 1 more for the
9535 // existing character that will be replaced.
9536 constexpr uint32_t maxCharExtraSpace =
9537 std::max({ArrayLength("&quot;"), ArrayLength("&amp;"),
9538 ArrayLength("&nbsp;")}) -
9539 2;
9540 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9541 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9542}
9543
9544static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
9545 StringBuilder& aBuilder) {
9546 if (nsAtom* atom = aValue.GetStoredAtom()) {
9547 nsDependentAtomString atomStr(atom);
9548 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
9549 if (space.isValid() && !space.value()) {
9550 aBuilder.Append(atom);
9551 } else {
9552 aBuilder.AppendWithAttrEncode(nsString(atomStr),
9553 space + atomStr.Length());
9554 }
9555 return;
9556 }
9557 // NOTE(emilio): In most cases this will just be a reference to the stored
9558 // nsStringBuffer.
9559 nsString str;
9560 aValue.ToString(str);
9561 auto space = ExtraSpaceNeededForAttrEncoding(str);
9562 if (!space.isValid() || space.value()) {
9563 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
9564 } else {
9565 aBuilder.Append(std::move(str));
9566 }
9567}
9568
9569static void StartElement(Element* aElement, StringBuilder& aBuilder) {
9570 nsAtom* localName = aElement->NodeInfo()->NameAtom();
9571 const int32_t tagNS = aElement->GetNameSpaceID();
9572
9573 aBuilder.Append(u"<");
9574 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
9575 tagNS == kNameSpaceID_MathML6) {
9576 aBuilder.Append(localName);
9577 } else {
9578 aBuilder.Append(nsString(aElement->NodeName()));
9579 }
9580
9581 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
9582 nsAtom* isAttr = ceData->GetIs(aElement);
9583 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
9584 aBuilder.Append(uR"( is=")");
9585 aBuilder.Append(isAttr);
9586 aBuilder.Append(uR"(")");
9587 }
9588 }
9589
9590 uint32_t i = 0;
9591 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
9592 const nsAttrName* name = info.mName;
9593
9594 int32_t attNs = name->NamespaceID();
9595 nsAtom* attName = name->LocalName();
9596
9597 // Filter out any attribute starting with [-|_]moz
9598 // FIXME(emilio): Do we still need this?
9599 nsDependentAtomString attrNameStr(attName);
9600 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
9601 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
9602 continue;
9603 }
9604
9605 aBuilder.Append(u" ");
9606
9607 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
9608 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
9609 // Nothing else required
9610 } else if (attNs == kNameSpaceID_XML2) {
9611 aBuilder.Append(u"xml:");
9612 } else if (attNs == kNameSpaceID_XMLNS1) {
9613 aBuilder.Append(u"xmlns:");
9614 } else if (attNs == kNameSpaceID_XLink4) {
9615 aBuilder.Append(u"xlink:");
9616 } else if (nsAtom* prefix = name->GetPrefix()) {
9617 aBuilder.Append(prefix);
9618 aBuilder.Append(u":");
9619 }
9620
9621 aBuilder.Append(attName);
9622 aBuilder.Append(uR"(=")");
9623 AppendEncodedAttributeValue(*info.mValue, aBuilder);
9624 aBuilder.Append(uR"(")");
9625 }
9626
9627 aBuilder.Append(u">");
9628
9629 /*
9630 // Per HTML spec we should append one \n if the first child of
9631 // pre/textarea/listing is a textnode and starts with a \n.
9632 // But because browsers haven't traditionally had that behavior,
9633 // we're not changing our behavior either - yet.
9634 if (aContent->IsHTMLElement()) {
9635 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
9636 localName == nsGkAtoms::listing) {
9637 nsIContent* fc = aContent->GetFirstChild();
9638 if (fc &&
9639 (fc->NodeType() == nsINode::TEXT_NODE ||
9640 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
9641 const nsTextFragment* text = fc->GetText();
9642 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
9643 aBuilder.Append("\n");
9644 }
9645 }
9646 }
9647 }*/
9648}
9649
9650static inline bool ShouldEscape(nsIContent* aParent) {
9651 if (!aParent || !aParent->IsHTMLElement()) {
9652 return true;
9653 }
9654
9655 static const nsAtom* nonEscapingElements[] = {
9656 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
9657 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
9658 nsGkAtoms::plaintext, nsGkAtoms::noscript};
9659 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
9660 static bool sInitialized = false;
9661 if (!sInitialized) {
9662 sInitialized = true;
9663 for (auto& nonEscapingElement : nonEscapingElements) {
9664 sFilter.add(nonEscapingElement);
9665 }
9666 }
9667
9668 nsAtom* tag = aParent->NodeInfo()->NameAtom();
9669 if (sFilter.mightContain(tag)) {
9670 for (auto& nonEscapingElement : nonEscapingElements) {
9671 if (tag == nonEscapingElement) {
9672 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
9673 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
9674 return true;
9675 }
9676 return false;
9677 }
9678 }
9679 }
9680 return true;
9681}
9682
9683static inline bool IsVoidTag(Element* aElement) {
9684 if (!aElement->IsHTMLElement()) {
9685 return false;
9686 }
9687 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
9688}
9689
9690static bool StartSerializingShadowDOM(
9691 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
9692 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9693 ShadowRoot* shadow = aNode->GetShadowRoot();
9694 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
9695 !aShadowRoots.Contains(shadow))) {
9696 return false;
9697 }
9698
9699 aBuilder.Append(u"<template shadowrootmode=\"");
9700 if (shadow->IsClosed()) {
9701 aBuilder.Append(u"closed\"");
9702 } else {
9703 aBuilder.Append(u"open\"");
9704 }
9705
9706 if (shadow->DelegatesFocus()) {
9707 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
9708 }
9709 if (shadow->Serializable()) {
9710 aBuilder.Append(u" shadowrootserializable=\"\"");
9711 }
9712 if (shadow->Clonable()) {
9713 aBuilder.Append(u" shadowrootclonable=\"\"");
9714 }
9715
9716 aBuilder.Append(u">");
9717
9718 if (!shadow->HasChildren()) {
9719 aBuilder.Append(u"</template>");
9720 return false;
9721 }
9722 return true;
9723}
9724
9725template <SerializeShadowRoots ShouldSerializeShadowRoots>
9726static void SerializeNodeToMarkupInternal(
9727 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
9728 bool aSerializableShadowRoots,
9729 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9730 nsINode* current =
9731 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
9732 if (!current) {
9733 return;
9734 }
9735
9736 nsIContent* next;
9737 while (true) {
9738 bool isVoid = false;
9739 switch (current->NodeType()) {
9740 case nsINode::ELEMENT_NODE: {
9741 Element* elem = current->AsElement();
9742 StartElement(elem, aBuilder);
9743
9744 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9745 if (StartSerializingShadowDOM(
9746 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
9747 current = current->GetShadowRoot()->GetFirstChild();
9748 continue;
9749 }
9750 }
9751
9752 isVoid = IsVoidTag(elem);
9753 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
9754 current = next;
9755 continue;
9756 }
9757 break;
9758 }
9759
9760 case nsINode::TEXT_NODE:
9761 case nsINode::CDATA_SECTION_NODE: {
9762 const nsTextFragment* text = &current->AsText()->TextFragment();
9763 nsIContent* parent = current->GetParent();
9764 if (ShouldEscape(parent)) {
9765 AppendEncodedCharacters(text, aBuilder);
9766 } else {
9767 aBuilder.Append(text);
9768 }
9769 break;
9770 }
9771
9772 case nsINode::COMMENT_NODE: {
9773 aBuilder.Append(u"<!--");
9774 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9775 aBuilder.Append(u"-->");
9776 break;
9777 }
9778
9779 case nsINode::DOCUMENT_TYPE_NODE: {
9780 aBuilder.Append(u"<!DOCTYPE ");
9781 aBuilder.Append(nsString(current->NodeName()));
9782 aBuilder.Append(u">");
9783 break;
9784 }
9785
9786 case nsINode::PROCESSING_INSTRUCTION_NODE: {
9787 aBuilder.Append(u"<?");
9788 aBuilder.Append(nsString(current->NodeName()));
9789 aBuilder.Append(u" ");
9790 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9791 aBuilder.Append(u">");
9792 break;
9793 }
9794 }
9795
9796 while (true) {
9797 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
9798 aBuilder.Append(u"</");
9799 nsIContent* elem = static_cast<nsIContent*>(current);
9800 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
9801 elem->IsMathMLElement()) {
9802 aBuilder.Append(elem->NodeInfo()->NameAtom());
9803 } else {
9804 aBuilder.Append(nsString(current->NodeName()));
9805 }
9806 aBuilder.Append(u">");
9807 }
9808 isVoid = false;
9809
9810 if (current == aRoot) {
9811 return;
9812 }
9813
9814 if ((next = current->GetNextSibling())) {
9815 current = next;
9816 break;
9817 }
9818
9819 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9820 // If the current node is a shadow root, then we must go to its host.
9821 // Since shadow DOMs are serialized declaratively as template elements,
9822 // we serialize the end tag of the template before going back to
9823 // serializing the shadow host.
9824 if (current->IsShadowRoot()) {
9825 current = current->GetContainingShadowHost();
9826 aBuilder.Append(u"</template>");
9827
9828 if (current->HasChildren()) {
9829 current = current->GetFirstChildOfTemplateOrNode();
9830 break;
9831 }
9832 continue;
9833 }
9834 }
9835
9836 current = current->GetParentNode();
9837
9838 // Handle template element. If the parent is a template's content,
9839 // then adjust the parent to be the template element.
9840 if (current != aRoot &&
9841 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
9842 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
9843 nsIContent* fragHost = frag->GetHost();
9844 if (fragHost && fragHost->IsTemplateElement()) {
9845 current = fragHost;
9846 }
9847 }
9848
9849 if (aDescendantsOnly && current == aRoot) {
9850 return;
9851 }
9852 }
9853 }
9854}
9855
9856template <SerializeShadowRoots ShouldSerializeShadowRoots>
9857bool nsContentUtils::SerializeNodeToMarkup(
9858 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9859 bool aSerializableShadowRoots,
9860 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9861 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
9862 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"
, 9862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { *((volatile int*)__null) = 9862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9863
9864 StringBuilder builder;
9865 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9866 if (aDescendantsOnly &&
9867 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
9868 aShadowRoots)) {
9869 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
9870 aRoot->GetShadowRoot()->GetFirstChild(), false, builder,
9871 aSerializableShadowRoots, aShadowRoots);
9872 // The template tag is opened in StartSerializingShadowDOM, so we need
9873 // to close it here before serializing any children of aRoot.
9874 builder.Append(u"</template>");
9875 }
9876 }
9877
9878 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
9879 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
9880 return builder.ToString(aOut);
9881}
9882
9883template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
9884 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9885 bool aSerializableShadowRoots,
9886 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9887template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
9888 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9889 bool aSerializableShadowRoots,
9890 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9891
9892bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
9893 // aUri must start with about: or this isn't the right function to be using.
9894 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"
, 9894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { *((volatile int*)__null) = 9894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9895
9896 // Make sure the global is a window
9897 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"
, 9897); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)"
")"); do { *((volatile int*)__null) = 9897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9898 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
9899 if (!win) {
9900 return false;
9901 }
9902
9903 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
9904 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"
, 9904); return false; } } while (false)
;
9905
9906 // First check the scheme to avoid getting long specs in the common case.
9907 if (!principal->SchemeIs("about")) {
9908 return false;
9909 }
9910
9911 nsAutoCString spec;
9912 principal->GetAsciiSpec(spec);
9913
9914 return spec.EqualsASCII(aUri);
9915}
9916
9917/* static */
9918void nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell,
9919 bool aVisible) {
9920 if (!aDocShell) {
9921 return;
9922 }
9923 auto pref = aVisible ? ScrollbarPreference::Auto : ScrollbarPreference::Never;
9924 nsDocShell::Cast(aDocShell)->SetScrollbarPreference(pref);
9925}
9926
9927/* static */
9928nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
9929 if (!aTarget) {
9930 return nullptr;
9931 }
9932
9933 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
9934 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
9935 bool ignore;
9936 innerWindow =
9937 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
9938 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
9939 // Nothing else to do
9940 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
9941 do_QueryInterface(aTarget)) {
9942 innerWindow = helper->GetOwnerWindow();
9943 }
9944
9945 if (innerWindow) {
9946 return innerWindow->GetDocShell();
9947 }
9948
9949 return nullptr;
9950}
9951
9952/*
9953 * Note: this function only relates to figuring out HTTPS state, which is an
9954 * input to the Secure Context algorithm. We are not actually implementing any
9955 * part of the Secure Context algorithm itself here.
9956 *
9957 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
9958 * nsIChannel as described in the Fetch and HTML specs, but making channels
9959 * know about whether they should inherit HTTPS state, propagating information
9960 * about who the channel's "client" is, exposing GetHttpsState API on channels
9961 * and modifying the various cache implementations to store and retrieve HTTPS
9962 * state involves a huge amount of code (see bug 1220687). We avoid that for
9963 * now using this function.
9964 *
9965 * This function takes advantage of the observation that we can return true if
9966 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
9967 * the document's origin (e.g. the origin has a scheme of 'https' or host
9968 * 'localhost' etc.). Since we generally propagate a creator document's origin
9969 * onto data:, blob:, etc. documents, this works for them too.
9970 *
9971 * The scenario where this observation breaks down is sandboxing without the
9972 * 'allow-same-origin' flag, since in this case a document is given a unique
9973 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
9974 * by using the origin that the document would have had had it not been
9975 * sandboxed.
9976 *
9977 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
9978 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
9979 * sandboxing is limited to the immediate sandbox. In the case that aDocument
9980 * should inherit its origin (e.g. data: URI) but its parent has ended up
9981 * with a unique origin due to sandboxing further up the parent chain we may
9982 * end up returning false when we would ideally return true (since we will
9983 * examine the parent's origin for 'https' and not finding it.) This means
9984 * that we may restrict the privileges of some pages unnecessarily in this
9985 * edge case.
9986 */
9987/* static */
9988bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
9989 if (!aDocument) {
9990 return false;
9991 }
9992
9993 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
9994
9995 if (principal->IsSystemPrincipal()) {
9996 return true;
9997 }
9998
9999 // If aDocument is sandboxed, try and get the principal that it would have
10000 // been given had it not been sandboxed:
10001 if (principal->GetIsNullPrincipal() &&
10002 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
10003 nsIChannel* channel = aDocument->GetChannel();
10004 if (channel) {
10005 nsCOMPtr<nsIScriptSecurityManager> ssm =
10006 nsContentUtils::GetSecurityManager();
10007 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
10008 channel, getter_AddRefs(principal));
10009 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10010 return false;
10011 }
10012 if (principal->IsSystemPrincipal()) {
10013 // If a document with the system principal is sandboxing a subdocument
10014 // that would normally inherit the embedding element's principal (e.g.
10015 // a srcdoc document) then the embedding document does not trust the
10016 // content that is written to the embedded document. Unlike when the
10017 // embedding document is https, in this case we have no indication as
10018 // to whether the embedded document's contents are delivered securely
10019 // or not, and the sandboxing would possibly indicate that they were
10020 // not. To play it safe we return false here. (See bug 1162772
10021 // comment 73-80.)
10022 return false;
10023 }
10024 }
10025 }
10026
10027 if (principal->GetIsNullPrincipal()) {
10028 return false;
10029 }
10030
10031 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"
, 10031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()"
")"); do { *((volatile int*)__null) = 10031; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10032
10033 return principal->GetIsOriginPotentiallyTrustworthy();
10034}
10035
10036/* static */
10037bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
10038 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"
, 10038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { *((volatile int*)__null) = 10038; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10039
10040 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
10041 nsCOMPtr<nsIPrincipal> principal;
10042 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
10043 aChannel, getter_AddRefs(principal));
10044 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10045 return false;
10046 }
10047
10048 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10049
10050 if (principal->IsSystemPrincipal()) {
10051 // If the load would've been sandboxed, treat this load as an untrusted
10052 // load, as system code considers sandboxed resources insecure.
10053 return !loadInfo->GetLoadingSandboxed();
10054 }
10055
10056 if (principal->GetIsNullPrincipal()) {
10057 return false;
10058 }
10059
10060 if (const RefPtr<WindowContext> windowContext =
10061 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
10062 if (!windowContext->GetIsSecureContext()) {
10063 return false;
10064 }
10065 }
10066
10067 return principal->GetIsOriginPotentiallyTrustworthy();
10068}
10069
10070/* static */
10071void nsContentUtils::TryToUpgradeElement(Element* aElement) {
10072 NodeInfo* nodeInfo = aElement->NodeInfo();
10073 RefPtr<nsAtom> typeAtom =
10074 aElement->GetCustomElementData()->GetCustomElementType();
10075
10076 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"
, 10076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 10076; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10077 CustomElementDefinition* definition =
10078 nsContentUtils::LookupCustomElementDefinition(
10079 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
10080 nodeInfo->NamespaceID(), typeAtom);
10081 if (definition) {
10082 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
10083 } else {
10084 // Add an unresolved custom element that is a candidate for upgrade when a
10085 // custom element is connected to the document.
10086 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
10087 }
10088}
10089
10090MOZ_CAN_RUN_SCRIPT
10091static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
10092 Document* aDoc, NodeInfo* aNodeInfo,
10093 CustomElementConstructor* aConstructor,
10094 ErrorResult& aRv, FromParser aFromParser) {
10095 JS::Rooted<JS::Value> constructResult(aCx);
10096 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
10097 CallbackFunction::eRethrowExceptions);
10098 if (aRv.Failed()) {
10099 return;
10100 }
10101
10102 RefPtr<Element> element;
10103 // constructResult is an ObjectValue because construction with a callback
10104 // always forms the return value from a JSObject.
10105 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
10106 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10107 if (!element || !element->IsHTMLElement()) {
10108 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10109 "HTMLElement");
10110 return;
10111 }
10112 } else {
10113 if (!element || !element->IsXULElement()) {
10114 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10115 "XULElement");
10116 return;
10117 }
10118 }
10119
10120 nsAtom* localName = aNodeInfo->NameAtom();
10121
10122 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
10123 element->HasChildren() || element->GetAttrCount() ||
10124 element->NodeInfo()->NameAtom() != localName) {
10125 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
10126 return;
10127 }
10128
10129 if (element->IsHTMLElement()) {
10130 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
10131 !(aFromParser & FROM_PARSER_NETWORK));
10132 }
10133
10134 element.forget(aElement);
10135}
10136
10137/* static */
10138nsresult nsContentUtils::NewXULOrHTMLElement(
10139 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
10140 FromParser aFromParser, nsAtom* aIsAtom,
10141 mozilla::dom::CustomElementDefinition* aDefinition) {
10142 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
10143 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"
, 10145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10145; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
10144 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"
, 10145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10145; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10145 "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"
, 10145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10145; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10146
10147 nsAtom* name = nodeInfo->NameAtom();
10148 int32_t tag = eHTMLTag_unknown;
10149 bool isCustomElementName = false;
10150 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
3
Taking false branch
10151 tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
10152 isCustomElementName =
10153 (tag == eHTMLTag_userdefined &&
10154 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
10155 } else { // kNameSpaceID_XUL
10156 if (aIsAtom) {
4
Assuming 'aIsAtom' is null
5
Taking false branch
10157 // Make sure the customized built-in element to be constructed confirms
10158 // to our naming requirement, i.e. [is] must be a dashed name and
10159 // the tag name must not.
10160 // if so, set isCustomElementName to false to kick off all the logics
10161 // that pick up aIsAtom.
10162 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
10163 !nsContentUtils::IsNameWithDash(name)) {
10164 isCustomElementName = false;
10165 } else {
10166 isCustomElementName =
10167 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10168 }
10169 } else {
10170 isCustomElementName =
10171 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10172 }
10173 }
10174
10175 nsAtom* tagAtom = nodeInfo->NameAtom();
10176 nsAtom* typeAtom = nullptr;
10177 bool isCustomElement = isCustomElementName
5.1
'isCustomElementName' is true
|| aIsAtom;
10178 if (isCustomElement
5.2
'isCustomElement' is true
) {
10179 typeAtom = isCustomElementName
6.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
6
Taking true branch
7
'?' condition is true
10180 }
10181
10182 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"
, 10182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { *((volatile int*)__null) = 10182; __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
10183
10184 // https://dom.spec.whatwg.org/#concept-create-element
10185 // We only handle the "synchronous custom elements flag is set" now.
10186 // For the unset case (e.g. cloning a node), see bug 1319342 for that.
10187 // Step 4.
10188 RefPtr<CustomElementDefinition> definition = aDefinition;
10189 if (isCustomElement
12.1
'isCustomElement' is true
&& !definition) {
13
Taking false branch
10190 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"
, 10190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 10190; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10191 definition = nsContentUtils::LookupCustomElementDefinition(
10192 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
10193 typeAtom);
10194 }
10195
10196 // It might be a problem that parser synchronously calls constructor, so filed
10197 // bug 1378079 to figure out what we should do for parser case.
10198 if (definition) {
14
Taking true branch
10199 /*
10200 * Synchronous custom elements flag is determined by 3 places in spec,
10201 * 1) create an element for a token, the flag is determined by
10202 * "will execute script" which is not originally created
10203 * for the HTML fragment parsing algorithm.
10204 * 2) createElement and createElementNS, the flag is the same as
10205 * NOT_FROM_PARSER.
10206 * 3) clone a node, our implementation will not go into this function.
10207 * For the unset case which is non-synchronous only applied for
10208 * inner/outerHTML.
10209 */
10210 bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT;
15
Assuming 'aFromParser' is not equal to FROM_PARSER_FRAGMENT
10211 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
10212 // use entry global in those places that are called from JS APIs and use the
10213 // node document's global object if it is called from parser.
10214 nsIGlobalObject* global;
10215 if (aFromParser == dom::NOT_FROM_PARSER) {
16
Assuming 'aFromParser' is equal to NOT_FROM_PARSER
17
Taking true branch
10216 global = GetEntryGlobal();
10217
10218 // Documents created from the PrototypeDocumentSink always use
10219 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
10220 // document in that case.
10221 if (!global) {
18
Assuming 'global' is non-null
19
Taking false branch
10222 Document* doc = nodeInfo->GetDocument();
10223 if (doc && doc->LoadedFromPrototype()) {
10224 global = doc->GetScopeObject();
10225 }
10226 }
10227 } else {
10228 global = nodeInfo->GetDocument()->GetScopeObject();
10229 }
10230 if (!global
19.1
'global' is non-null
) {
20
Taking false branch
10231 // In browser chrome code, one may have access to a document which doesn't
10232 // have scope object anymore.
10233 return NS_ERROR_FAILURE;
10234 }
10235
10236 AutoAllowLegacyScriptExecution exemption;
10237 AutoEntryScript aes(global, "create custom elements");
10238 JSContext* cx = aes.cx();
10239 ErrorResult rv;
10240
10241 // Step 5.
10242 if (definition->IsCustomBuiltIn()) {
21
Taking true branch
10243 // SetupCustomElement() should be called with an element that don't have
10244 // CustomElementData setup, if not we will hit the assertion in
10245 // SetCustomElementData().
10246 // Built-in element
10247 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
22
Taking false branch
10248 *aResult =
10249 CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10250 } else {
10251 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
23
Assigning value
10252 }
10253 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
24
Called C++ object pointer is null
10254 if (synchronousCustomElements) {
10255 CustomElementRegistry::Upgrade(*aResult, definition, rv);
10256 if (rv.MaybeSetPendingException(cx)) {
10257 aes.ReportException();
10258 }
10259 } else {
10260 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10261 }
10262
10263 return NS_OK;
10264 }
10265
10266 // Step 6.1.
10267 if (synchronousCustomElements) {
10268 definition->mPrefixStack.AppendElement(nodeInfo->GetPrefixAtom());
10269 RefPtr<Document> doc = nodeInfo->GetDocument();
10270 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
10271 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
10272 aFromParser);
10273 if (rv.MaybeSetPendingException(cx)) {
10274 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10275 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
10276 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
10277 } else {
10278 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10279 }
10280 (*aResult)->SetDefined(false);
10281 }
10282 definition->mPrefixStack.RemoveLastElement();
10283 return NS_OK;
10284 }
10285
10286 // Step 6.2.
10287 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10288 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10289 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10290 } else {
10291 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10292 }
10293 (*aResult)->SetCustomElementData(
10294 MakeUnique<CustomElementData>(definition->mType));
10295 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10296 return NS_OK;
10297 }
10298
10299 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10300 // Per the Custom Element specification, unknown tags that are valid custom
10301 // element names should be HTMLElement instead of HTMLUnknownElement.
10302 if (isCustomElementName) {
10303 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10304 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10305 } else {
10306 *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10307 }
10308 } else {
10309 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10310 }
10311
10312 if (!*aResult) {
10313 return NS_ERROR_OUT_OF_MEMORY;
10314 }
10315
10316 if (isCustomElement) {
10317 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
10318 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
10319 }
10320
10321 return NS_OK;
10322}
10323
10324CustomElementRegistry* nsContentUtils::GetCustomElementRegistry(
10325 Document* aDoc) {
10326 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"
, 10326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")")
; do { *((volatile int*)__null) = 10326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10327
10328 if (!aDoc->GetDocShell()) {
10329 return nullptr;
10330 }
10331
10332 nsPIDOMWindowInner* window = aDoc->GetInnerWindow();
10333 if (!window) {
10334 return nullptr;
10335 }
10336
10337 return window->CustomElements();
10338}
10339
10340/* static */
10341CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
10342 Document* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
10343 nsAtom* aTypeAtom) {
10344 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
10345 return nullptr;
10346 }
10347
10348 RefPtr<CustomElementRegistry> registry = GetCustomElementRegistry(aDoc);
10349 if (!registry) {
10350 return nullptr;
10351 }
10352
10353 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
10354 aTypeAtom);
10355}
10356
10357/* static */
10358void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
10359 nsAtom* aTypeName) {
10360 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"
, 10360); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10361
10362 Document* doc = aElement->OwnerDoc();
10363 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10364 if (registry) {
10365 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
10366 }
10367}
10368
10369/* static */
10370void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
10371 nsAtom* aTypeName) {
10372 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"
, 10372); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10372; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10373
10374 Document* doc = aElement->OwnerDoc();
10375 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10376 if (registry) {
10377 registry->RegisterUnresolvedElement(aElement, aTypeName);
10378 }
10379}
10380
10381/* static */
10382void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
10383 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"
, 10383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10383; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10384
10385 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
10386 Document* doc = aElement->OwnerDoc();
10387 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10388 if (registry) {
10389 registry->UnregisterUnresolvedElement(aElement, typeAtom);
10390 }
10391}
10392
10393/* static */
10394void nsContentUtils::EnqueueUpgradeReaction(
10395 Element* aElement, CustomElementDefinition* aDefinition) {
10396 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"
, 10396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10397
10398 Document* doc = aElement->OwnerDoc();
10399
10400 // No DocGroup means no custom element reactions stack.
10401 if (!doc->GetDocGroup()) {
10402 return;
10403 }
10404
10405 CustomElementReactionsStack* stack =
10406 doc->GetDocGroup()->CustomElementReactionsStack();
10407 stack->EnqueueUpgradeReaction(aElement, aDefinition);
10408}
10409
10410/* static */
10411void nsContentUtils::EnqueueLifecycleCallback(
10412 ElementCallbackType aType, Element* aCustomElement,
10413 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
10414 // No DocGroup means no custom element reactions stack.
10415 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
10416 return;
10417 }
10418
10419 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
10420 aDefinition);
10421}
10422
10423/* static */
10424CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
10425 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
10426 if (aState.IsNull()) {
10427 return void_t{};
10428 }
10429 const auto& state = aState.Value();
10430 if (state.IsFile()) {
10431 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
10432 return {std::move(impl)};
10433 }
10434 if (state.IsUSVString()) {
10435 return state.GetAsUSVString();
10436 }
10437 return state.GetAsFormData()->ConvertToCustomElementFormValue();
10438}
10439
10440/* static */
10441Nullable<OwningFileOrUSVStringOrFormData>
10442nsContentUtils::ExtractFormAssociatedCustomElementValue(
10443 nsIGlobalObject* aGlobal,
10444 const mozilla::dom::CustomElementFormValue& aCEValue) {
10445 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"
, 10445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { *((volatile int*)__null) = 10445; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10446
10447 OwningFileOrUSVStringOrFormData value;
10448 switch (aCEValue.type()) {
10449 case CustomElementFormValue::TBlobImpl: {
10450 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
10451 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10451)
) {
10452 return {};
10453 }
10454 value.SetAsFile() = file;
10455 } break;
10456
10457 case CustomElementFormValue::TnsString:
10458 value.SetAsUSVString() = aCEValue.get_nsString();
10459 break;
10460
10461 case CustomElementFormValue::TArrayOfFormDataTuple: {
10462 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
10463 auto formData = MakeRefPtr<FormData>();
10464
10465 for (auto i = 0ul; i < array.Length(); ++i) {
10466 const auto& item = array.ElementAt(i);
10467 switch (item.value().type()) {
10468 case FormDataValue::TnsString:
10469 formData->AddNameValuePair(item.name(),
10470 item.value().get_nsString());
10471 break;
10472
10473 case FormDataValue::TBlobImpl: {
10474 auto blobImpl = item.value().get_BlobImpl();
10475 auto* blob = Blob::Create(aGlobal, blobImpl);
10476 formData->AddNameBlobPair(item.name(), blob);
10477 } break;
10478
10479 default:
10480 continue;
10481 }
10482 }
10483
10484 value.SetAsFormData() = formData;
10485 } break;
10486 case CustomElementFormValue::Tvoid_t:
10487 return {};
10488 default:
10489 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"
, 10489)
;
10490 return {};
10491 }
10492 return value;
10493}
10494
10495/* static */
10496void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
10497 Document* aDocument, nsTArray<nsIContent*>& aElements) {
10498 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"
, 10498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { *((volatile int*)__null) = 10498; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10499#ifdef DEBUG1
10500 size_t oldLength = aElements.Length();
10501#endif
10502
10503 if (PresShell* presShell = aDocument->GetPresShell()) {
10504 if (ScrollContainerFrame* rootScrollContainerFrame =
10505 presShell->GetRootScrollContainerFrame()) {
10506 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
10507 }
10508 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
10509 canvasFrame->AppendAnonymousContentTo(aElements, 0);
10510 }
10511 }
10512
10513#ifdef DEBUG1
10514 for (size_t i = oldLength; i < aElements.Length(); i++) {
10515 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"
, 10517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10516 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"
, 10517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10517 "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"
, 10517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10518 }
10519#endif
10520}
10521
10522static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
10523 nsTArray<nsIContent*>& aKids,
10524 uint32_t aFlags) {
10525 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
10526 ac->AppendAnonymousContentTo(aKids, aFlags);
10527 }
10528}
10529
10530/* static */
10531void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
10532 nsTArray<nsIContent*>& aKids,
10533 uint32_t aFlags) {
10534 if (aContent->MayHaveAnonymousChildren()) {
10535 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
10536 // NAC created by the element's primary frame.
10537 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
10538
10539 // NAC created by any other non-primary frames for the element.
10540 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
10541 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
10542 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
10543 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"
, 10543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { *((volatile int*)__null) = 10543; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10544 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
10545 aFlags);
10546 }
10547 }
10548
10549 // Get manually created NAC (editor resize handles, etc.).
10550 if (auto nac = static_cast<ManualNACArray*>(
10551 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
10552 aKids.AppendElements(*nac);
10553 }
10554 }
10555
10556 // The root scroll frame is not the primary frame of the root element.
10557 // Detect and handle this case.
10558 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
10559 aContent == aContent->OwnerDoc()->GetRootElement()) {
10560 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
10561 }
10562}
10563
10564bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
10565 nsIPrincipal* aDefaultTriggeringPrincipal,
10566 CORSMode aCORSMode) {
10567 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10568 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
10569 getter_AddRefs(triggeringPrincipal));
10570 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"
, 10570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "triggeringPrincipal"
")"); do { *((volatile int*)__null) = 10570; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10571
10572 Document* doc = aLoadingNode->OwnerDoc();
10573 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
10574}
10575
10576bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
10577 nsIPrincipal* aTriggeringPrincipal,
10578 CORSMode aCORSMode, Document* aDoc) {
10579 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
10580 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
10581 aDoc);
10582}
10583
10584/* static */
10585bool nsContentUtils::QueryTriggeringPrincipal(
10586 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
10587 nsIPrincipal** aTriggeringPrincipal) {
10588 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"
, 10588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { *((volatile int*)__null) = 10588; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10589 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"
, 10589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
")"); do { *((volatile int*)__null) = 10589; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10590
10591 bool result = false;
10592 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
10593 if (!loadingPrincipal) {
10594 loadingPrincipal = aLoadingNode->NodePrincipal();
10595 }
10596
10597 // If aLoadingNode is content, bail out early.
10598 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
10599 loadingPrincipal.forget(aTriggeringPrincipal);
10600 return result;
10601 }
10602
10603 nsAutoString loadingStr;
10604 if (aLoadingNode->IsElement()) {
10605 aLoadingNode->AsElement()->GetAttr(
10606 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
10607 }
10608
10609 // Fall back if 'triggeringprincipal' isn't specified,
10610 if (loadingStr.IsEmpty()) {
10611 loadingPrincipal.forget(aTriggeringPrincipal);
10612 return result;
10613 }
10614
10615 nsCString binary;
10616 nsCOMPtr<nsIPrincipal> serializedPrin =
10617 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
10618 if (serializedPrin) {
10619 result = true;
10620 serializedPrin.forget(aTriggeringPrincipal);
10621 }
10622
10623 if (!result) {
10624 // Fallback if the deserialization is failed.
10625 loadingPrincipal.forget(aTriggeringPrincipal);
10626 }
10627
10628 return result;
10629}
10630
10631/* static */
10632void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
10633 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
10634 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
10635 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"
, 10635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequestContextID"
")"); do { *((volatile int*)__null) = 10635; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10636
10637 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
10638 if (result) {
10639 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
10640 // indicating it's a favicon loading.
10641 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
10642
10643 nsAutoString requestContextID;
10644 if (aLoadingNode->IsElement()) {
10645 aLoadingNode->AsElement()->GetAttr(
10646 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
10647 }
10648 nsresult rv;
10649 int64_t val = requestContextID.ToInteger64(&rv);
10650 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
10651 } else {
10652 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
10653 }
10654}
10655
10656/* static */
10657nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
10658 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
10659 JS::MutableHandle<JS::Value> aValue) {
10660 if (aTransfer.IsEmpty()) {
10661 return NS_OK;
10662 }
10663
10664 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
10665 if (!array) {
10666 return NS_ERROR_OUT_OF_MEMORY;
10667 }
10668
10669 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
10670 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
10671 if (!object) {
10672 continue;
10673 }
10674
10675 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"
, 10676)
10676 !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"
, 10676)
) {
10677 return NS_ERROR_OUT_OF_MEMORY;
10678 }
10679 }
10680
10681 aValue.setObject(*array);
10682 return NS_OK;
10683}
10684
10685/* static */
10686void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
10687 JS::Handle<JS::Value> aValue,
10688 const StructuredSerializeOptions& aOptions,
10689 JS::MutableHandle<JS::Value> aRetval,
10690 ErrorResult& aError) {
10691 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
10692 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
10693 aCx, aOptions.mTransfer, &transferArray);
10694 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"
, 10694)
) {
10695 return;
10696 }
10697
10698 JS::CloneDataPolicy clonePolicy;
10699 // We are definitely staying in the same agent cluster.
10700 clonePolicy.allowIntraClusterClonableSharedObjects();
10701 if (aGlobal->IsSharedMemoryAllowed()) {
10702 clonePolicy.allowSharedMemoryObjects();
10703 }
10704
10705 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
10706 StructuredCloneHolder::TransferringSupported,
10707 JS::StructuredCloneScope::SameProcess);
10708 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
10709 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"
, 10709)
) {
10710 return;
10711 }
10712
10713 holder.Read(aGlobal, aCx, aRetval, clonePolicy, aError);
10714 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"
, 10714)
) {
10715 return;
10716 }
10717
10718 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
10719 Unused << ports;
10720}
10721
10722/* static */
10723bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
10724 nsCOMPtr<nsIPrincipal> principal;
10725 RefPtr<Element> targetElement =
10726 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
10727 nsCOMPtr<nsIBrowser> targetBrowser;
10728 if (targetElement) {
10729 targetBrowser = targetElement->AsBrowser();
10730 }
10731 bool isRemoteBrowser = false;
10732 if (targetBrowser) {
10733 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
10734 }
10735
10736 if (isRemoteBrowser) {
10737 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
10738 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
10739 : false;
10740 }
10741
10742 if (targetElement) {
10743 Document* doc = targetElement->GetUncomposedDoc();
10744 if (doc) {
10745 RefPtr<WindowContext> wc = doc->GetWindowContext();
10746 if (wc) {
10747 return wc->TopWindowContext()->GetShortcutsPermission() ==
10748 nsIPermissionManager::DENY_ACTION;
10749 }
10750 }
10751 }
10752
10753 return false;
10754}
10755
10756/**
10757 * Checks whether the given type is a supported document type for
10758 * loading within the nsObjectLoadingContent specified by aContent.
10759 *
10760 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
10761 * NOTE Does not take content policy or capabilities into account
10762 */
10763static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
10764 nsCOMPtr<nsIWebNavigationInfo> info(
10765 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
10766 if (!info) {
10767 return false;
10768 }
10769
10770 uint32_t supported;
10771 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
10772
10773 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10774 return false;
10775 }
10776
10777 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
10778 // Don't want to support plugins as documents
10779 return supported != nsIWebNavigationInfo::FALLBACK;
10780 }
10781
10782 // Try a stream converter
10783 // NOTE: We treat any type we can convert from as a supported type. If a
10784 // type is not actually supported, the URI loader will detect that and
10785 // return an error, and we'll fallback.
10786 nsCOMPtr<nsIStreamConverterService> convServ =
10787 do_GetService("@mozilla.org/streamConverters;1");
10788 bool canConvert = false;
10789 if (convServ) {
10790 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
10791 }
10792 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
10793}
10794
10795/* static */
10796uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
10797 const nsCString& aMIMEType) {
10798 if (aMIMEType.IsEmpty()) {
10799 return nsIObjectLoadingContent::TYPE_FALLBACK;
10800 }
10801
10802 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
10803 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10804 }
10805
10806 // Faking support of the PDF content as a document for EMBED tags
10807 // when internal PDF viewer is enabled.
10808 if (aMIMEType.LowerCaseEqualsLiteral("application/pdf") && IsPDFJSEnabled()) {
10809 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10810 }
10811
10812 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
10813 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10814 }
10815
10816 return nsIObjectLoadingContent::TYPE_FALLBACK;
10817}
10818
10819/* static */
10820bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
10821 return !aString.IsEmpty() && aString[0] == '#';
10822}
10823
10824// We use only 53 bits for the ID so that it can be converted to and from a JS
10825// value without loss of precision. The upper bits of the ID hold the process
10826// ID. The lower bits identify the object itself.
10827static constexpr uint64_t kIdTotalBits = 53;
10828static constexpr uint64_t kIdProcessBits = 22;
10829static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
10830
10831/* static */
10832uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
10833 uint64_t processId = 0;
10834 if (XRE_IsContentProcess()) {
10835 ContentChild* cc = ContentChild::GetSingleton();
10836 processId = cc->GetID();
10837 }
10838
10839 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"
, 10839); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { *((volatile int*)__null) = 10839; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10840 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
10841
10842 uint64_t id = aId;
10843 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"
, 10843); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { *((volatile int*)__null) = 10843; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10844 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
10845
10846 return (processBits << kIdBits) | bits;
10847}
10848
10849/* static */
10850std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId(
10851 uint64_t aId) {
10852 return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)};
10853}
10854
10855// Next process-local Tab ID.
10856static uint64_t gNextTabId = 0;
10857
10858/* static */
10859uint64_t nsContentUtils::GenerateTabId() {
10860 return GenerateProcessSpecificId(++gNextTabId);
10861}
10862
10863// Next process-local Browser ID.
10864static uint64_t gNextBrowserId = 0;
10865
10866/* static */
10867uint64_t nsContentUtils::GenerateBrowserId() {
10868 return GenerateProcessSpecificId(++gNextBrowserId);
10869}
10870
10871// Next process-local Browsing Context ID.
10872static uint64_t gNextBrowsingContextId = 0;
10873
10874/* static */
10875uint64_t nsContentUtils::GenerateBrowsingContextId() {
10876 return GenerateProcessSpecificId(++gNextBrowsingContextId);
10877}
10878
10879// Next process-local Window ID.
10880static uint64_t gNextWindowId = 0;
10881
10882/* static */
10883uint64_t nsContentUtils::GenerateWindowId() {
10884 return GenerateProcessSpecificId(++gNextWindowId);
10885}
10886
10887// Next process-local load.
10888static Atomic<uint64_t> gNextLoadIdentifier(0);
10889
10890/* static */
10891uint64_t nsContentUtils::GenerateLoadIdentifier() {
10892 return GenerateProcessSpecificId(++gNextLoadIdentifier);
10893}
10894
10895/* static */
10896bool nsContentUtils::GetUserIsInteracting() {
10897 return UserInteractionObserver::sUserActive;
10898}
10899
10900/* static */
10901bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
10902 nsACString& aResult) {
10903 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
10904 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10905 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
10906 }
10907 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
10908}
10909
10910/* static */
10911bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
10912 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10913 mozilla::dom::PBrowser::PBrowserStart) {
10914 switch (aMsg.type()) {
10915 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
10916 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10917 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
10918 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10919 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10920 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10921 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
10922 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10923 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
10924 return true;
10925 }
10926 }
10927 return false;
10928}
10929
10930/* static */
10931bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) {
10932 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10933 mozilla::dom::PBrowser::PBrowserStart) {
10934 switch (aMsg.type()) {
10935 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10936 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10937 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10938 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10939 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10940 return true;
10941 }
10942 }
10943 return false;
10944}
10945
10946static const char* kUserInteractionInactive = "user-interaction-inactive";
10947static const char* kUserInteractionActive = "user-interaction-active";
10948
10949void nsContentUtils::UserInteractionObserver::Init() {
10950 // Listen for the observer messages from EventStateManager which are telling
10951 // us whether or not the user is interacting.
10952 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10953 obs->AddObserver(this, kUserInteractionInactive, false);
10954 obs->AddObserver(this, kUserInteractionActive, false);
10955
10956 // We can't register ourselves as an annotator yet, as the
10957 // BackgroundHangMonitor hasn't started yet. It will have started by the
10958 // time we have the chance to spin the event loop.
10959 RefPtr<UserInteractionObserver> self = this;
10960 NS_DispatchToMainThread(NS_NewRunnableFunction(
10961 "nsContentUtils::UserInteractionObserver::Init",
10962 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
10963}
10964
10965void nsContentUtils::UserInteractionObserver::Shutdown() {
10966 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10967 if (obs) {
10968 obs->RemoveObserver(this, kUserInteractionInactive);
10969 obs->RemoveObserver(this, kUserInteractionActive);
10970 }
10971
10972 BackgroundHangMonitor::UnregisterAnnotator(*this);
10973}
10974
10975/**
10976 * NB: This function is always called by the BackgroundHangMonitor thread.
10977 * Plan accordingly
10978 */
10979void nsContentUtils::UserInteractionObserver::AnnotateHang(
10980 BackgroundHangAnnotations& aAnnotations) {
10981 // NOTE: Only annotate the hang report if the user is known to be interacting.
10982 if (sUserActive) {
10983 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
10984 }
10985}
10986
10987NS_IMETHODIMPnsresult
10988nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
10989 const char* aTopic,
10990 const char16_t* aData) {
10991 if (!strcmp(aTopic, kUserInteractionInactive)) {
10992 if (sUserActive && XRE_IsParentProcess()) {
10993 glean::RecordPowerMetrics();
10994 }
10995 sUserActive = false;
10996 } else if (!strcmp(aTopic, kUserInteractionActive)) {
10997 if (!sUserActive && XRE_IsParentProcess()) {
10998 glean::RecordPowerMetrics();
10999
11000 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
11001 do_GetService("@mozilla.org/widget/useridleservice;1");
11002 if (idleService) {
11003 idleService->ResetIdleTimeOut(0);
11004 }
11005 }
11006
11007 sUserActive = true;
11008 } else {
11009 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"
, 11009)
;
11010 }
11011 return NS_OK;
11012}
11013
11014Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
11015NS_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"
, 11015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
11015; __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"
, 11015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 11015; __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"
, 11015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 11015
; __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"
, 11015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 11015; __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"
, 11015); 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((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
11016
11017/* static */
11018bool nsContentUtils::IsSpecialName(const nsAString& aName) {
11019 return aName.LowerCaseEqualsLiteral("_blank") ||
11020 aName.LowerCaseEqualsLiteral("_top") ||
11021 aName.LowerCaseEqualsLiteral("_parent") ||
11022 aName.LowerCaseEqualsLiteral("_self");
11023}
11024
11025/* static */
11026bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
11027 return !aName.IsEmpty() && !IsSpecialName(aName);
11028}
11029
11030// Unfortunately, we can't unwrap an IDL object using only a concrete type.
11031// We need to calculate type data based on the IDL typename. Which means
11032// wrapping our templated function in a macro.
11033#define EXTRACT_EXN_VALUES(T, ...) \
11034 ExtractExceptionValues<mozilla::dom::prototypes::id::T, \
11035 T##_Binding::NativeType, T>(__VA_ARGS__) \
11036 .isOk()
11037
11038template <prototypes::ID PrototypeID, class NativeType, typename T>
11039static Result<Ok, nsresult> ExtractExceptionValues(
11040 JSContext* aCx, JS::Handle<JSObject*> aObj, nsAString& aSourceSpecOut,
11041 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11042 AssertStaticUnwrapOK<PrototypeID>();
11043 RefPtr<T> exn;
11044 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)
;
11045
11046 exn->GetFilename(aCx, aSourceSpecOut);
11047 if (!aSourceSpecOut.IsEmpty()) {
11048 *aLineOut = exn->LineNumber(aCx);
11049 *aColumnOut = exn->ColumnNumber();
11050 }
11051
11052 exn->GetName(aMessageOut);
11053 aMessageOut.AppendLiteral(": ");
11054
11055 nsAutoString message;
11056 exn->GetMessageMoz(message);
11057 aMessageOut.Append(message);
11058 return Ok();
11059}
11060
11061/* static */
11062void nsContentUtils::ExtractErrorValues(
11063 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
11064 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11065 nsAutoString sourceSpec;
11066 ExtractErrorValues(aCx, aValue, sourceSpec, aLineOut, aColumnOut,
11067 aMessageOut);
11068 CopyUTF16toUTF8(sourceSpec, aSourceSpecOut);
11069}
11070
11071/* static */
11072void nsContentUtils::ExtractErrorValues(
11073 JSContext* aCx, JS::Handle<JS::Value> aValue, nsAString& aSourceSpecOut,
11074 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11075 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"
, 11075); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { *((volatile int*)__null) = 11075; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11076 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"
, 11076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { *((volatile int*)__null) = 11076; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11077
11078 if (aValue.isObject()) {
11079 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
11080
11081 // Try to process as an Error object. Use the file/line/column values
11082 // from the Error as they will be more specific to the root cause of
11083 // the problem.
11084 JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr;
11085 if (err) {
11086 // Use xpc to extract the error message only. We don't actually send
11087 // this report anywhere.
11088 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
11089 report->Init(err,
11090 nullptr, // toString result
11091 false, // chrome
11092 0); // window ID
11093
11094 if (!report->mFileName.IsEmpty()) {
11095 aSourceSpecOut = report->mFileName;
11096 *aLineOut = report->mLineNumber;
11097 *aColumnOut = report->mColumn;
11098 }
11099 aMessageOut.Assign(report->mErrorMsg);
11100 }
11101
11102 // Next, try to unwrap the rejection value as a DOMException.
11103 else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
11104 aLineOut, aColumnOut, aMessageOut)) {
11105 return;
11106 }
11107
11108 // Next, try to unwrap the rejection value as an XPC Exception.
11109 else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut, aLineOut,
11110 aColumnOut, aMessageOut)) {
11111 return;
11112 }
11113 }
11114
11115 // If we could not unwrap a specific error type, then perform default safe
11116 // string conversions on primitives. Objects will result in "[Object]"
11117 // unfortunately.
11118 if (aMessageOut.IsEmpty()) {
11119 nsAutoJSString jsString;
11120 if (jsString.init(aCx, aValue)) {
11121 aMessageOut = jsString;
11122 } else {
11123 JS_ClearPendingException(aCx);
11124 }
11125 }
11126}
11127
11128#undef EXTRACT_EXN_VALUES
11129
11130/* static */
11131bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
11132 if (!aContent || !aContent->IsElement()) {
11133 return false;
11134 }
11135
11136 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
11137 return true;
11138 }
11139
11140 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
11141 nsGkAtoms::simple, eCaseMatters);
11142}
11143
11144/* static */
11145already_AddRefed<ContentFrameMessageManager>
11146nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
11147 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
11148 if (!frameLoaderOwner) {
11149 return nullptr;
11150 }
11151
11152 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
11153 if (!frameLoader) {
11154 return nullptr;
11155 }
11156
11157 RefPtr<ContentFrameMessageManager> manager =
11158 frameLoader->GetBrowserChildMessageManager();
11159 return manager.forget();
11160}
11161
11162/* static */
11163uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
11164 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"
, 11164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11164; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11165 ++sInnerOrOuterWindowCount;
11166 return ++sInnerOrOuterWindowSerialCounter;
11167}
11168
11169/* static */
11170void nsContentUtils::InnerOrOuterWindowDestroyed() {
11171 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"
, 11171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11172 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"
, 11172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { *((volatile int*)__null) = 11172; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11173 --sInnerOrOuterWindowCount;
11174}
11175
11176/* static */
11177nsresult nsContentUtils::AnonymizeURI(nsIURI* aURI, nsCString& aAnonymizedURI) {
11178 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"
, 11178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 11178; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11179
11180 if (aURI->SchemeIs("data")) {
11181 aAnonymizedURI.Assign("data:..."_ns);
11182 return NS_OK;
11183 }
11184 // Anonymize the URL.
11185 // Strip the URL of any possible username/password and make it ready to be
11186 // presented in the UI.
11187 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(aURI);
11188 return exposableURI->GetSpec(aAnonymizedURI);
11189}
11190
11191static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
11192 nsAString* result = static_cast<nsAString*>(aData);
11193 return result->Append(aBuf, aLen, fallible);
11194}
11195
11196/* static */
11197bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
11198 nsAString& aOutStr, JSONBehavior aBehavior) {
11199 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"
, 11199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { *((volatile int*)__null) = 11199; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11200 switch (aBehavior) {
11201 case UndefinedIsNullStringLiteral: {
11202 aOutStr.Truncate();
11203 JS::Rooted<JS::Value> value(aCx, aValue);
11204 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
11205 JSONCreator, &aOutStr);
11206 }
11207 case UndefinedIsVoidString: {
11208 aOutStr.SetIsVoid(true);
11209 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
11210 &aOutStr);
11211 }
11212 default:
11213 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"
, 11213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { *((volatile int*)__null) = 11213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11214 return false;
11215 }
11216}
11217
11218/* static */
11219bool nsContentUtils::
11220 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
11221 Document* aDocument) {
11222 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"
, 11223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11223 "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"
, 11223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11224
11225 if (aDocument && !aDocument->IsLoadedAsData()) {
11226 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
11227 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"
, 11228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11228; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11228 "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"
, 11228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11228; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11229
11230 return !presContext->GetInProcessRootContentDocumentPresContext()
11231 ->HadFirstContentfulPaint() &&
11232 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
11233 }
11234 }
11235 return false;
11236}
11237
11238static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
11239 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"
, 11239); return nullptr; } } while (false)
;
11240
11241 if (auto* window = aGlobal->GetAsInnerWindow()) {
11242 return nsGlobalWindowInner::Cast(window);
11243 }
11244
11245 // When Extensions run content scripts inside a sandbox, it uses
11246 // sandboxPrototype to make them appear as though they're running in the
11247 // scope of the page. So when a content script invokes postMessage, it expects
11248 // the |source| of the received message to be the window set as the
11249 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
11250 // now we need to do some special handling to support it.
11251 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
11252 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"
, 11252); return nullptr; } } while (false)
;
11253
11254 if (xpc::IsSandbox(scope)) {
11255 AutoJSAPI jsapi;
11256 MOZ_ALWAYS_TRUE(jsapi.Init(scope))do { if ((__builtin_expect(!!(jsapi.Init(scope)), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "jsapi.Init(scope)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11256); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "jsapi.Init(scope)" ")"); do { *((volatile int*)__null
) = 11256; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); } } while (false)
;
11257 JSContext* cx = jsapi.cx();
11258 // Our current Realm on aCx is the sandbox. Using that for unwrapping
11259 // makes sense: if the sandbox can unwrap the window, we can use it.
11260 return xpc::SandboxWindowOrNull(scope, cx);
11261 }
11262
11263 // The calling window must be holding a reference, so we can return a weak
11264 // pointer.
11265 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
11266}
11267
11268/* static */
11269nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
11270 return GetInnerWindowForGlobal(GetIncumbentGlobal());
11271}
11272
11273/* static */
11274nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
11275 return GetInnerWindowForGlobal(GetEntryGlobal());
11276}
11277
11278/* static */
11279bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
11280 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"
, 11280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { *((volatile int*)__null) = 11280; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11281
11282 nsAutoCString list;
11283 Preferences::GetCString(aPrefName, list);
11284 ToLowerCase(list);
11285 return IsURIInList(aURI, list);
11286}
11287
11288/* static */
11289bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
11290#ifdef DEBUG1
11291 nsAutoCString listLowerCase(aList);
11292 ToLowerCase(listLowerCase);
11293 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"
, 11294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11294; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
11294 "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"
, 11294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11294; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
11295#endif
11296
11297 if (!aURI) {
11298 return false;
11299 }
11300
11301 nsAutoCString scheme;
11302 aURI->GetScheme(scheme);
11303 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
11304 return false;
11305 }
11306
11307 if (aList.IsEmpty()) {
11308 return false;
11309 }
11310
11311 // The list is comma separated domain list. Each item may start with "*.".
11312 // If starts with "*.", it matches any sub-domains.
11313
11314 nsCCharSeparatedTokenizer tokenizer(aList, ',');
11315 while (tokenizer.hasMoreTokens()) {
11316 const nsCString token(tokenizer.nextToken());
11317
11318 nsAutoCString host;
11319 aURI->GetHost(host);
11320 if (host.IsEmpty()) {
11321 return false;
11322 }
11323 ToLowerCase(host);
11324
11325 for (;;) {
11326 int32_t index = token.Find(host);
11327 if (index >= 0 &&
11328 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
11329 // If we found a full match, return true.
11330 size_t indexAfterHost = index + host.Length();
11331 if (index == 0 && indexAfterHost == token.Length()) {
11332 return true;
11333 }
11334 // If next character is '/', we need to check the path too.
11335 // We assume the path in the list means "/foo" + "*".
11336 if (token[indexAfterHost] == '/') {
11337 nsDependentCSubstring pathInList(
11338 token, indexAfterHost,
11339 static_cast<nsDependentCSubstring::size_type>(-1));
11340 nsAutoCString filePath;
11341 aURI->GetFilePath(filePath);
11342 ToLowerCase(filePath);
11343 if (StringBeginsWith(filePath, pathInList) &&
11344 (filePath.Length() == pathInList.Length() ||
11345 pathInList.EqualsLiteral("/") ||
11346 filePath[pathInList.Length() - 1] == '/' ||
11347 filePath[pathInList.Length() - 1] == '?' ||
11348 filePath[pathInList.Length() - 1] == '#')) {
11349 return true;
11350 }
11351 }
11352 }
11353 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
11354 int32_t startIndexOfNextLevel =
11355 host.Find(".", startIndexOfCurrentLevel + 1);
11356 if (startIndexOfNextLevel <= 0) {
11357 break;
11358 }
11359 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
11360 }
11361 }
11362
11363 return false;
11364}
11365
11366/* static */
11367ScreenIntMargin nsContentUtils::GetWindowSafeAreaInsets(
11368 nsIScreen* aScreen, const ScreenIntMargin& aSafeAreaInsets,
11369 const LayoutDeviceIntRect& aWindowRect) {
11370 // This calculates safe area insets of window from screen rectangle, window
11371 // rectangle and safe area insets of screen.
11372 //
11373 // +----------------------------------------+ <-- screen
11374 // | +-------------------------------+ <------- window
11375 // | | window's safe area inset top) | |
11376 // +--+-------------------------------+--+ |
11377 // | | | |<------ safe area rectangle of
11378 // | | | | | screen
11379 // +--+-------------------------------+--+ |
11380 // | |window's safe area inset bottom| |
11381 // | +-------------------------------+ |
11382 // +----------------------------------------+
11383 //
11384 ScreenIntMargin windowSafeAreaInsets;
11385
11386 if (windowSafeAreaInsets == aSafeAreaInsets) {
11387 // no safe area insets.
11388 return windowSafeAreaInsets;
11389 }
11390
11391 int32_t screenLeft, screenTop, screenWidth, screenHeight;
11392 nsresult rv =
11393 aScreen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
11394 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"
, 11394)
) {
11395 return windowSafeAreaInsets;
11396 }
11397
11398 const ScreenIntRect screenRect(screenLeft, screenTop, screenWidth,
11399 screenHeight);
11400
11401 ScreenIntRect safeAreaRect = screenRect;
11402 safeAreaRect.Deflate(aSafeAreaInsets);
11403
11404 ScreenIntRect windowRect = ViewAs<ScreenPixel>(
11405 aWindowRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
11406
11407 // FIXME(bug 1754323): This can trigger because the screen rect is not
11408 // orientation-aware.
11409 // MOZ_ASSERT(screenRect.Contains(windowRect),
11410 // "Screen doesn't contain window rect? Something seems off");
11411
11412 // window's rect of safe area
11413 safeAreaRect = safeAreaRect.Intersect(windowRect);
11414
11415 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
11416 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
11417 windowSafeAreaInsets.right =
11418 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
11419 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
11420 (safeAreaRect.y + safeAreaRect.height);
11421
11422 windowSafeAreaInsets.EnsureAtLeast(ScreenIntMargin());
11423 // This shouldn't be needed, but it wallpapers orientation issues, see bug
11424 // 1754323.
11425 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
11426
11427 return windowSafeAreaInsets;
11428}
11429
11430/* static */
11431nsContentUtils::SubresourceCacheValidationInfo
11432nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
11433 nsIURI* aURI) {
11434 SubresourceCacheValidationInfo info;
11435 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
11436 uint32_t value = 0;
11437 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
11438 info.mExpirationTime.emplace(value);
11439 }
11440 }
11441
11442 // Determine whether the cache entry must be revalidated when we try to use
11443 // it. Currently, only HTTP specifies this information...
11444 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
11445 Unused << httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
11446
11447 if (!info.mMustRevalidate) {
11448 Unused << httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
11449 }
11450 }
11451
11452 // data: URIs are safe to cache across documents under any circumstance, so we
11453 // special-case them here even though the channel itself doesn't have any
11454 // caching policy. Same for chrome:// uris.
11455 //
11456 // TODO(emilio): Figure out which other schemes that don't have caching
11457 // policies are safe to cache. Blobs should be...
11458 const bool knownCacheable = [&] {
11459 if (!aURI) {
11460 return false;
11461 }
11462 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
11463 aURI->SchemeIs("moz-extension")) {
11464 return true;
11465 }
11466 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
11467 return !StaticPrefs::nglayout_debug_disable_xul_cache();
11468 }
11469 return false;
11470 }();
11471
11472 if (knownCacheable) {
11473 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"
, 11473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mExpirationTime"
")"); do { *((volatile int*)__null) = 11473; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11474 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"
, 11474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mMustRevalidate"
")"); do { *((volatile int*)__null) = 11474; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11475 info.mExpirationTime = Some(0); // 0 means "doesn't expire".
11476 }
11477
11478 return info;
11479}
11480
11481/* static */
11482bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
11483 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
11484 if (!lg) {
11485 return false;
11486 }
11487 nsLoadFlags flags;
11488 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
11489 return false;
11490 }
11491 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
11492 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
11493}
11494
11495nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
11496 nsCString spec;
11497 if (aURL) {
11498 aURL->GetSpec(spec);
11499 spec.Truncate(std::min(aMaxLen, spec.Length()));
11500 }
11501 return spec;
11502}
11503
11504/* static */
11505nsresult nsContentUtils::AnonymizeId(nsAString& aId,
11506 const nsACString& aOriginKey,
11507 OriginFormat aFormat) {
11508 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"
, 11508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11508; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11509
11510 nsresult rv;
11511 nsCString rawKey;
11512 if (aFormat == OriginFormat::Base64) {
11513 rv = Base64Decode(aOriginKey, rawKey);
11514 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"
, 11514); return rv; } } while (false)
;
11515 } else {
11516 rawKey = aOriginKey;
11517 }
11518
11519 HMAC hmac;
11520 rv = hmac.Begin(
11521 SEC_OID_SHA256,
11522 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
11523 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"
, 11523); return rv; } } while (false)
;
11524
11525 NS_ConvertUTF16toUTF8 id(aId);
11526 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
11527 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"
, 11527); return rv; } } while (false)
;
11528
11529 nsTArray<uint8_t> macBytes;
11530 rv = hmac.End(macBytes);
11531 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"
, 11531); return rv; } } while (false)
;
11532
11533 nsCString macBase64;
11534 rv = Base64Encode(
11535 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
11536 macBytes.Length()),
11537 macBase64);
11538 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"
, 11538); return rv; } } while (false)
;
11539
11540 CopyUTF8toUTF16(macBase64, aId);
11541 return NS_OK;
11542}
11543
11544void nsContentUtils::RequestGeckoTaskBurst() {
11545 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{ 0x2d96b3df, 0xc051, 0x11d1, { 0xa8, 0x27, 0x00, 0x40, 0x95,
0x9a, 0x28, 0xc9 } }
);
11546 if (appShell) {
11547 appShell->GeckoTaskBurst();
11548 }
11549}
11550
11551nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
11552 for (nsIContent* content = aContent; content;
11553 content = content->GetFlattenedTreeParent()) {
11554 if (nsContentUtils::IsDraggableLink(content)) {
11555 return content;
11556 }
11557 }
11558 return nullptr;
11559}
11560
11561template <TreeKind aKind>
11562MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
11563 if constexpr (aKind == TreeKind::DOM) {
11564 return aNode->GetParentNode();
11565 } else {
11566 return aNode->GetFlattenedTreeParentNode();
11567 }
11568}
11569
11570template <TreeKind aKind>
11571MOZ_ALWAYS_INLINEinline Maybe<uint32_t> GetIndexInParent(const nsINode* aParent,
11572 const nsINode* aNode) {
11573 if constexpr (aKind == TreeKind::DOM) {
11574 return aParent->ComputeIndexOf(aNode);
11575 } else {
11576 return aParent->ComputeFlatTreeIndexOf(aNode);
11577 }
11578}
11579
11580template <TreeKind aTreeKind>
11581int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
11582 const nsINode* aNode2,
11583 const nsINode* aCommonAncestor) {
11584 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"
, 11584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") ("
"aNode1 must not be null" ")"); do { *((volatile int*)__null
) = 11584; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11585 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"
, 11585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") ("
"aNode2 must not be null" ")"); do { *((volatile int*)__null
) = 11585; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11586
11587 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"
, 11587)
) {
11588 return 0;
11589 }
11590
11591 AutoTArray<const nsINode*, 32> node1Ancestors;
11592 const nsINode* c1;
11593 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
11594 c1 = GetParent<aTreeKind>(c1)) {
11595 node1Ancestors.AppendElement(c1);
11596 }
11597 if (!c1 && aCommonAncestor) {
11598 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
11599 // Never mind. We can continue as if aCommonAncestor was null.
11600 aCommonAncestor = nullptr;
11601 }
11602
11603 AutoTArray<const nsINode*, 32> node2Ancestors;
11604 const nsINode* c2;
11605 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
11606 c2 = GetParent<aTreeKind>(c2)) {
11607 node2Ancestors.AppendElement(c2);
11608 }
11609 if (!c2 && aCommonAncestor) {
11610 // So, it turns out aCommonAncestor was not an ancestor of c2.
11611 // We need to retry with no common ancestor hint.
11612 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr);
11613 }
11614
11615 int last1 = node1Ancestors.Length() - 1;
11616 int last2 = node2Ancestors.Length() - 1;
11617 const nsINode* node1Ancestor = nullptr;
11618 const nsINode* node2Ancestor = nullptr;
11619 while (last1 >= 0 && last2 >= 0 &&
11620 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
11621 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
11622 last1--;
11623 last2--;
11624 }
11625
11626 if (last1 < 0) {
11627 if (last2 < 0) {
11628 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"
, 11628); MOZ_PretendNoReturn(); } } while (0)
;
11629 return 0;
11630 }
11631 // aContent1 is an ancestor of aContent2
11632 return -1;
11633 }
11634
11635 if (last2 < 0) {
11636 // aContent2 is an ancestor of aContent1
11637 return 1;
11638 }
11639
11640 // node1Ancestor != node2Ancestor, so they must be siblings with the
11641 // same parent
11642 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
11643 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11643)
) { // different documents??
11644 return 0;
11645 }
11646
11647 const Maybe<uint32_t> index1 =
11648 GetIndexInParent<aTreeKind>(parent, node1Ancestor);
11649 const Maybe<uint32_t> index2 =
11650 GetIndexInParent<aTreeKind>(parent, node2Ancestor);
11651
11652 // None of the nodes are anonymous, just do a regular comparison.
11653 if (index1.isSome() && index2.isSome()) {
11654 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
11655 }
11656
11657 // Otherwise handle pseudo-element and anonymous node ordering.
11658 // ::marker -> ::before -> anon siblings -> regular siblings -> ::after
11659 auto PseudoIndex = [](const nsINode* aNode,
11660 const Maybe<uint32_t>& aNodeIndex) -> int32_t {
11661 if (aNodeIndex.isSome()) {
11662 return 1; // Not a pseudo.
11663 }
11664 if (aNode->IsGeneratedContentContainerForMarker()) {
11665 return -2;
11666 }
11667 if (aNode->IsGeneratedContentContainerForBefore()) {
11668 return -1;
11669 }
11670 if (aNode->IsGeneratedContentContainerForAfter()) {
11671 return 2;
11672 }
11673 return 0;
11674 };
11675
11676 return PseudoIndex(node1Ancestor, index1) -
11677 PseudoIndex(node2Ancestor, index2);
11678}
11679
11680nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost,
11681 ShadowRootMode aMode,
11682 bool aIsClonable,
11683 bool aIsSerializable,
11684 bool aDelegatesFocus) {
11685 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
11686 if (!host || host->GetShadowRoot()) {
11687 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
11688 return nullptr;
11689 }
11690
11691 ShadowRootInit init;
11692 init.mMode = aMode;
11693 init.mDelegatesFocus = aDelegatesFocus;
11694 init.mSlotAssignment = SlotAssignmentMode::Named;
11695 init.mClonable = aIsClonable;
11696 init.mSerializable = aIsSerializable;
11697
11698 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
11699 if (shadowRoot) {
11700 shadowRoot->SetIsDeclarative(
11701 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
11702 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
11703 shadowRoot->SetAvailableToElementInternals();
11704 }
11705 return shadowRoot;
11706}
11707
11708template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
11709 const nsINode*, const nsINode*, const nsINode*);
11710template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
11711 const nsINode*, const nsINode*, const nsINode*);
11712
11713namespace mozilla {
11714std::ostream& operator<<(std::ostream& aOut,
11715 const PreventDefaultResult aPreventDefaultResult) {
11716 switch (aPreventDefaultResult) {
11717 case PreventDefaultResult::No:
11718 aOut << "unhandled";
11719 break;
11720 case PreventDefaultResult::ByContent:
11721 aOut << "handled-by-content";
11722 break;
11723 case PreventDefaultResult::ByChrome:
11724 aOut << "handled-by-chrome";
11725 break;
11726 }
11727 return aOut;
11728}
11729} // namespace mozilla