Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp
Warning:line 10286, column 5
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-27-022226-2793976-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
7047bool nsContentUtils::HasScrollgrab(nsIContent* aContent) {
7048 // If we ever standardize this feature we'll want to hook this up properly
7049 // again. For now we're removing all the DOM-side code related to it but
7050 // leaving the layout and APZ handling for it in place.
7051 return false;
7052}
7053
7054void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
7055 if (!aWindow) {
7056 return;
7057 }
7058
7059 // Note that because FlushPendingNotifications flushes parents, this
7060 // is O(N^2) in docshell tree depth. However, the docshell tree is
7061 // usually pretty shallow.
7062
7063 if (RefPtr<Document> doc = aWindow->GetDoc()) {
7064 doc->FlushPendingNotifications(FlushType::Layout);
7065 }
7066
7067 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
7068 int32_t i = 0, i_end;
7069 docShell->GetInProcessChildCount(&i_end);
7070 for (; i < i_end; ++i) {
7071 nsCOMPtr<nsIDocShellTreeItem> item;
7072 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
7073 item) {
7074 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
7075 FlushLayoutForTree(win);
7076 }
7077 }
7078 }
7079 }
7080}
7081
7082void nsContentUtils::RemoveNewlines(nsString& aString) { aString.StripCRLF(); }
7083
7084void nsContentUtils::PlatformToDOMLineBreaks(nsString& aString) {
7085 if (!PlatformToDOMLineBreaks(aString, fallible)) {
7086 aString.AllocFailed(aString.Length());
7087 }
7088}
7089
7090bool nsContentUtils::PlatformToDOMLineBreaks(nsString& aString,
7091 const fallible_t& aFallible) {
7092 if (aString.FindChar(char16_t('\r')) != -1) {
7093 // Windows linebreaks: Map CRLF to LF:
7094 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
7095 return false;
7096 }
7097
7098 // Mac linebreaks: Map any remaining CR to LF:
7099 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
7100 return false;
7101 }
7102 }
7103
7104 return true;
7105}
7106
7107already_AddRefed<nsContentList> nsContentUtils::GetElementsByClassName(
7108 nsINode* aRootNode, const nsAString& aClasses) {
7109 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"
, 7109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") ("
"Must have root node" ")"); do { *((volatile int*)__null) = 7109
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7110
7111 return GetFuncStringContentList<nsCacheableFuncStringHTMLCollection>(
7112 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
7113 aClasses);
7114}
7115
7116PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
7117 const Document* doc = aDocument;
7118 Document* displayDoc = doc->GetDisplayDocument();
7119 if (displayDoc) {
7120 doc = displayDoc;
7121 }
7122
7123 PresShell* presShell = doc->GetPresShell();
7124 if (presShell) {
7125 return presShell;
7126 }
7127
7128 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
7129 while (docShellTreeItem) {
7130 // We may be in a display:none subdocument, or we may not have a presshell
7131 // created yet.
7132 // Walk the docshell tree to find the nearest container that has a
7133 // presshell, and return that.
7134 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
7135 if (PresShell* presShell = docShell->GetPresShell()) {
7136 return presShell;
7137 }
7138 nsCOMPtr<nsIDocShellTreeItem> parent;
7139 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
7140 docShellTreeItem = parent;
7141 }
7142
7143 return nullptr;
7144}
7145
7146/* static */
7147nsPresContext* nsContentUtils::FindPresContextForDocument(
7148 const Document* aDocument) {
7149 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
7150 return presShell->GetPresContext();
7151 }
7152 return nullptr;
7153}
7154
7155nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
7156 PresShell* presShell = FindPresShellForDocument(aDocument);
7157 if (!presShell) {
7158 return nullptr;
7159 }
7160 nsViewManager* vm = presShell->GetViewManager();
7161 if (!vm) {
7162 return nullptr;
7163 }
7164 nsView* rootView = vm->GetRootView();
7165 if (!rootView) {
7166 return nullptr;
7167 }
7168 nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView);
7169 if (!displayRoot) {
7170 return nullptr;
7171 }
7172 return displayRoot->GetNearestWidget(nullptr);
7173}
7174
7175nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
7176 nsIFrame* frame = aContent->GetPrimaryFrame();
7177 if (frame) {
7178 frame = nsLayoutUtils::GetDisplayRootFrame(frame);
7179
7180 nsView* view = frame->GetView();
7181 if (view) {
7182 return view->GetWidget();
7183 }
7184 }
7185
7186 return nullptr;
7187}
7188
7189WindowRenderer* nsContentUtils::WindowRendererForContent(
7190 const nsIContent* aContent) {
7191 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
7192 if (widget) {
7193 return widget->GetWindowRenderer();
7194 }
7195
7196 return nullptr;
7197}
7198
7199WindowRenderer* nsContentUtils::WindowRendererForDocument(
7200 const Document* aDoc) {
7201 nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc);
7202 if (widget) {
7203 return widget->GetWindowRenderer();
7204 }
7205
7206 return nullptr;
7207}
7208
7209bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
7210 if (!aPrincipal) {
7211 return false;
7212 }
7213
7214 if (aPrincipal->IsSystemPrincipal()) {
7215 return true;
7216 }
7217
7218 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
7219}
7220
7221bool nsContentUtils::IsPDFJSEnabled() {
7222 nsCOMPtr<nsIStreamConverter> conv = do_CreateInstance(
7223 "@mozilla.org/streamconv;1?from=application/pdf&to=text/html");
7224 return conv;
7225}
7226
7227bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
7228 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
7229 return false;
7230 }
7231 nsAutoCString spec;
7232 nsresult rv = aPrincipal->GetAsciiSpec(spec);
7233 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"
, 7233); return false; } } while (false)
;
7234 return spec.EqualsLiteral("resource://pdf.js/web/viewer.html");
7235}
7236
7237bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
7238 nsIPrincipal* principal = SubjectPrincipal(aCx);
7239 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
7240}
7241
7242bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
7243 JSObject* aGlobal) {
7244 nsIPrincipal* principal = SubjectPrincipal(aCx);
7245 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
7246 aGlobal) ||
7247 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
7248}
7249
7250already_AddRefed<nsIDocumentLoaderFactory>
7251nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
7252 DocumentViewerType* aLoaderType) {
7253 if (aLoaderType) {
7254 *aLoaderType = TYPE_UNSUPPORTED;
7255 }
7256
7257 // one helper factory, please
7258 nsCOMPtr<nsICategoryManager> catMan(
7259 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
7260 if (!catMan) return nullptr;
7261
7262 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
7263
7264 nsCString contractID;
7265 nsresult rv =
7266 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
7267 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7268 docFactory = do_GetService(contractID.get());
7269 if (docFactory && aLoaderType) {
7270 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
7271 *aLoaderType = TYPE_CONTENT;
7272 else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID"@mozilla.org/content/plugin/document-loader-factory;1"))
7273 *aLoaderType = TYPE_FALLBACK;
7274 else
7275 *aLoaderType = TYPE_UNKNOWN;
7276 }
7277 return docFactory.forget();
7278 }
7279
7280 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
7281 // another type which we may dynamically support, such as `text/*` types or
7282 // video document types. These types are all backed by the nsContentDLF.
7283 if (IsPlainTextType(aType) ||
7284 DecoderTraits::IsSupportedInVideoDocument(aType)) {
7285 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
7286 if (docFactory && aLoaderType) {
7287 *aLoaderType = TYPE_CONTENT;
7288 }
7289 return docFactory.forget();
7290 }
7291
7292 return nullptr;
7293}
7294
7295static void ReportPatternCompileFailure(nsAString& aPattern,
7296 const JS::RegExpFlags& aFlags,
7297 const Document* aDocument,
7298 JS::MutableHandle<JS::Value> error,
7299 JSContext* cx) {
7300 AutoTArray<nsString, 3> strings;
7301
7302 strings.AppendElement(aPattern);
7303
7304 std::stringstream flag_ss;
7305 flag_ss << aFlags;
7306 nsString* flagstr = strings.AppendElement();
7307 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
7308
7309 JS::AutoSaveExceptionState savedExc(cx);
7310 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
7311 JS::Rooted<JS::Value> messageVal(cx);
7312 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
7313 return;
7314 }
7315 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
7316 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"
, 7316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { *((volatile int*)__null) = 7316; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7317 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
7318 return;
7319 }
7320
7321 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
7322 aDocument, nsContentUtils::eDOM_PROPERTIES,
7323 "PatternAttributeCompileFailurev2", strings);
7324 savedExc.drop();
7325}
7326
7327// static
7328Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
7329 nsString&& aPattern,
7330 const Document* aDocument,
7331 bool aHasMultiple,
7332 JS::RegExpFlags aFlags) {
7333 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"
, 7333); MOZ_PretendNoReturn(); } } while (0)
;
7334
7335 // The fact that we're using a JS regexp under the hood should not be visible
7336 // to things like window onerror handlers, so we don't initialize our JSAPI
7337 // with the document's window (which may not exist anyway).
7338 AutoJSAPI jsapi;
7339 jsapi.Init();
7340 JSContext* cx = jsapi.cx();
7341 AutoDisableJSInterruptCallback disabler(cx);
7342
7343 // We can use the junk scope here, because we're just using it for regexp
7344 // evaluation, not actual script execution, and we disable statics so that the
7345 // evaluation does not interact with the execution global.
7346 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
7347
7348 // Check if the pattern by itself is valid first, and not that it only becomes
7349 // valid once we add ^(?: and )$.
7350 JS::Rooted<JS::Value> error(cx);
7351 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
7352 aFlags, &error)) {
7353 return Nothing();
7354 }
7355
7356 if (!error.isUndefined()) {
7357 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
7358 return Some(true);
7359 }
7360
7361 // The pattern has to match the entire value.
7362 aPattern.InsertLiteral(u"^(?:", 0);
7363 aPattern.AppendLiteral(")$");
7364
7365 JS::Rooted<JSObject*> re(
7366 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
7367 aFlags));
7368 if (!re) {
7369 return Nothing();
7370 }
7371
7372 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
7373 if (!aHasMultiple) {
7374 size_t idx = 0;
7375 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
7376 aValue.Length(), &idx, true, &rval)) {
7377 return Nothing();
7378 }
7379 return Some(!rval.isNull());
7380 }
7381
7382 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
7383 while (tokenizer.hasMoreTokens()) {
7384 const nsAString& value = tokenizer.nextToken();
7385 size_t idx = 0;
7386 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
7387 value.Length(), &idx, true, &rval)) {
7388 return Nothing();
7389 }
7390 if (rval.isNull()) {
7391 return Some(false);
7392 }
7393 }
7394 return Some(true);
7395}
7396
7397// static
7398nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
7399 bool* aResult) {
7400 // Note: about:blank URIs do NOT inherit the security context from the
7401 // current document, which is what this function tests for...
7402 return NS_URIChainHasFlags(
7403 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
7404}
7405
7406// static
7407bool nsContentUtils::ChannelShouldInheritPrincipal(
7408 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
7409 bool aForceInherit) {
7410 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"
, 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7411; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7411 "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"
, 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ *((volatile int*)__null) = 7411; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7412
7413 // Only tell the channel to inherit if it can't provide its own security
7414 // context.
7415 //
7416 // XXX: If this is ever changed, check all callers for what owners
7417 // they're passing in. In particular, see the code and
7418 // comments in nsDocShell::LoadURI where we fall back on
7419 // inheriting the owner if called from chrome. That would be
7420 // very wrong if this code changed anything but channels that
7421 // can't provide their own security context!
7422 //
7423 // If aForceInherit is true, we will inherit, even for a channel that
7424 // can provide its own security context. This is used for srcdoc loads.
7425 bool inherit = aForceInherit;
7426 if (!inherit) {
7427 bool uriInherits;
7428 // We expect URIInheritsSecurityContext to return success for an
7429 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
7430 // This condition needs to match the one in nsDocShell::InternalLoad where
7431 // we're checking for things that will use the owner.
7432 inherit =
7433 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
7434 (uriInherits || (aInheritForAboutBlank &&
7435 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
7436 //
7437 // file: uri special-casing
7438 //
7439 // If this is a file: load opened from another file: then it may need
7440 // to inherit the owner from the referrer so they can script each other.
7441 // If we don't set the owner explicitly then each file: gets an owner
7442 // based on its own codebase later.
7443 //
7444 (URIIsLocalFile(aURI) &&
7445 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
7446 // One more check here. CheckMayLoad will always return true for the
7447 // system principal, but we do NOT want to inherit in that case.
7448 !aLoadingPrincipal->IsSystemPrincipal());
7449 }
7450 return inherit;
7451}
7452
7453/* static */
7454bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
7455 nsIPrincipal& aSubjectPrincipal) {
7456 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
7457 aDocument->HasValidTransientUserGestureActivation()) {
7458 return true;
7459 }
7460
7461 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
7462}
7463
7464/* static */
7465bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
7466 if (!aDoc1 || !aDoc2) {
7467 return false;
7468 }
7469 bool principalsEqual = false;
7470 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
7471 return principalsEqual;
7472}
7473
7474/* static */
7475void nsContentUtils::FireMutationEventsForDirectParsing(
7476 Document* aDoc, nsIContent* aDest, int32_t aOldChildCount) {
7477 // Fire mutation events. Optimize for the case when there are no listeners
7478 int32_t newChildCount = aDest->GetChildCount();
7479 if (newChildCount && nsContentUtils::HasMutationListeners(
7480 aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED0x02)) {
7481 AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
7482 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"
, 7483); MOZ_PretendNoReturn(); } } while (0)
7483 "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"
, 7483); MOZ_PretendNoReturn(); } } while (0)
;
7484 childNodes.SetCapacity(newChildCount - aOldChildCount);
7485 for (nsIContent* child = aDest->GetFirstChild(); child;
7486 child = child->GetNextSibling()) {
7487 childNodes.AppendElement(child);
7488 }
7489 FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes);
7490 }
7491}
7492
7493/* static */
7494const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
7495 const Document* aDoc) {
7496 if (!aDoc) {
7497 return nullptr;
7498 }
7499 const Document* doc = aDoc;
7500 while (doc->GetInProcessParentDocument()) {
7501 doc = doc->GetInProcessParentDocument();
7502 }
7503 return doc;
7504}
7505
7506// static
7507int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
7508 int32_t aOffset) {
7509 // The structure of the anonymous frames within a text control frame is
7510 // an optional block frame, followed by an optional br frame.
7511
7512 // If the offset frame has a child, then this frame is the block which
7513 // has the text frames (containing the content) as its children. This will
7514 // be the case if we click to the right of any of the text frames, or at the
7515 // bottom of the text area.
7516 nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
7517 if (firstChild) {
7518 // In this case, the passed-in offset is incorrect, and we want the length
7519 // of the entire content in the text control frame.
7520 return firstChild->GetContent()->Length();
7521 }
7522
7523 if (aOffsetFrame->GetPrevSibling() && !aOffsetFrame->GetNextSibling()) {
7524 // In this case, we're actually within the last frame, which is a br
7525 // frame. Our offset should therefore be the length of the first child of
7526 // our parent.
7527 int32_t aOutOffset = aOffsetFrame->GetParent()
7528 ->PrincipalChildList()
7529 .FirstChild()
7530 ->GetContent()
7531 ->Length();
7532 return aOutOffset;
7533 }
7534
7535 // Otherwise, we're within one of the text frames, in which case our offset
7536 // has already been correctly calculated.
7537 return aOffset;
7538}
7539
7540// static
7541bool nsContentUtils::IsPointInSelection(
7542 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
7543 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
7544 const bool selectionIsCollapsed =
7545 !aAllowCrossShadowBoundary
7546 ? aSelection.IsCollapsed()
7547 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
7548 if (selectionIsCollapsed) {
7549 return false;
7550 }
7551
7552 const uint32_t rangeCount = aSelection.RangeCount();
7553 for (const uint32_t i : IntegerRange(rangeCount)) {
7554 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"
, 7554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount"
")"); do { *((volatile int*)__null) = 7554; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7555 RefPtr<const nsRange> range = aSelection.GetRangeAt(i);
7556 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 7556)
) {
7557 // Don't bail yet, iterate through them all
7558 continue;
7559 }
7560
7561 // Done when we find a range that we are in
7562 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
7563 aAllowCrossShadowBoundary)) {
7564 return true;
7565 }
7566 }
7567
7568 return false;
7569}
7570
7571// static
7572void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
7573 Element* aRoot,
7574 uint32_t& aOutStartOffset,
7575 uint32_t& aOutEndOffset) {
7576 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"
, 7576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection && aRoot"
")"); do { *((volatile int*)__null) = 7576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7577
7578 // We don't care which end of this selection is anchor and which is focus. In
7579 // fact, we explicitly want to know which is the _start_ and which is the
7580 // _end_, not anchor vs focus.
7581 const nsRange* range = aSelection->GetAnchorFocusRange();
7582 if (!range) {
7583 // Nothing selected
7584 aOutStartOffset = aOutEndOffset = 0;
7585 return;
7586 }
7587
7588 // All the node pointers here are raw pointers for performance. We shouldn't
7589 // be doing anything in this function that invalidates the node tree.
7590 nsINode* startContainer = range->GetStartContainer();
7591 uint32_t startOffset = range->StartOffset();
7592 nsINode* endContainer = range->GetEndContainer();
7593 uint32_t endOffset = range->EndOffset();
7594
7595 // We have at most two children, consisting of an optional text node followed
7596 // by an optional <br>.
7597 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"
, 7597); MOZ_PretendNoReturn(); } } while (0)
;
7598 nsIContent* firstChild = aRoot->GetFirstChild();
7599#ifdef DEBUG1
7600 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
7601 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"
, 7603); MOZ_PretendNoReturn(); } } while (0)
7602 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"
, 7603); MOZ_PretendNoReturn(); } } while (0)
7603 "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"
, 7603); MOZ_PretendNoReturn(); } } while (0)
;
7604 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"
, 7606); MOZ_PretendNoReturn(); } } while (0)
7605 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"
, 7606); MOZ_PretendNoReturn(); } } while (0)
7606 "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"
, 7606); MOZ_PretendNoReturn(); } } while (0)
;
7607 // firstChild is either text or a <br> (hence an element).
7608 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"
, 7608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { *((volatile int*)__null) = 7608; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7609#endif
7610 if (!firstChild || firstChild->IsElement()) {
7611 // No text node, so everything is 0
7612 startOffset = endOffset = 0;
7613 } else {
7614 // First child is text. If the start/end is already in the text node,
7615 // or the start of the root node, no change needed. If it's in the root
7616 // node but not the start, or in the trailing <br>, we need to set the
7617 // offset to the end.
7618 if ((startContainer == aRoot && startOffset != 0) ||
7619 (startContainer != aRoot && startContainer != firstChild)) {
7620 startOffset = firstChild->Length();
7621 }
7622 if ((endContainer == aRoot && endOffset != 0) ||
7623 (endContainer != aRoot && endContainer != firstChild)) {
7624 endOffset = firstChild->Length();
7625 }
7626 }
7627
7628 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"
, 7628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startOffset <= endOffset"
")"); do { *((volatile int*)__null) = 7628; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7629 aOutStartOffset = startOffset;
7630 aOutEndOffset = endOffset;
7631}
7632
7633// static
7634HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
7635 if (!aPresContext) {
7636 return nullptr;
7637 }
7638 return GetHTMLEditor(aPresContext->GetDocShell());
7639}
7640
7641// static
7642HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
7643 bool isEditable;
7644 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
7645 !isEditable) {
7646 return nullptr;
7647 }
7648 return aDocShell->GetHTMLEditor();
7649}
7650
7651// static
7652EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
7653 if (!aPresContext) {
7654 return nullptr;
7655 }
7656
7657 return GetActiveEditor(aPresContext->Document()->GetWindow());
7658}
7659
7660// static
7661EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
7662 if (!aWindow || !aWindow->GetExtantDoc()) {
7663 return nullptr;
7664 }
7665
7666 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
7667 // handles all events. I.e., it's focused editor in this case.
7668 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
7669 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7670 }
7671
7672 // If focused element is associated with TextEditor, it must be <input>
7673 // element or <textarea> element. Let's return it even if it's in a
7674 // contenteditable element.
7675 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
7676 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
7677 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
7678 getter_AddRefs(focusedWindow))) {
7679 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
7680 return textEditor;
7681 }
7682 }
7683
7684 // Otherwise, HTMLEditor may handle inputs even non-editable element has
7685 // focus or nobody has focus.
7686 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
7687}
7688
7689// static
7690TextEditor* nsContentUtils::GetTextEditorFromAnonymousNodeWithoutCreation(
7691 const nsIContent* aAnonymousContent) {
7692 if (!aAnonymousContent) {
7693 return nullptr;
7694 }
7695 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
7696 if (!parent || parent == aAnonymousContent) {
7697 return nullptr;
7698 }
7699 if (HTMLInputElement* inputElement =
7700 HTMLInputElement::FromNodeOrNull(parent)) {
7701 return inputElement->GetTextEditorWithoutCreation();
7702 }
7703 if (HTMLTextAreaElement* textareaElement =
7704 HTMLTextAreaElement::FromNodeOrNull(parent)) {
7705 return textareaElement->GetTextEditorWithoutCreation();
7706 }
7707 return nullptr;
7708}
7709
7710// static
7711bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
7712 while (aNode) {
7713 if (aNode->IsEditable()) {
7714 return true;
7715 }
7716 aNode = aNode->GetParent();
7717 }
7718 return false;
7719}
7720
7721// static
7722bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
7723 const nsACString& aValue) {
7724 if (IsForbiddenSystemRequestHeader(aHeader)) {
7725 return true;
7726 }
7727
7728 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
7729 nsContentUtils::ContainsForbiddenMethod(aValue))) {
7730 return true;
7731 }
7732
7733 if (StringBeginsWith(aHeader, "proxy-"_ns,
7734 nsCaseInsensitiveCStringComparator) ||
7735 StringBeginsWith(aHeader, "sec-"_ns,
7736 nsCaseInsensitiveCStringComparator)) {
7737 return true;
7738 }
7739
7740 return false;
7741}
7742
7743// static
7744bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
7745 static const char* kInvalidHeaders[] = {"accept-charset",
7746 "accept-encoding",
7747 "access-control-request-headers",
7748 "access-control-request-method",
7749 "connection",
7750 "content-length",
7751 "cookie",
7752 "cookie2",
7753 "date",
7754 "dnt",
7755 "expect",
7756 "host",
7757 "keep-alive",
7758 "origin",
7759 "referer",
7760 "set-cookie",
7761 "te",
7762 "trailer",
7763 "transfer-encoding",
7764 "upgrade",
7765 "via"};
7766 for (auto& kInvalidHeader : kInvalidHeaders) {
7767 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
7768 return true;
7769 }
7770 }
7771 return false;
7772}
7773
7774// static
7775bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
7776 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
7777 aHeader.LowerCaseEqualsASCII("set-cookie2"));
7778}
7779
7780// static
7781bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
7782 return headerName.EqualsIgnoreCase("x-http-method-override") ||
7783 headerName.EqualsIgnoreCase("x-http-method") ||
7784 headerName.EqualsIgnoreCase("x-method-override");
7785}
7786
7787// static
7788bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
7789 bool hasInsecureMethod = false;
7790 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
7791
7792 while (tokenizer.hasMoreTokens()) {
7793 const nsDependentCSubstring& value = tokenizer.nextToken();
7794
7795 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
7796 value.EqualsIgnoreCase("track")) {
7797 hasInsecureMethod = true;
7798 break;
7799 }
7800 }
7801
7802 return hasInsecureMethod;
7803}
7804
7805Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
7806 const nsACString& aHeaderValue, bool aAllowWhitespace) {
7807 // See https://fetch.spec.whatwg.org/#simple-range-header-value
7808 mozilla::Tokenizer p(aHeaderValue);
7809 Maybe<uint64_t> rangeStart;
7810 Maybe<uint64_t> rangeEnd;
7811
7812 // Step 2 and 3
7813 if (!p.CheckWord("bytes")) {
7814 return Nothing();
7815 }
7816
7817 // Step 4
7818 if (aAllowWhitespace) {
7819 p.SkipWhites();
7820 }
7821
7822 // Step 5 and 6
7823 if (!p.CheckChar('=')) {
7824 return Nothing();
7825 }
7826
7827 // Step 7
7828 if (aAllowWhitespace) {
7829 p.SkipWhites();
7830 }
7831
7832 // Step 8 and 9
7833 uint64_t res;
7834 if (p.ReadInteger(&res)) {
7835 rangeStart = Some(res);
7836 }
7837
7838 // Step 10
7839 if (aAllowWhitespace) {
7840 p.SkipWhites();
7841 }
7842
7843 // Step 11
7844 if (!p.CheckChar('-')) {
7845 return Nothing();
7846 }
7847
7848 // Step 13
7849 if (aAllowWhitespace) {
7850 p.SkipWhites();
7851 }
7852
7853 // Step 14 and 15
7854 if (p.ReadInteger(&res)) {
7855 rangeEnd = Some(res);
7856 }
7857
7858 // Step 16
7859 if (!p.CheckEOF()) {
7860 return Nothing();
7861 }
7862
7863 // Step 17
7864 if (!rangeStart && !rangeEnd) {
7865 return Nothing();
7866 }
7867
7868 // Step 18
7869 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
7870 return Nothing();
7871 }
7872
7873 return Some(ParsedRange(rangeStart, rangeEnd));
7874}
7875
7876// static
7877bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
7878 const nsACString& aHeaderValue) {
7879 const char* cur = aHeaderValue.BeginReading();
7880 const char* end = aHeaderValue.EndReading();
7881
7882 while (cur != end) {
7883 // Implementation of
7884 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
7885 // than a space but not a horizontal tab
7886 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
7887 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
7888 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
7889 *cur == ']' || *cur == '{' || *cur == '}' ||
7890 *cur == 0x7F) { // 0x75 is DEL
7891 return true;
7892 }
7893 cur++;
7894 }
7895 return false;
7896}
7897
7898// static
7899bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
7900 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7901 return false;
7902 }
7903 return true;
7904}
7905
7906// static
7907bool nsContentUtils::IsAllowedNonCorsContentType(
7908 const nsACString& aHeaderValue) {
7909 nsAutoCString contentType;
7910 nsAutoCString unused;
7911
7912 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
7913 return false;
7914 }
7915
7916 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
7917 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7918 return false;
7919 }
7920
7921 return contentType.LowerCaseEqualsLiteral("text/plain") ||
7922 contentType.LowerCaseEqualsLiteral(
7923 "application/x-www-form-urlencoded") ||
7924 contentType.LowerCaseEqualsLiteral("multipart/form-data");
7925}
7926
7927// static
7928bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
7929 const char* cur = aHeaderValue.BeginReading();
7930 const char* end = aHeaderValue.EndReading();
7931
7932 while (cur != end) {
7933 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
7934 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
7935 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
7936 *cur == '=') {
7937 cur++;
7938 continue;
7939 }
7940 return false;
7941 }
7942 return true;
7943}
7944
7945bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
7946 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
7947 if (!parsedRange) {
7948 return false;
7949 }
7950
7951 if (!parsedRange->Start()) {
7952 return false;
7953 }
7954
7955 return true;
7956}
7957
7958// static
7959bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
7960 const nsACString& aValue) {
7961 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
7962 if (aValue.Length() > 128) {
7963 return false;
7964 }
7965 return (aName.LowerCaseEqualsLiteral("accept") &&
7966 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
7967 (aName.LowerCaseEqualsLiteral("accept-language") &&
7968 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7969 (aName.LowerCaseEqualsLiteral("content-language") &&
7970 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
7971 (aName.LowerCaseEqualsLiteral("content-type") &&
7972 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
7973 (aName.LowerCaseEqualsLiteral("range") &&
7974 nsContentUtils::IsAllowedNonCorsRange(aValue));
7975}
7976
7977mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
7978 return gResistFingerprintingLog;
7979}
7980mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
7981
7982bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7983 nsAString& aResult,
7984 const fallible_t& aFallible) {
7985 aResult.Truncate();
7986 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7987}
7988
7989void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
7990 nsAString& aResult) {
7991 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
7992 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
7993 }
7994}
7995
7996void nsContentUtils::DestroyMatchString(void* aData) {
7997 if (aData) {
7998 nsString* matchString = static_cast<nsString*>(aData);
7999 delete matchString;
8000 }
8001}
8002
8003// Table ordered from most to least likely JS MIME types.
8004static constexpr std::string_view kJavascriptMIMETypes[] = {
8005 "text/javascript",
8006 "text/ecmascript",
8007 "application/javascript",
8008 "application/ecmascript",
8009 "application/x-javascript",
8010 "application/x-ecmascript",
8011 "text/javascript1.0",
8012 "text/javascript1.1",
8013 "text/javascript1.2",
8014 "text/javascript1.3",
8015 "text/javascript1.4",
8016 "text/javascript1.5",
8017 "text/jscript",
8018 "text/livescript",
8019 "text/x-ecmascript",
8020 "text/x-javascript"};
8021
8022bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
8023 for (std::string_view type : kJavascriptMIMETypes) {
8024 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
8025 return true;
8026 }
8027 }
8028 return false;
8029}
8030
8031bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
8032 for (std::string_view type : kJavascriptMIMETypes) {
8033 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
8034 return true;
8035 }
8036 }
8037 return false;
8038}
8039
8040bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
8041 //
8042 // SECURITY CHECK: disable prefetching and preloading from mailnews!
8043 //
8044 // walk up the docshell tree to see if any containing
8045 // docshell are of type MAIL.
8046 //
8047
8048 if (!aDocShell) {
8049 return false;
8050 }
8051
8052 nsCOMPtr<nsIDocShell> docshell = aDocShell;
8053 nsCOMPtr<nsIDocShellTreeItem> parentItem;
8054
8055 do {
8056 auto appType = docshell->GetAppType();
8057 if (appType == nsIDocShell::APP_TYPE_MAIL) {
8058 return false; // do not prefetch, preload, preconnect from mailnews
8059 }
8060
8061 docshell->GetInProcessParent(getter_AddRefs(parentItem));
8062 if (parentItem) {
8063 docshell = do_QueryInterface(parentItem);
8064 if (!docshell) {
8065 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"
, 8065); MOZ_PretendNoReturn(); } while (0)
;
8066 return false;
8067 }
8068 }
8069 } while (parentItem);
8070
8071 return true;
8072}
8073
8074uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
8075 // can't do anything if there's no nsIRequest!
8076 if (!aRequest) {
8077 return 0;
8078 }
8079
8080 nsCOMPtr<nsILoadGroup> loadGroup;
8081 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
8082
8083 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
8084 return 0;
8085 }
8086
8087 return GetInnerWindowID(loadGroup);
8088}
8089
8090uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
8091 if (!aLoadGroup) {
8092 return 0;
8093 }
8094
8095 nsCOMPtr<nsIInterfaceRequestor> callbacks;
8096 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
8097 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
8098 return 0;
8099 }
8100
8101 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
8102 if (!loadContext) {
8103 return 0;
8104 }
8105
8106 nsCOMPtr<mozIDOMWindowProxy> window;
8107 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
8108 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
8109 return 0;
8110 }
8111
8112 auto* pwindow = nsPIDOMWindowOuter::From(window);
8113 if (!pwindow) {
8114 return 0;
8115 }
8116
8117 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
8118 return inner ? inner->WindowID() : 0;
8119}
8120
8121// static
8122void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
8123 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
8124 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"
, 8125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
")"); do { *((volatile int*)__null) = 8125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8125 (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"
, 8125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')"
")"); do { *((volatile int*)__null) = 8125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8126 aHost.Insert('[', 0);
8127 aHost.Append(']');
8128 }
8129}
8130
8131nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8132 nsACString& aHost) {
8133 aHost.Truncate();
8134 nsresult rv = aURI->GetHost(aHost);
8135 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8136 return rv;
8137 }
8138
8139 MaybeFixIPv6Host(aHost);
8140
8141 return NS_OK;
8142}
8143
8144nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
8145 nsAString& aHost) {
8146 nsAutoCString hostname;
8147 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
8148 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8149 return rv;
8150 }
8151 CopyUTF8toUTF16(hostname, aHost);
8152 return NS_OK;
8153}
8154
8155nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
8156 nsACString& aHost) {
8157 nsresult rv = aPrincipal->GetAsciiHost(aHost);
8158 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
8159 return rv;
8160 }
8161
8162 MaybeFixIPv6Host(aHost);
8163 return NS_OK;
8164}
8165
8166CallState nsContentUtils::CallOnAllRemoteChildren(
8167 MessageBroadcaster* aManager,
8168 const std::function<CallState(BrowserParent*)>& aCallback) {
8169 uint32_t browserChildCount = aManager->ChildCount();
8170 for (uint32_t j = 0; j < browserChildCount; ++j) {
8171 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
8172 if (!childMM) {
8173 continue;
8174 }
8175
8176 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
8177 if (nonLeafMM) {
8178 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
8179 return CallState::Stop;
8180 }
8181 continue;
8182 }
8183
8184 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
8185 if (cb) {
8186 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
8187 BrowserParent* remote = BrowserParent::GetFrom(fl);
8188 if (remote && aCallback) {
8189 if (aCallback(remote) == CallState::Stop) {
8190 return CallState::Stop;
8191 }
8192 }
8193 }
8194 }
8195
8196 return CallState::Continue;
8197}
8198
8199void nsContentUtils::CallOnAllRemoteChildren(
8200 nsPIDOMWindowOuter* aWindow,
8201 const std::function<CallState(BrowserParent*)>& aCallback) {
8202 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
8203 if (window->IsChromeWindow()) {
8204 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
8205 if (windowMM) {
8206 CallOnAllRemoteChildren(windowMM, aCallback);
8207 }
8208 }
8209}
8210
8211bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
8212 const IPCTransferableDataItem& aItem) {
8213 // Unknown types are converted to kCustomTypesMime.
8214 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
8215 return true;
8216 }
8217
8218 for (const char* format : DataTransfer::kKnownFormats) {
8219 if (aItem.flavor().EqualsASCII(format)) {
8220 return true;
8221 }
8222 }
8223
8224 return false;
8225}
8226
8227nsresult nsContentUtils::IPCTransferableDataToTransferable(
8228 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
8229 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8230 nsresult rv;
8231 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
8232 for (const auto& item : items) {
8233 if (aFilterUnknownFlavors && !IPCTransferableDataItemHasKnownFlavor(item)) {
8234 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"
, 8236)
8235 "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"
, 8236)
8236 "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"
, 8236)
;
8237 continue;
8238 }
8239
8240 if (aAddDataFlavor) {
8241 aTransferable->AddDataFlavor(item.flavor().get());
8242 }
8243
8244 nsCOMPtr<nsISupports> transferData;
8245 switch (item.data().type()) {
8246 case IPCTransferableDataType::TIPCTransferableDataString: {
8247 const auto& data = item.data().get_IPCTransferableDataString();
8248 nsCOMPtr<nsISupportsString> dataWrapper =
8249 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
8250 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"
, 8250); return rv; } } while (false)
;
8251 rv = dataWrapper->SetData(nsDependentSubstring(
8252 reinterpret_cast<const char16_t*>(data.data().Data()),
8253 data.data().Size() / sizeof(char16_t)));
8254 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"
, 8254); return rv; } } while (false)
;
8255 transferData = dataWrapper;
8256 break;
8257 }
8258 case IPCTransferableDataType::TIPCTransferableDataCString: {
8259 const auto& data = item.data().get_IPCTransferableDataCString();
8260 nsCOMPtr<nsISupportsCString> dataWrapper =
8261 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
8262 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"
, 8262); return rv; } } while (false)
;
8263 rv = dataWrapper->SetData(nsDependentCSubstring(
8264 reinterpret_cast<const char*>(data.data().Data()),
8265 data.data().Size()));
8266 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"
, 8266); return rv; } } while (false)
;
8267 transferData = dataWrapper;
8268 break;
8269 }
8270 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8271 const auto& data = item.data().get_IPCTransferableDataInputStream();
8272 nsCOMPtr<nsIInputStream> stream;
8273 rv = NS_NewByteInputStream(getter_AddRefs(stream),
8274 AsChars(data.data().AsSpan()),
8275 NS_ASSIGNMENT_COPY);
8276 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"
, 8276); return rv; } } while (false)
;
8277 transferData = stream.forget();
8278 break;
8279 }
8280 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8281 const auto& data = item.data().get_IPCTransferableDataImageContainer();
8282 nsCOMPtr<imgIContainer> container;
8283 rv = DeserializeTransferableDataImageContainer(
8284 data, getter_AddRefs(container));
8285 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"
, 8285); return rv; } } while (false)
;
8286 transferData = container;
8287 break;
8288 }
8289 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8290 const auto& data = item.data().get_IPCTransferableDataBlob();
8291 transferData = IPCBlobUtils::Deserialize(data.blob());
8292 break;
8293 }
8294 case IPCTransferableDataType::T__None:
8295 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"
, 8295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8295; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8296 return NS_ERROR_FAILURE;
8297 }
8298
8299 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
8300 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"
, 8300); return rv; } } while (false)
;
8301 }
8302 return NS_OK;
8303}
8304
8305nsresult nsContentUtils::IPCTransferableToTransferable(
8306 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
8307 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
8308 // Note that we need to set privacy status of transferable before adding any
8309 // data into it.
8310 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
8311
8312 nsresult rv =
8313 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
8314 aTransferable, aFilterUnknownFlavors);
8315 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"
, 8315); return rv; } } while (false)
;
8316
8317 if (aIPCTransferable.cookieJarSettings().isSome()) {
8318 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
8319 net::CookieJarSettings::Deserialize(
8320 aIPCTransferable.cookieJarSettings().ref(),
8321 getter_AddRefs(cookieJarSettings));
8322 aTransferable->SetCookieJarSettings(cookieJarSettings);
8323 }
8324 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
8325 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
8326 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
8327
8328 return NS_OK;
8329}
8330
8331nsresult nsContentUtils::IPCTransferableDataItemToVariant(
8332 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
8333 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"
, 8333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { *((volatile int*)__null) = 8333; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8334
8335 switch (aItem.data().type()) {
8336 case IPCTransferableDataType::TIPCTransferableDataString: {
8337 const auto& data = aItem.data().get_IPCTransferableDataString();
8338 return aVariant->SetAsAString(nsDependentSubstring(
8339 reinterpret_cast<const char16_t*>(data.data().Data()),
8340 data.data().Size() / sizeof(char16_t)));
8341 }
8342 case IPCTransferableDataType::TIPCTransferableDataCString: {
8343 const auto& data = aItem.data().get_IPCTransferableDataCString();
8344 return aVariant->SetAsACString(nsDependentCSubstring(
8345 reinterpret_cast<const char*>(data.data().Data()),
8346 data.data().Size()));
8347 }
8348 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
8349 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
8350 nsCOMPtr<nsIInputStream> stream;
8351 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
8352 AsChars(data.data().AsSpan()),
8353 NS_ASSIGNMENT_COPY);
8354 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"
, 8354); return rv; } } while (false)
;
8355 return aVariant->SetAsISupports(stream);
8356 }
8357 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
8358 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
8359 nsCOMPtr<imgIContainer> container;
8360 nsresult rv = DeserializeTransferableDataImageContainer(
8361 data, getter_AddRefs(container));
8362 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"
, 8362); return rv; } } while (false)
;
8363 return aVariant->SetAsISupports(container);
8364 }
8365 case IPCTransferableDataType::TIPCTransferableDataBlob: {
8366 const auto& data = aItem.data().get_IPCTransferableDataBlob();
8367 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
8368 return aVariant->SetAsISupports(blobImpl);
8369 }
8370 case IPCTransferableDataType::T__None:
8371 break;
8372 }
8373
8374 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"
, 8374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null
) = 8374; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8375 return NS_ERROR_UNEXPECTED;
8376}
8377
8378void nsContentUtils::TransferablesToIPCTransferableDatas(
8379 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
8380 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8381 aIPC.Clear();
8382 if (aTransferables) {
8383 uint32_t transferableCount = 0;
8384 aTransferables->GetLength(&transferableCount);
8385 for (uint32_t i = 0; i < transferableCount; ++i) {
8386 IPCTransferableData* dt = aIPC.AppendElement();
8387 nsCOMPtr<nsITransferable> transferable =
8388 do_QueryElementAt(aTransferables, i);
8389 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
8390 aParent);
8391 }
8392 }
8393}
8394
8395nsresult nsContentUtils::CalculateBufferSizeForImage(
8396 const uint32_t& aStride, const IntSize& aImageSize,
8397 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
8398 size_t* aUsedBufferSize) {
8399 CheckedInt32 requiredBytes =
8400 CheckedInt32(aStride) * CheckedInt32(aImageSize.height);
8401
8402 CheckedInt32 usedBytes =
8403 requiredBytes - aStride +
8404 (CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat));
8405 if (!usedBytes.isValid()) {
8406 return NS_ERROR_FAILURE;
8407 }
8408
8409 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"
, 8409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "requiredBytes.isValid()"
") (" "usedBytes valid but not required?" ")"); do { *((volatile
int*)__null) = 8409; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8410 *aMaxBufferSize = requiredBytes.value();
8411 *aUsedBufferSize = usedBytes.value();
8412 return NS_OK;
8413}
8414
8415static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
8416 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
8417 SurfaceFormat aFormat) {
8418 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
8419 return nullptr;
8420 }
8421
8422 // Validate shared memory buffer size
8423 size_t imageBufLen = 0;
8424 size_t maxBufLen = 0;
8425 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
8426 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
8427 return nullptr;
8428 }
8429 if (imageBufLen > aData.Size()) {
8430 return nullptr;
8431 }
8432 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
8433 aStride);
8434}
8435
8436nsresult nsContentUtils::DeserializeTransferableDataImageContainer(
8437 const IPCTransferableDataImageContainer& aData,
8438 imgIContainer** aContainer) {
8439 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aData.image());
8440 if (!surface) {
8441 return NS_ERROR_FAILURE;
8442 }
8443
8444 RefPtr<gfxDrawable> drawable =
8445 new gfxSurfaceDrawable(surface, surface->GetSize());
8446 nsCOMPtr<imgIContainer> imageContainer =
8447 image::ImageOps::CreateFromDrawable(drawable);
8448 imageContainer.forget(aContainer);
8449
8450 return NS_OK;
8451}
8452
8453bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
8454 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
8455 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
8456 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
8457 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
8458 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
8459}
8460
8461// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
8462// will be implicitly serialized in shmem when sent over IPDL directly.
8463static IPCTransferableDataString AsIPCTransferableDataString(
8464 Span<const char16_t> aInput) {
8465 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
8466}
8467
8468// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
8469// will be implicitly serialized in shmem when sent over IPDL directly.
8470static IPCTransferableDataCString AsIPCTransferableDataCString(
8471 Span<const char> aInput) {
8472 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
8473}
8474
8475void nsContentUtils::TransferableToIPCTransferableData(
8476 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
8477 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8478 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"
, 8478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { *((volatile int*)__null) = 8478; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8479
8480 if (aTransferable) {
8481 nsTArray<nsCString> flavorList;
8482 aTransferable->FlavorsTransferableCanExport(flavorList);
8483
8484 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
8485 nsCString& flavorStr = flavorList[j];
8486 if (!flavorStr.Length()) {
8487 continue;
8488 }
8489
8490 nsCOMPtr<nsISupports> data;
8491 nsresult rv =
8492 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
8493
8494 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
8495 if (aInSyncMessage) {
8496 // Can't do anything.
8497 // FIXME: This shouldn't be the case anymore!
8498 continue;
8499 }
8500
8501 // This is a hack to support kFilePromiseMime.
8502 // On Windows there just needs to be an entry for it,
8503 // and for OSX we need to create
8504 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
8505 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
8506 IPCTransferableDataItem* item =
8507 aTransferableData->items().AppendElement();
8508 item->flavor() = flavorStr;
8509 item->data() =
8510 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
8511 continue;
8512 }
8513
8514 // Empty element, transfer only the flavor
8515 IPCTransferableDataItem* item =
8516 aTransferableData->items().AppendElement();
8517 item->flavor() = flavorStr;
8518 item->data() = AsIPCTransferableDataString(EmptyString());
8519 continue;
8520 }
8521
8522 // We need to handle nsIInputStream before nsISupportsCString, otherwise
8523 // nsStringInputStream would be converted into a wrong type.
8524 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
8525 IPCTransferableDataItem* item =
8526 aTransferableData->items().AppendElement();
8527 item->flavor() = flavorStr;
8528 nsCString imageData;
8529 DebugOnly<nsresult> rv =
8530 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
8531 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"
, 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8532 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"
, 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8533 "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"
, 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8534 // FIXME: This can probably be simplified once bug 1783240 lands, as
8535 // `nsCString` will be implicitly serialized in shmem when sent over
8536 // IPDL directly.
8537 item->data() =
8538 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
8539 continue;
8540 }
8541
8542 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
8543 nsAutoString dataAsString;
8544 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"
, 8544); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"); do
{ *((volatile int*)__null) = 8544; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
8545
8546 IPCTransferableDataItem* item =
8547 aTransferableData->items().AppendElement();
8548 item->flavor() = flavorStr;
8549 item->data() = AsIPCTransferableDataString(dataAsString);
8550 continue;
8551 }
8552
8553 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
8554 nsAutoCString dataAsString;
8555 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"
, 8555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(ctext->GetData(dataAsString))" ")"); do
{ *((volatile int*)__null) = 8555; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
8556
8557 IPCTransferableDataItem* item =
8558 aTransferableData->items().AppendElement();
8559 item->flavor() = flavorStr;
8560 item->data() = AsIPCTransferableDataCString(dataAsString);
8561 continue;
8562 }
8563
8564 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
8565 // Images to be placed on the clipboard are imgIContainers.
8566 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
8567 imgIContainer::FRAME_CURRENT,
8568 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
8569 if (!surface) {
8570 continue;
8571 }
8572 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
8573 surface->GetDataSurface();
8574 if (!dataSurface) {
8575 continue;
8576 }
8577
8578 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
8579 if (!imageData) {
8580 continue;
8581 }
8582
8583 IPCTransferableDataItem* item =
8584 aTransferableData->items().AppendElement();
8585 item->flavor() = flavorStr;
8586 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
8587 continue;
8588 }
8589
8590 // Otherwise, handle this as a file.
8591 nsCOMPtr<BlobImpl> blobImpl;
8592 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
8593 if (aParent) {
8594 bool isDir = false;
8595 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
8596 nsAutoString path;
8597 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"
, 8597)
) {
8598 continue;
8599 }
8600
8601 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
8602 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
8603 }
8604 }
8605
8606 blobImpl = new FileBlobImpl(file);
8607
8608 IgnoredErrorResult rv;
8609
8610 // Ensure that file data is cached no that the content process
8611 // has this data available to it when passed over:
8612 blobImpl->GetSize(rv);
8613 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"
, 8613)
) {
8614 continue;
8615 }
8616
8617 blobImpl->GetLastModified(rv);
8618 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"
, 8618)
) {
8619 continue;
8620 }
8621 } else {
8622 if (aInSyncMessage) {
8623 // Can't do anything.
8624 // FIXME: This shouldn't be the case anymore!
8625 continue;
8626 }
8627
8628 blobImpl = do_QueryInterface(data);
8629 }
8630
8631 if (blobImpl) {
8632 // If we failed to create the blob actor, then this blob probably
8633 // can't get the file size for the underlying file, ignore it for
8634 // now. TODO pass this through anyway.
8635 IPCBlob ipcBlob;
8636 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
8637 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"
, 8637)
) {
8638 continue;
8639 }
8640
8641 IPCTransferableDataItem* item =
8642 aTransferableData->items().AppendElement();
8643 item->flavor() = flavorStr;
8644 item->data() = IPCTransferableDataBlob(ipcBlob);
8645 }
8646 }
8647 }
8648}
8649
8650void nsContentUtils::TransferableToIPCTransferable(
8651 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
8652 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
8653 IPCTransferableData ipcTransferableData;
8654 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
8655 aInSyncMessage, aParent);
8656
8657 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
8658 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
8659 aTransferable->GetCookieJarSettings()) {
8660 net::CookieJarSettingsArgs args;
8661 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
8662 cookieJarSettingsArgs = Some(std::move(args));
8663 }
8664
8665 aIPCTransferable->data() = std::move(ipcTransferableData);
8666 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
8667 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
8668 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
8669 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
8670 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
8671}
8672
8673Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
8674 size_t* aLength,
8675 int32_t* aStride) {
8676 mozilla::gfx::DataSourceSurface::MappedSurface map;
8677 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
8678 return Nothing();
8679 }
8680
8681 size_t bufLen = 0;
8682 size_t maxBufLen = 0;
8683 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
8684 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
8685 &bufLen);
8686 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8687 aSurface.Unmap();
8688 return Nothing();
8689 }
8690
8691 BigBuffer surfaceData(maxBufLen);
8692 memcpy(surfaceData.Data(), map.mData, bufLen);
8693 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
8694
8695 *aLength = maxBufLen;
8696 *aStride = map.mStride;
8697
8698 aSurface.Unmap();
8699 return Some(std::move(surfaceData));
8700}
8701
8702Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
8703 size_t len = 0;
8704 int32_t stride = 0;
8705 auto mem = GetSurfaceData(aSurface, &len, &stride);
8706 if (!mem) {
8707 return Nothing();
8708 }
8709 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
8710 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
8711}
8712
8713already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
8714 const IPCImage& aImage) {
8715 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
8716 aImage.size().ToUnknownSize(), aImage.format());
8717}
8718
8719Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
8720 Modifiers result = 0;
8721 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
8722 result |= mozilla::MODIFIER_SHIFT;
8723 }
8724 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
8725 result |= mozilla::MODIFIER_CONTROL;
8726 }
8727 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
8728 result |= mozilla::MODIFIER_ALT;
8729 }
8730 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
8731 result |= mozilla::MODIFIER_META;
8732 }
8733 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
8734 result |= mozilla::MODIFIER_ALTGRAPH;
8735 }
8736 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
8737 result |= mozilla::MODIFIER_CAPSLOCK;
8738 }
8739 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
8740 result |= mozilla::MODIFIER_FN;
8741 }
8742 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
8743 result |= mozilla::MODIFIER_FNLOCK;
8744 }
8745 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
8746 result |= mozilla::MODIFIER_NUMLOCK;
8747 }
8748 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
8749 result |= mozilla::MODIFIER_SCROLLLOCK;
8750 }
8751 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
8752 result |= mozilla::MODIFIER_SYMBOL;
8753 }
8754 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
8755 result |= mozilla::MODIFIER_SYMBOLLOCK;
8756 }
8757 return result;
8758}
8759
8760nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
8761 if (!aPresShell) {
8762 return nullptr;
8763 }
8764 nsIFrame* frame = aPresShell->GetRootFrame();
8765 if (!frame) {
8766 return nullptr;
8767 }
8768 return frame->GetView()->GetNearestWidget(aOffset);
8769}
8770
8771int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
8772 switch (aButton) {
8773 case -1:
8774 return MouseButtonsFlag::eNoButtons;
8775 case MouseButton::ePrimary:
8776 return MouseButtonsFlag::ePrimaryFlag;
8777 case MouseButton::eMiddle:
8778 return MouseButtonsFlag::eMiddleFlag;
8779 case MouseButton::eSecondary:
8780 return MouseButtonsFlag::eSecondaryFlag;
8781 case 3:
8782 return MouseButtonsFlag::e4thFlag;
8783 case 4:
8784 return MouseButtonsFlag::e5thFlag;
8785 case MouseButton::eEraser:
8786 return MouseButtonsFlag::eEraserFlag;
8787 default:
8788 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"
, 8788); MOZ_PretendNoReturn(); } while (0)
;
8789 return 0;
8790 }
8791}
8792
8793LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
8794 const CSSPoint& aPoint, const nsPoint& aOffset,
8795 nsPresContext* aPresContext) {
8796 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
8797 nsPoint visualRelative =
8798 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
8799 return LayoutDeviceIntPoint::FromAppUnitsRounded(
8800 visualRelative, aPresContext->AppUnitsPerDevPixel());
8801}
8802
8803nsView* nsContentUtils::GetViewToDispatchEvent(nsPresContext* aPresContext,
8804 PresShell** aPresShell) {
8805 if (!aPresContext || !aPresShell) {
8806 return nullptr;
8807 }
8808 RefPtr<PresShell> presShell = aPresContext->PresShell();
8809 if (NS_WARN_IF(!presShell)NS_warn_if_impl(!presShell, "!presShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 8809)
) {
8810 *aPresShell = nullptr;
8811 return nullptr;
8812 }
8813 nsViewManager* viewManager = presShell->GetViewManager();
8814 if (!viewManager) {
8815 presShell.forget(aPresShell); // XXX Is this intentional?
8816 return nullptr;
8817 }
8818 presShell.forget(aPresShell);
8819 return viewManager->GetRootView();
8820}
8821
8822nsresult nsContentUtils::SendMouseEvent(
8823 mozilla::PresShell* aPresShell, const nsAString& aType, float aX, float aY,
8824 int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers,
8825 bool aIgnoreRootScrollFrame, float aPressure,
8826 unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
8827 PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
8828 bool aIsWidgetEventSynthesized) {
8829 nsPoint offset;
8830 nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
8831 if (!widget) return NS_ERROR_FAILURE;
8832
8833 EventMessage msg;
8834 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
8835 bool contextMenuKey = false;
8836 if (aType.EqualsLiteral("mousedown")) {
8837 msg = eMouseDown;
8838 } else if (aType.EqualsLiteral("mouseup")) {
8839 msg = eMouseUp;
8840 } else if (aType.EqualsLiteral("mousemove")) {
8841 msg = eMouseMove;
8842 } else if (aType.EqualsLiteral("mouseover")) {
8843 msg = eMouseEnterIntoWidget;
8844 } else if (aType.EqualsLiteral("mouseout")) {
8845 msg = eMouseExitFromWidget;
8846 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
8847 } else if (aType.EqualsLiteral("mousecancel")) {
8848 msg = eMouseExitFromWidget;
8849 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
8850 : WidgetMouseEvent::ePuppet);
8851 } else if (aType.EqualsLiteral("mouselongtap")) {
8852 msg = eMouseLongTap;
8853 } else if (aType.EqualsLiteral("contextmenu")) {
8854 msg = eContextMenu;
8855 contextMenuKey = (aButton == 0);
8856 } else if (aType.EqualsLiteral("MozMouseHittest")) {
8857 msg = eMouseHitTest;
8858 } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
8859 msg = eMouseExploreByTouch;
8860 } else {
8861 return NS_ERROR_FAILURE;
8862 }
8863
8864 if (aInputSourceArg == MouseEvent_Binding::MOZ_SOURCE_UNKNOWN) {
8865 aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
8866 }
8867
8868 Maybe<WidgetPointerEvent> pointerEvent;
8869 Maybe<WidgetMouseEvent> mouseEvent;
8870 if (IsPointerEventMessage(msg)) {
8871 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"
, 8872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8872; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8872 "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"
, 8872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized"
") (" "The event shouldn't be dispatched as a synthesized event"
")"); do { *((volatile int*)__null) = 8872; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8873 if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)(__builtin_expect(!!(aIsWidgetEventSynthesized), 0))) {
8874 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
8875 // synthesized event.
8876 return NS_ERROR_INVALID_ARG;
8877 }
8878 pointerEvent.emplace(true, msg, widget,
8879 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8880 : WidgetMouseEvent::eNormal);
8881 } else {
8882 mouseEvent.emplace(true, msg, widget,
8883 aIsWidgetEventSynthesized
8884 ? WidgetMouseEvent::eSynthesized
8885 : WidgetMouseEvent::eReal,
8886 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
8887 : WidgetMouseEvent::eNormal);
8888 }
8889 WidgetMouseEvent& mouseOrPointerEvent =
8890 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
8891 mouseOrPointerEvent.pointerId = aIdentifier;
8892 mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers);
8893 mouseOrPointerEvent.mButton = aButton;
8894 mouseOrPointerEvent.mButtons =
8895 aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ? aButtons
8896 : msg == eMouseUp ? 0
8897 : GetButtonsFlagForButton(aButton);
8898 mouseOrPointerEvent.mPressure = aPressure;
8899 mouseOrPointerEvent.mInputSource = aInputSourceArg;
8900 mouseOrPointerEvent.mClickCount = aClickCount;
8901 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
8902 mouseOrPointerEvent.mExitFrom = exitFrom;
8903
8904 nsPresContext* presContext = aPresShell->GetPresContext();
8905 if (!presContext) return NS_ERROR_FAILURE;
8906
8907 mouseOrPointerEvent.mRefPoint =
8908 ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
8909 mouseOrPointerEvent.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
8910
8911 nsEventStatus status = nsEventStatus_eIgnore;
8912 if (aToWindow) {
8913 RefPtr<PresShell> presShell;
8914 nsView* view =
8915 GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
8916 if (!presShell || !view) {
8917 return NS_ERROR_FAILURE;
8918 }
8919 return presShell->HandleEvent(view->GetFrame(), &mouseOrPointerEvent, false,
8920 &status);
8921 }
8922 if (StaticPrefs::test_events_async_enabled()) {
8923 status = widget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
8924 } else {
8925 nsresult rv = widget->DispatchEvent(&mouseOrPointerEvent, status);
8926 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"
, 8926); return rv; } } while (false)
;
8927 }
8928 if (aPreventDefault) {
8929 if (status == nsEventStatus_eConsumeNoDefault) {
8930 if (mouseOrPointerEvent.mFlags.mDefaultPreventedByContent) {
8931 *aPreventDefault = PreventDefaultResult::ByContent;
8932 } else {
8933 *aPreventDefault = PreventDefaultResult::ByChrome;
8934 }
8935 } else {
8936 *aPreventDefault = PreventDefaultResult::No;
8937 }
8938 }
8939
8940 return NS_OK;
8941}
8942
8943/* static */
8944void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
8945 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8946 bool aOnlySystemGroup) {
8947 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"
, 8947); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { *((volatile int*)__null) = 8947; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8948 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"
, 8948); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler"
")"); do { *((volatile int*)__null) = 8948; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8949
8950 RefPtr<Document> doc = aItem->GetDocument();
8951 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"
, 8951); MOZ_PretendNoReturn(); } } while (0)
;
8952 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
8953
8954 int32_t childCount = 0;
8955 aItem->GetInProcessChildCount(&childCount);
8956 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8957 kids.AppendElements(childCount);
8958 for (int32_t i = 0; i < childCount; ++i) {
8959 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8960 }
8961
8962 for (uint32_t i = 0; i < kids.Length(); ++i) {
8963 if (kids[i]) {
8964 FirePageHideEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8965 aOnlySystemGroup);
8966 }
8967 }
8968}
8969
8970// The pageshow event is fired for a given document only if IsShowing() returns
8971// the same thing as aFireIfShowing. This gives us a way to fire pageshow only
8972// on documents that are still loading or only on documents that are already
8973// loaded.
8974/* static */
8975void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
8976 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
8977 bool aFireIfShowing, bool aOnlySystemGroup) {
8978 int32_t childCount = 0;
8979 aItem->GetInProcessChildCount(&childCount);
8980 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8981 kids.AppendElements(childCount);
8982 for (int32_t i = 0; i < childCount; ++i) {
8983 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
8984 }
8985
8986 for (uint32_t i = 0; i < kids.Length(); ++i) {
8987 if (kids[i]) {
8988 FirePageShowEventForFrameLoaderSwap(kids[i], aChromeEventHandler,
8989 aFireIfShowing, aOnlySystemGroup);
8990 }
8991 }
8992
8993 RefPtr<Document> doc = aItem->GetDocument();
8994 if (doc && doc->IsShowing() == aFireIfShowing) {
8995 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
8996 }
8997}
8998
8999/* static */
9000already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
9001 if (aDoc) {
9002 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
9003 return win->GetTopWindowRoot();
9004 }
9005 }
9006 return nullptr;
9007}
9008
9009/* static */
9010bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
9011 nsIURI* aDocURI) {
9012 if (aAnchor.IsEmpty()) {
9013 // anchor parameter not present or empty -> same document reference
9014 return true;
9015 }
9016
9017 // the document URI might contain a fragment identifier ("#...')
9018 // we want to ignore that because it's invisible to the server
9019 // and just affects the local interpretation in the recipient
9020 nsCOMPtr<nsIURI> contextUri;
9021 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
9022
9023 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9024 // copying failed
9025 return false;
9026 }
9027
9028 // resolve anchor against context
9029 nsCOMPtr<nsIURI> resolvedUri;
9030 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
9031
9032 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9033 // resolving failed
9034 return false;
9035 }
9036
9037 bool same;
9038 rv = contextUri->Equals(resolvedUri, &same);
9039 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9040 // comparison failed
9041 return false;
9042 }
9043
9044 return same;
9045}
9046
9047/* static */
9048bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
9049 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
9050 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
9051 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
9052 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
9053 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
9054 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
9055}
9056
9057// static
9058ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
9059 nsIChannel* aChannel) {
9060 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
9061 if (!httpChannel) {
9062 return ReferrerPolicy::_empty;
9063 }
9064
9065 nsresult rv;
9066 nsAutoCString headerValue;
9067 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
9068 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
9069 return ReferrerPolicy::_empty;
9070 }
9071
9072 return ReferrerInfo::ReferrerPolicyFromHeaderString(
9073 NS_ConvertUTF8toUTF16(headerValue));
9074}
9075
9076// static
9077bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
9078 nsLoadFlags loadFlags = 0;
9079 aChannel->GetLoadFlags(&loadFlags);
9080 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
9081 return true;
9082 }
9083
9084 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9085 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
9086 return IsNonSubresourceInternalPolicyType(type);
9087}
9088
9089// static
9090bool nsContentUtils::IsNonSubresourceInternalPolicyType(
9091 nsContentPolicyType aType) {
9092 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
9093 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
9094 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
9095 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
9096 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
9097}
9098
9099// static public
9100bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
9101 nsPIDOMWindowInner* aWindow) {
9102 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"
, 9102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9102; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9103
9104 Document* document = aWindow->GetExtantDoc();
9105 if (!document) {
9106 return false;
9107 }
9108
9109 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9110 do_QueryInterface(document->GetChannel());
9111 if (!classifiedChannel) {
9112 return false;
9113 }
9114
9115 return classifiedChannel->IsThirdPartyTrackingResource();
9116}
9117
9118// static public
9119bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
9120 nsPIDOMWindowInner* aWindow) {
9121 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"
, 9121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 9121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9122
9123 Document* document = aWindow->GetExtantDoc();
9124 if (!document) {
9125 return false;
9126 }
9127
9128 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
9129 do_QueryInterface(document->GetChannel());
9130 if (!classifiedChannel) {
9131 return false;
9132 }
9133
9134 uint32_t classificationFlags =
9135 classifiedChannel->GetFirstPartyClassificationFlags();
9136
9137 return mozilla::net::UrlClassifierCommon::IsTrackingClassificationFlag(
9138 classificationFlags, NS_UsePrivateBrowsing(document->GetChannel()));
9139}
9140
9141namespace {
9142
9143// We put StringBuilder in the anonymous namespace to prevent anything outside
9144// this file from accidentally being linked against it.
9145class BulkAppender {
9146 using size_type = typename nsAString::size_type;
9147
9148 public:
9149 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
9150 : mHandle(std::move(aHandle)), mPosition(0) {}
9151 ~BulkAppender() = default;
9152
9153 template <int N>
9154 void AppendLiteral(const char16_t (&aStr)[N]) {
9155 size_t len = N - 1;
9156 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"
, 9156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9157 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
9158 mPosition += len;
9159 }
9160
9161 void Append(Span<const char16_t> aStr) {
9162 size_t len = aStr.Length();
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 // Both mHandle.Elements() and aStr.Elements() are guaranteed
9165 // to be non-null (by the string implementation and by Span,
9166 // respectively), so not checking the pointers for null before
9167 // memcpy does not lead to UB even if len was zero.
9168 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
9169 len * sizeof(char16_t));
9170 mPosition += len;
9171 }
9172
9173 void Append(Span<const char> aStr) {
9174 size_t len = aStr.Length();
9175 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"
, 9175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()"
")"); do { *((volatile int*)__null) = 9175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9176 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
9177 mPosition += len;
9178 }
9179
9180 void Finish() { mHandle.Finish(mPosition, false); }
9181
9182 private:
9183 BulkWriteHandle<char16_t> mHandle;
9184 size_type mPosition;
9185};
9186
9187class StringBuilder {
9188 private:
9189 class Unit {
9190 public:
9191 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)
; }
9192 ~Unit() {
9193 if (mType == Type::String || mType == Type::StringWithEncode) {
9194 mString.~nsString();
9195 }
9196 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)
;
9197 }
9198
9199 enum class Type : uint8_t {
9200 Unknown,
9201 Atom,
9202 String,
9203 StringWithEncode,
9204 Literal,
9205 TextFragment,
9206 TextFragmentWithEncode,
9207 };
9208
9209 struct LiteralSpan {
9210 const char16_t* mData;
9211 uint32_t mLength;
9212
9213 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
9214 };
9215
9216 union {
9217 nsAtom* mAtom;
9218 LiteralSpan mLiteral;
9219 nsString mString;
9220 const nsTextFragment* mTextFragment;
9221 };
9222 Type mType = Type::Unknown;
9223 };
9224
9225 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
9226 "Unit should remain small");
9227
9228 public:
9229 // Try to keep the size of StringBuilder close to a jemalloc bucket size (the
9230 // 16kb one in this case).
9231 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
9232
9233 // The number of units we need to remove from the inline buffer so that the
9234 // rest of the builder members fit. A more precise approach would be to
9235 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) / sizeof(Unit)
9236 // or so, but this is simpler.
9237 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
9238
9239 static constexpr uint32_t STRING_BUFFER_UNITS =
9240 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
9241
9242 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)
; }
9243
9244 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); }
9245
9246 void Append(nsAtom* aAtom) {
9247 Unit* u = AddUnit();
9248 u->mAtom = aAtom;
9249 u->mType = Unit::Type::Atom;
9250 uint32_t len = aAtom->GetLength();
9251 mLength += len;
9252 }
9253
9254 template <int N>
9255 void Append(const char16_t (&aLiteral)[N]) {
9256 constexpr uint32_t len = N - 1;
9257 Unit* u = AddUnit();
9258 u->mLiteral = {aLiteral, len};
9259 u->mType = Unit::Type::Literal;
9260 mLength += len;
9261 }
9262
9263 void Append(nsString&& aString) {
9264 Unit* u = AddUnit();
9265 uint32_t len = aString.Length();
9266 new (&u->mString) nsString(std::move(aString));
9267 u->mType = Unit::Type::String;
9268 mLength += len;
9269 }
9270
9271 // aLen can be !isValid(), which will get propagated into mLength.
9272 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
9273 Unit* u = AddUnit();
9274 new (&u->mString) nsString(std::move(aString));
9275 u->mType = Unit::Type::StringWithEncode;
9276 mLength += aLen;
9277 }
9278
9279 void Append(const nsTextFragment* aTextFragment) {
9280 Unit* u = AddUnit();
9281 u->mTextFragment = aTextFragment;
9282 u->mType = Unit::Type::TextFragment;
9283 uint32_t len = aTextFragment->GetLength();
9284 mLength += len;
9285 }
9286
9287 // aLen can be !isValid(), which will get propagated into mLength.
9288 void AppendWithEncode(const nsTextFragment* aTextFragment,
9289 CheckedInt<uint32_t> aLen) {
9290 Unit* u = AddUnit();
9291 u->mTextFragment = aTextFragment;
9292 u->mType = Unit::Type::TextFragmentWithEncode;
9293 mLength += aLen;
9294 }
9295
9296 bool ToString(nsAString& aOut) {
9297 if (!mLength.isValid()) {
9298 return false;
9299 }
9300 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
9301 if (appenderOrErr.isErr()) {
9302 return false;
9303 }
9304
9305 BulkAppender appender{appenderOrErr.unwrap()};
9306
9307 for (StringBuilder* current = this; current;
9308 current = current->mNext.get()) {
9309 uint32_t len = current->mUnits.Length();
9310 for (uint32_t i = 0; i < len; ++i) {
9311 Unit& u = current->mUnits[i];
9312 switch (u.mType) {
9313 case Unit::Type::Atom:
9314 appender.Append(*(u.mAtom));
9315 break;
9316 case Unit::Type::String:
9317 appender.Append(u.mString);
9318 break;
9319 case Unit::Type::StringWithEncode:
9320 EncodeAttrString(u.mString, appender);
9321 break;
9322 case Unit::Type::Literal:
9323 appender.Append(u.mLiteral.AsSpan());
9324 break;
9325 case Unit::Type::TextFragment:
9326 if (u.mTextFragment->Is2b()) {
9327 appender.Append(
9328 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()));
9329 } else {
9330 appender.Append(
9331 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()));
9332 }
9333 break;
9334 case Unit::Type::TextFragmentWithEncode:
9335 if (u.mTextFragment->Is2b()) {
9336 EncodeTextFragment(
9337 Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()),
9338 appender);
9339 } else {
9340 EncodeTextFragment(
9341 Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()),
9342 appender);
9343 }
9344 break;
9345 default:
9346 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"
, 9346); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown unit type?"
")"); do { *((volatile int*)__null) = 9346; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9347 }
9348 }
9349 }
9350 appender.Finish();
9351 return true;
9352 }
9353
9354 private:
9355 Unit* AddUnit() {
9356 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
9357 new StringBuilder(this);
9358 }
9359 return mLast->mUnits.AppendElement();
9360 }
9361
9362 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
9363 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)
;
9364 aFirst->mLast->mNext = WrapUnique(this);
9365 aFirst->mLast = this;
9366 }
9367
9368 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
9369 size_t flushedUntil = 0;
9370 size_t currentPosition = 0;
9371 for (char16_t c : aStr) {
9372 switch (c) {
9373 case '"':
9374 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9375 aAppender.AppendLiteral(u"&quot;");
9376 flushedUntil = currentPosition + 1;
9377 break;
9378 case '&':
9379 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9380 aAppender.AppendLiteral(u"&amp;");
9381 flushedUntil = currentPosition + 1;
9382 break;
9383 case 0x00A0:
9384 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9385 aAppender.AppendLiteral(u"&nbsp;");
9386 flushedUntil = currentPosition + 1;
9387 break;
9388 default:
9389 break;
9390 }
9391 currentPosition++;
9392 }
9393 if (currentPosition > flushedUntil) {
9394 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9395 }
9396 }
9397
9398 template <class T>
9399 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
9400 size_t flushedUntil = 0;
9401 size_t currentPosition = 0;
9402 for (T c : aStr) {
9403 switch (c) {
9404 case '<':
9405 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9406 aAppender.AppendLiteral(u"&lt;");
9407 flushedUntil = currentPosition + 1;
9408 break;
9409 case '>':
9410 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9411 aAppender.AppendLiteral(u"&gt;");
9412 flushedUntil = currentPosition + 1;
9413 break;
9414 case '&':
9415 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9416 aAppender.AppendLiteral(u"&amp;");
9417 flushedUntil = currentPosition + 1;
9418 break;
9419 case T(0xA0):
9420 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9421 aAppender.AppendLiteral(u"&nbsp;");
9422 flushedUntil = currentPosition + 1;
9423 break;
9424 default:
9425 break;
9426 }
9427 currentPosition++;
9428 }
9429 if (currentPosition > flushedUntil) {
9430 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
9431 }
9432 }
9433
9434 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
9435 UniquePtr<StringBuilder> mNext;
9436 StringBuilder* mLast;
9437 // mLength is used only in the first StringBuilder object in the linked list.
9438 CheckedInt<uint32_t> mLength;
9439};
9440
9441static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
9442 "StringBuilder should fit in the target bucket");
9443
9444} // namespace
9445
9446static void AppendEncodedCharacters(const nsTextFragment* aText,
9447 StringBuilder& aBuilder) {
9448 uint32_t numEncodedChars = 0;
9449 uint32_t len = aText->GetLength();
9450 if (aText->Is2b()) {
9451 const char16_t* data = aText->Get2b();
9452 for (uint32_t i = 0; i < len; ++i) {
9453 const char16_t c = data[i];
9454 switch (c) {
9455 case '<':
9456 case '>':
9457 case '&':
9458 case 0x00A0:
9459 ++numEncodedChars;
9460 break;
9461 default:
9462 break;
9463 }
9464 }
9465 } else {
9466 const char* data = aText->Get1b();
9467 for (uint32_t i = 0; i < len; ++i) {
9468 const unsigned char c = data[i];
9469 switch (c) {
9470 case '<':
9471 case '>':
9472 case '&':
9473 case 0x00A0:
9474 ++numEncodedChars;
9475 break;
9476 default:
9477 break;
9478 }
9479 }
9480 }
9481
9482 if (numEncodedChars) {
9483 // For simplicity, conservatively estimate the size of the string after
9484 // encoding. This will result in reserving more memory than we actually
9485 // need, but that should be fine unless the string has an enormous number of
9486 // eg < in it. We subtract 1 for the null terminator, then 1 more for the
9487 // existing character that will be replaced.
9488 constexpr uint32_t maxCharExtraSpace =
9489 std::max({ArrayLength("&lt;"), ArrayLength("&gt;"),
9490 ArrayLength("&amp;"), ArrayLength("&nbsp;")}) -
9491 2;
9492 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9493 CheckedInt<uint32_t> maxExtraSpace =
9494 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9495 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
9496 } else {
9497 aBuilder.Append(aText);
9498 }
9499}
9500
9501static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
9502 const nsAString& aValue) {
9503 const char16_t* c = aValue.BeginReading();
9504 const char16_t* end = aValue.EndReading();
9505
9506 uint32_t numEncodedChars = 0;
9507 while (c < end) {
9508 switch (*c) {
9509 case '"':
9510 case '&':
9511 case 0x00A0:
9512 ++numEncodedChars;
9513 break;
9514 default:
9515 break;
9516 }
9517 ++c;
9518 }
9519
9520 if (!numEncodedChars) {
9521 return 0;
9522 }
9523
9524 // For simplicity, conservatively estimate the size of the string after
9525 // encoding. This will result in reserving more memory than we actually
9526 // need, but that should be fine unless the string has an enormous number of
9527 // & in it. We subtract 1 for the null terminator, then 1 more for the
9528 // existing character that will be replaced.
9529 constexpr uint32_t maxCharExtraSpace =
9530 std::max({ArrayLength("&quot;"), ArrayLength("&amp;"),
9531 ArrayLength("&nbsp;")}) -
9532 2;
9533 static_assert(maxCharExtraSpace < 100, "Possible underflow");
9534 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
9535}
9536
9537static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
9538 StringBuilder& aBuilder) {
9539 if (nsAtom* atom = aValue.GetStoredAtom()) {
9540 nsDependentAtomString atomStr(atom);
9541 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
9542 if (space.isValid() && !space.value()) {
9543 aBuilder.Append(atom);
9544 } else {
9545 aBuilder.AppendWithAttrEncode(nsString(atomStr),
9546 space + atomStr.Length());
9547 }
9548 return;
9549 }
9550 // NOTE(emilio): In most cases this will just be a reference to the stored
9551 // nsStringBuffer.
9552 nsString str;
9553 aValue.ToString(str);
9554 auto space = ExtraSpaceNeededForAttrEncoding(str);
9555 if (!space.isValid() || space.value()) {
9556 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
9557 } else {
9558 aBuilder.Append(std::move(str));
9559 }
9560}
9561
9562static void StartElement(Element* aElement, StringBuilder& aBuilder) {
9563 nsAtom* localName = aElement->NodeInfo()->NameAtom();
9564 const int32_t tagNS = aElement->GetNameSpaceID();
9565
9566 aBuilder.Append(u"<");
9567 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
9568 tagNS == kNameSpaceID_MathML6) {
9569 aBuilder.Append(localName);
9570 } else {
9571 aBuilder.Append(nsString(aElement->NodeName()));
9572 }
9573
9574 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
9575 nsAtom* isAttr = ceData->GetIs(aElement);
9576 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
9577 aBuilder.Append(uR"( is=")");
9578 aBuilder.Append(isAttr);
9579 aBuilder.Append(uR"(")");
9580 }
9581 }
9582
9583 uint32_t i = 0;
9584 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
9585 const nsAttrName* name = info.mName;
9586
9587 int32_t attNs = name->NamespaceID();
9588 nsAtom* attName = name->LocalName();
9589
9590 // Filter out any attribute starting with [-|_]moz
9591 // FIXME(emilio): Do we still need this?
9592 nsDependentAtomString attrNameStr(attName);
9593 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
9594 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
9595 continue;
9596 }
9597
9598 aBuilder.Append(u" ");
9599
9600 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
9601 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
9602 // Nothing else required
9603 } else if (attNs == kNameSpaceID_XML2) {
9604 aBuilder.Append(u"xml:");
9605 } else if (attNs == kNameSpaceID_XMLNS1) {
9606 aBuilder.Append(u"xmlns:");
9607 } else if (attNs == kNameSpaceID_XLink4) {
9608 aBuilder.Append(u"xlink:");
9609 } else if (nsAtom* prefix = name->GetPrefix()) {
9610 aBuilder.Append(prefix);
9611 aBuilder.Append(u":");
9612 }
9613
9614 aBuilder.Append(attName);
9615 aBuilder.Append(uR"(=")");
9616 AppendEncodedAttributeValue(*info.mValue, aBuilder);
9617 aBuilder.Append(uR"(")");
9618 }
9619
9620 aBuilder.Append(u">");
9621
9622 /*
9623 // Per HTML spec we should append one \n if the first child of
9624 // pre/textarea/listing is a textnode and starts with a \n.
9625 // But because browsers haven't traditionally had that behavior,
9626 // we're not changing our behavior either - yet.
9627 if (aContent->IsHTMLElement()) {
9628 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
9629 localName == nsGkAtoms::listing) {
9630 nsIContent* fc = aContent->GetFirstChild();
9631 if (fc &&
9632 (fc->NodeType() == nsINode::TEXT_NODE ||
9633 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
9634 const nsTextFragment* text = fc->GetText();
9635 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
9636 aBuilder.Append("\n");
9637 }
9638 }
9639 }
9640 }*/
9641}
9642
9643static inline bool ShouldEscape(nsIContent* aParent) {
9644 if (!aParent || !aParent->IsHTMLElement()) {
9645 return true;
9646 }
9647
9648 static const nsAtom* nonEscapingElements[] = {
9649 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
9650 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
9651 nsGkAtoms::plaintext, nsGkAtoms::noscript};
9652 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
9653 static bool sInitialized = false;
9654 if (!sInitialized) {
9655 sInitialized = true;
9656 for (auto& nonEscapingElement : nonEscapingElements) {
9657 sFilter.add(nonEscapingElement);
9658 }
9659 }
9660
9661 nsAtom* tag = aParent->NodeInfo()->NameAtom();
9662 if (sFilter.mightContain(tag)) {
9663 for (auto& nonEscapingElement : nonEscapingElements) {
9664 if (tag == nonEscapingElement) {
9665 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
9666 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
9667 return true;
9668 }
9669 return false;
9670 }
9671 }
9672 }
9673 return true;
9674}
9675
9676static inline bool IsVoidTag(Element* aElement) {
9677 if (!aElement->IsHTMLElement()) {
9678 return false;
9679 }
9680 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
9681}
9682
9683static bool StartSerializingShadowDOM(
9684 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
9685 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9686 ShadowRoot* shadow = aNode->GetShadowRoot();
9687 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
9688 !aShadowRoots.Contains(shadow))) {
9689 return false;
9690 }
9691
9692 aBuilder.Append(u"<template shadowrootmode=\"");
9693 if (shadow->IsClosed()) {
9694 aBuilder.Append(u"closed\"");
9695 } else {
9696 aBuilder.Append(u"open\"");
9697 }
9698
9699 if (shadow->DelegatesFocus()) {
9700 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
9701 }
9702 if (shadow->Serializable()) {
9703 aBuilder.Append(u" shadowrootserializable=\"\"");
9704 }
9705 if (shadow->Clonable()) {
9706 aBuilder.Append(u" shadowrootclonable=\"\"");
9707 }
9708
9709 aBuilder.Append(u">");
9710
9711 if (!shadow->HasChildren()) {
9712 aBuilder.Append(u"</template>");
9713 return false;
9714 }
9715 return true;
9716}
9717
9718template <SerializeShadowRoots ShouldSerializeShadowRoots>
9719static void SerializeNodeToMarkupInternal(
9720 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
9721 bool aSerializableShadowRoots,
9722 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9723 nsINode* current =
9724 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
9725 if (!current) {
9726 return;
9727 }
9728
9729 nsIContent* next;
9730 while (true) {
9731 bool isVoid = false;
9732 switch (current->NodeType()) {
9733 case nsINode::ELEMENT_NODE: {
9734 Element* elem = current->AsElement();
9735 StartElement(elem, aBuilder);
9736
9737 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9738 if (StartSerializingShadowDOM(
9739 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
9740 current = current->GetShadowRoot()->GetFirstChild();
9741 continue;
9742 }
9743 }
9744
9745 isVoid = IsVoidTag(elem);
9746 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
9747 current = next;
9748 continue;
9749 }
9750 break;
9751 }
9752
9753 case nsINode::TEXT_NODE:
9754 case nsINode::CDATA_SECTION_NODE: {
9755 const nsTextFragment* text = &current->AsText()->TextFragment();
9756 nsIContent* parent = current->GetParent();
9757 if (ShouldEscape(parent)) {
9758 AppendEncodedCharacters(text, aBuilder);
9759 } else {
9760 aBuilder.Append(text);
9761 }
9762 break;
9763 }
9764
9765 case nsINode::COMMENT_NODE: {
9766 aBuilder.Append(u"<!--");
9767 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9768 aBuilder.Append(u"-->");
9769 break;
9770 }
9771
9772 case nsINode::DOCUMENT_TYPE_NODE: {
9773 aBuilder.Append(u"<!DOCTYPE ");
9774 aBuilder.Append(nsString(current->NodeName()));
9775 aBuilder.Append(u">");
9776 break;
9777 }
9778
9779 case nsINode::PROCESSING_INSTRUCTION_NODE: {
9780 aBuilder.Append(u"<?");
9781 aBuilder.Append(nsString(current->NodeName()));
9782 aBuilder.Append(u" ");
9783 aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
9784 aBuilder.Append(u">");
9785 break;
9786 }
9787 }
9788
9789 while (true) {
9790 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
9791 aBuilder.Append(u"</");
9792 nsIContent* elem = static_cast<nsIContent*>(current);
9793 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
9794 elem->IsMathMLElement()) {
9795 aBuilder.Append(elem->NodeInfo()->NameAtom());
9796 } else {
9797 aBuilder.Append(nsString(current->NodeName()));
9798 }
9799 aBuilder.Append(u">");
9800 }
9801 isVoid = false;
9802
9803 if (current == aRoot) {
9804 return;
9805 }
9806
9807 if ((next = current->GetNextSibling())) {
9808 current = next;
9809 break;
9810 }
9811
9812 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9813 // If the current node is a shadow root, then we must go to its host.
9814 // Since shadow DOMs are serialized declaratively as template elements,
9815 // we serialize the end tag of the template before going back to
9816 // serializing the shadow host.
9817 if (current->IsShadowRoot()) {
9818 current = current->GetContainingShadowHost();
9819 aBuilder.Append(u"</template>");
9820
9821 if (current->HasChildren()) {
9822 current = current->GetFirstChildOfTemplateOrNode();
9823 break;
9824 }
9825 continue;
9826 }
9827 }
9828
9829 current = current->GetParentNode();
9830
9831 // Handle template element. If the parent is a template's content,
9832 // then adjust the parent to be the template element.
9833 if (current != aRoot &&
9834 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
9835 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
9836 nsIContent* fragHost = frag->GetHost();
9837 if (fragHost && fragHost->IsTemplateElement()) {
9838 current = fragHost;
9839 }
9840 }
9841
9842 if (aDescendantsOnly && current == aRoot) {
9843 return;
9844 }
9845 }
9846 }
9847}
9848
9849template <SerializeShadowRoots ShouldSerializeShadowRoots>
9850bool nsContentUtils::SerializeNodeToMarkup(
9851 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9852 bool aSerializableShadowRoots,
9853 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
9854 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
9855 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"
, 9855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { *((volatile int*)__null) = 9855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9856
9857 StringBuilder builder;
9858 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
9859 if (aDescendantsOnly &&
9860 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
9861 aShadowRoots)) {
9862 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
9863 aRoot->GetShadowRoot()->GetFirstChild(), false, builder,
9864 aSerializableShadowRoots, aShadowRoots);
9865 // The template tag is opened in StartSerializingShadowDOM, so we need
9866 // to close it here before serializing any children of aRoot.
9867 builder.Append(u"</template>");
9868 }
9869 }
9870
9871 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
9872 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
9873 return builder.ToString(aOut);
9874}
9875
9876template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
9877 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9878 bool aSerializableShadowRoots,
9879 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9880template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
9881 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
9882 bool aSerializableShadowRoots,
9883 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
9884
9885bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
9886 // aUri must start with about: or this isn't the right function to be using.
9887 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"
, 9887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { *((volatile int*)__null) = 9887; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9888
9889 // Make sure the global is a window
9890 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"
, 9890); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)"
")"); do { *((volatile int*)__null) = 9890; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9891 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
9892 if (!win) {
9893 return false;
9894 }
9895
9896 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
9897 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"
, 9897); return false; } } while (false)
;
9898
9899 // First check the scheme to avoid getting long specs in the common case.
9900 if (!principal->SchemeIs("about")) {
9901 return false;
9902 }
9903
9904 nsAutoCString spec;
9905 principal->GetAsciiSpec(spec);
9906
9907 return spec.EqualsASCII(aUri);
9908}
9909
9910/* static */
9911void nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell,
9912 bool aVisible) {
9913 if (!aDocShell) {
9914 return;
9915 }
9916 auto pref = aVisible ? ScrollbarPreference::Auto : ScrollbarPreference::Never;
9917 nsDocShell::Cast(aDocShell)->SetScrollbarPreference(pref);
9918}
9919
9920/* static */
9921nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
9922 if (!aTarget) {
9923 return nullptr;
9924 }
9925
9926 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
9927 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
9928 bool ignore;
9929 innerWindow =
9930 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
9931 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
9932 // Nothing else to do
9933 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
9934 do_QueryInterface(aTarget)) {
9935 innerWindow = helper->GetOwnerWindow();
9936 }
9937
9938 if (innerWindow) {
9939 return innerWindow->GetDocShell();
9940 }
9941
9942 return nullptr;
9943}
9944
9945/*
9946 * Note: this function only relates to figuring out HTTPS state, which is an
9947 * input to the Secure Context algorithm. We are not actually implementing any
9948 * part of the Secure Context algorithm itself here.
9949 *
9950 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
9951 * nsIChannel as described in the Fetch and HTML specs, but making channels
9952 * know about whether they should inherit HTTPS state, propagating information
9953 * about who the channel's "client" is, exposing GetHttpsState API on channels
9954 * and modifying the various cache implementations to store and retrieve HTTPS
9955 * state involves a huge amount of code (see bug 1220687). We avoid that for
9956 * now using this function.
9957 *
9958 * This function takes advantage of the observation that we can return true if
9959 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
9960 * the document's origin (e.g. the origin has a scheme of 'https' or host
9961 * 'localhost' etc.). Since we generally propagate a creator document's origin
9962 * onto data:, blob:, etc. documents, this works for them too.
9963 *
9964 * The scenario where this observation breaks down is sandboxing without the
9965 * 'allow-same-origin' flag, since in this case a document is given a unique
9966 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
9967 * by using the origin that the document would have had had it not been
9968 * sandboxed.
9969 *
9970 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
9971 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
9972 * sandboxing is limited to the immediate sandbox. In the case that aDocument
9973 * should inherit its origin (e.g. data: URI) but its parent has ended up
9974 * with a unique origin due to sandboxing further up the parent chain we may
9975 * end up returning false when we would ideally return true (since we will
9976 * examine the parent's origin for 'https' and not finding it.) This means
9977 * that we may restrict the privileges of some pages unnecessarily in this
9978 * edge case.
9979 */
9980/* static */
9981bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
9982 if (!aDocument) {
9983 return false;
9984 }
9985
9986 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
9987
9988 if (principal->IsSystemPrincipal()) {
9989 return true;
9990 }
9991
9992 // If aDocument is sandboxed, try and get the principal that it would have
9993 // been given had it not been sandboxed:
9994 if (principal->GetIsNullPrincipal() &&
9995 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
9996 nsIChannel* channel = aDocument->GetChannel();
9997 if (channel) {
9998 nsCOMPtr<nsIScriptSecurityManager> ssm =
9999 nsContentUtils::GetSecurityManager();
10000 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
10001 channel, getter_AddRefs(principal));
10002 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10003 return false;
10004 }
10005 if (principal->IsSystemPrincipal()) {
10006 // If a document with the system principal is sandboxing a subdocument
10007 // that would normally inherit the embedding element's principal (e.g.
10008 // a srcdoc document) then the embedding document does not trust the
10009 // content that is written to the embedded document. Unlike when the
10010 // embedding document is https, in this case we have no indication as
10011 // to whether the embedded document's contents are delivered securely
10012 // or not, and the sandboxing would possibly indicate that they were
10013 // not. To play it safe we return false here. (See bug 1162772
10014 // comment 73-80.)
10015 return false;
10016 }
10017 }
10018 }
10019
10020 if (principal->GetIsNullPrincipal()) {
10021 return false;
10022 }
10023
10024 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"
, 10024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()"
")"); do { *((volatile int*)__null) = 10024; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10025
10026 return principal->GetIsOriginPotentiallyTrustworthy();
10027}
10028
10029/* static */
10030bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
10031 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"
, 10031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { *((volatile int*)__null) = 10031; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10032
10033 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
10034 nsCOMPtr<nsIPrincipal> principal;
10035 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
10036 aChannel, getter_AddRefs(principal));
10037 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10038 return false;
10039 }
10040
10041 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10042
10043 if (principal->IsSystemPrincipal()) {
10044 // If the load would've been sandboxed, treat this load as an untrusted
10045 // load, as system code considers sandboxed resources insecure.
10046 return !loadInfo->GetLoadingSandboxed();
10047 }
10048
10049 if (principal->GetIsNullPrincipal()) {
10050 return false;
10051 }
10052
10053 if (const RefPtr<WindowContext> windowContext =
10054 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
10055 if (!windowContext->GetIsSecureContext()) {
10056 return false;
10057 }
10058 }
10059
10060 return principal->GetIsOriginPotentiallyTrustworthy();
10061}
10062
10063/* static */
10064void nsContentUtils::TryToUpgradeElement(Element* aElement) {
10065 NodeInfo* nodeInfo = aElement->NodeInfo();
10066 RefPtr<nsAtom> typeAtom =
10067 aElement->GetCustomElementData()->GetCustomElementType();
10068
10069 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"
, 10069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 10069; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10070 CustomElementDefinition* definition =
10071 nsContentUtils::LookupCustomElementDefinition(
10072 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
10073 nodeInfo->NamespaceID(), typeAtom);
10074 if (definition) {
10075 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
10076 } else {
10077 // Add an unresolved custom element that is a candidate for upgrade when a
10078 // custom element is connected to the document.
10079 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
10080 }
10081}
10082
10083MOZ_CAN_RUN_SCRIPT
10084static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
10085 Document* aDoc, NodeInfo* aNodeInfo,
10086 CustomElementConstructor* aConstructor,
10087 ErrorResult& aRv, FromParser aFromParser) {
10088 JS::Rooted<JS::Value> constructResult(aCx);
10089 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
10090 CallbackFunction::eRethrowExceptions);
10091 if (aRv.Failed()) {
10092 return;
10093 }
10094
10095 RefPtr<Element> element;
10096 // constructResult is an ObjectValue because construction with a callback
10097 // always forms the return value from a JSObject.
10098 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
10099 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10100 if (!element || !element->IsHTMLElement()) {
10101 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10102 "HTMLElement");
10103 return;
10104 }
10105 } else {
10106 if (!element || !element->IsXULElement()) {
10107 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
10108 "XULElement");
10109 return;
10110 }
10111 }
10112
10113 nsAtom* localName = aNodeInfo->NameAtom();
10114
10115 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
10116 element->HasChildren() || element->GetAttrCount() ||
10117 element->NodeInfo()->NameAtom() != localName) {
10118 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
10119 return;
10120 }
10121
10122 if (element->IsHTMLElement()) {
10123 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
10124 !(aFromParser & FROM_PARSER_NETWORK));
10125 }
10126
10127 element.forget(aElement);
10128}
10129
10130/* static */
10131nsresult nsContentUtils::NewXULOrHTMLElement(
10132 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
10133 FromParser aFromParser, nsAtom* aIsAtom,
10134 mozilla::dom::CustomElementDefinition* aDefinition) {
10135 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
10136 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"
, 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
10137 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"
, 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10138 "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"
, 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { *(
(volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10139
10140 nsAtom* name = nodeInfo->NameAtom();
10141 int32_t tag = eHTMLTag_unknown;
10142 bool isCustomElementName = false;
10143 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
3
Taking false branch
10144 tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
10145 isCustomElementName =
10146 (tag == eHTMLTag_userdefined &&
10147 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
10148 } else { // kNameSpaceID_XUL
10149 if (aIsAtom) {
4
Assuming 'aIsAtom' is null
5
Taking false branch
10150 // Make sure the customized built-in element to be constructed confirms
10151 // to our naming requirement, i.e. [is] must be a dashed name and
10152 // the tag name must not.
10153 // if so, set isCustomElementName to false to kick off all the logics
10154 // that pick up aIsAtom.
10155 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
10156 !nsContentUtils::IsNameWithDash(name)) {
10157 isCustomElementName = false;
10158 } else {
10159 isCustomElementName =
10160 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10161 }
10162 } else {
10163 isCustomElementName =
10164 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
10165 }
10166 }
10167
10168 nsAtom* tagAtom = nodeInfo->NameAtom();
10169 nsAtom* typeAtom = nullptr;
10170 bool isCustomElement = isCustomElementName
5.1
'isCustomElementName' is true
|| aIsAtom;
10171 if (isCustomElement
5.2
'isCustomElement' is true
) {
10172 typeAtom = isCustomElementName
6.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
6
Taking true branch
7
'?' condition is true
10173 }
10174
10175 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"
, 10175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { *((volatile int*)__null) = 10175; __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
10176
10177 // https://dom.spec.whatwg.org/#concept-create-element
10178 // We only handle the "synchronous custom elements flag is set" now.
10179 // For the unset case (e.g. cloning a node), see bug 1319342 for that.
10180 // Step 4.
10181 RefPtr<CustomElementDefinition> definition = aDefinition;
10182 if (isCustomElement
12.1
'isCustomElement' is true
&& !definition) {
13
Taking false branch
10183 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"
, 10183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { *((volatile int*)__null) = 10183; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10184 definition = nsContentUtils::LookupCustomElementDefinition(
10185 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
10186 typeAtom);
10187 }
10188
10189 // It might be a problem that parser synchronously calls constructor, so filed
10190 // bug 1378079 to figure out what we should do for parser case.
10191 if (definition) {
14
Taking true branch
10192 /*
10193 * Synchronous custom elements flag is determined by 3 places in spec,
10194 * 1) create an element for a token, the flag is determined by
10195 * "will execute script" which is not originally created
10196 * for the HTML fragment parsing algorithm.
10197 * 2) createElement and createElementNS, the flag is the same as
10198 * NOT_FROM_PARSER.
10199 * 3) clone a node, our implementation will not go into this function.
10200 * For the unset case which is non-synchronous only applied for
10201 * inner/outerHTML.
10202 */
10203 bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT;
15
Assuming 'aFromParser' is equal to FROM_PARSER_FRAGMENT
10204 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
10205 // use entry global in those places that are called from JS APIs and use the
10206 // node document's global object if it is called from parser.
10207 nsIGlobalObject* global;
10208 if (aFromParser
15.1
'aFromParser' is not equal to NOT_FROM_PARSER
== dom::NOT_FROM_PARSER) {
16
Taking false branch
10209 global = GetEntryGlobal();
10210
10211 // Documents created from the PrototypeDocumentSink always use
10212 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
10213 // document in that case.
10214 if (!global) {
10215 Document* doc = nodeInfo->GetDocument();
10216 if (doc && doc->LoadedFromPrototype()) {
10217 global = doc->GetScopeObject();
10218 }
10219 }
10220 } else {
10221 global = nodeInfo->GetDocument()->GetScopeObject();
10222 }
10223 if (!global) {
17
Assuming 'global' is non-null
18
Taking false branch
10224 // In browser chrome code, one may have access to a document which doesn't
10225 // have scope object anymore.
10226 return NS_ERROR_FAILURE;
10227 }
10228
10229 AutoAllowLegacyScriptExecution exemption;
10230 AutoEntryScript aes(global, "create custom elements");
10231 JSContext* cx = aes.cx();
10232 ErrorResult rv;
10233
10234 // Step 5.
10235 if (definition->IsCustomBuiltIn()) {
19
Taking false branch
10236 // SetupCustomElement() should be called with an element that don't have
10237 // CustomElementData setup, if not we will hit the assertion in
10238 // SetCustomElementData().
10239 // Built-in element
10240 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10241 *aResult =
10242 CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10243 } else {
10244 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10245 }
10246 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
10247 if (synchronousCustomElements) {
10248 CustomElementRegistry::Upgrade(*aResult, definition, rv);
10249 if (rv.MaybeSetPendingException(cx)) {
10250 aes.ReportException();
10251 }
10252 } else {
10253 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10254 }
10255
10256 return NS_OK;
10257 }
10258
10259 // Step 6.1.
10260 if (synchronousCustomElements
19.1
'synchronousCustomElements' is false
) {
20
Taking false branch
10261 definition->mPrefixStack.AppendElement(nodeInfo->GetPrefixAtom());
10262 RefPtr<Document> doc = nodeInfo->GetDocument();
10263 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
10264 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
10265 aFromParser);
10266 if (rv.MaybeSetPendingException(cx)) {
10267 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10268 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
10269 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
10270 } else {
10271 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10272 }
10273 (*aResult)->SetDefined(false);
10274 }
10275 definition->mPrefixStack.RemoveLastElement();
10276 return NS_OK;
10277 }
10278
10279 // Step 6.2.
10280 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
21
Taking false branch
10281 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10282 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10283 } else {
10284 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
22
Assigning value
10285 }
10286 (*aResult)->SetCustomElementData(
23
Called C++ object pointer is null
10287 MakeUnique<CustomElementData>(definition->mType));
10288 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
10289 return NS_OK;
10290 }
10291
10292 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
10293 // Per the Custom Element specification, unknown tags that are valid custom
10294 // element names should be HTMLElement instead of HTMLUnknownElement.
10295 if (isCustomElementName) {
10296 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
10297 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
10298 } else {
10299 *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
10300 }
10301 } else {
10302 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
10303 }
10304
10305 if (!*aResult) {
10306 return NS_ERROR_OUT_OF_MEMORY;
10307 }
10308
10309 if (isCustomElement) {
10310 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
10311 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
10312 }
10313
10314 return NS_OK;
10315}
10316
10317CustomElementRegistry* nsContentUtils::GetCustomElementRegistry(
10318 Document* aDoc) {
10319 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"
, 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")")
; do { *((volatile int*)__null) = 10319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10320
10321 if (!aDoc->GetDocShell()) {
10322 return nullptr;
10323 }
10324
10325 nsPIDOMWindowInner* window = aDoc->GetInnerWindow();
10326 if (!window) {
10327 return nullptr;
10328 }
10329
10330 return window->CustomElements();
10331}
10332
10333/* static */
10334CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
10335 Document* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
10336 nsAtom* aTypeAtom) {
10337 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
10338 return nullptr;
10339 }
10340
10341 RefPtr<CustomElementRegistry> registry = GetCustomElementRegistry(aDoc);
10342 if (!registry) {
10343 return nullptr;
10344 }
10345
10346 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
10347 aTypeAtom);
10348}
10349
10350/* static */
10351void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
10352 nsAtom* aTypeName) {
10353 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"
, 10353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10354
10355 Document* doc = aElement->OwnerDoc();
10356 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10357 if (registry) {
10358 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
10359 }
10360}
10361
10362/* static */
10363void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
10364 nsAtom* aTypeName) {
10365 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"
, 10365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10365; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10366
10367 Document* doc = aElement->OwnerDoc();
10368 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10369 if (registry) {
10370 registry->RegisterUnresolvedElement(aElement, aTypeName);
10371 }
10372}
10373
10374/* static */
10375void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
10376 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"
, 10376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10377
10378 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
10379 Document* doc = aElement->OwnerDoc();
10380 CustomElementRegistry* registry = GetCustomElementRegistry(doc);
10381 if (registry) {
10382 registry->UnregisterUnresolvedElement(aElement, typeAtom);
10383 }
10384}
10385
10386/* static */
10387void nsContentUtils::EnqueueUpgradeReaction(
10388 Element* aElement, CustomElementDefinition* aDefinition) {
10389 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"
, 10389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { *((volatile int*)__null) = 10389; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10390
10391 Document* doc = aElement->OwnerDoc();
10392
10393 // No DocGroup means no custom element reactions stack.
10394 if (!doc->GetDocGroup()) {
10395 return;
10396 }
10397
10398 CustomElementReactionsStack* stack =
10399 doc->GetDocGroup()->CustomElementReactionsStack();
10400 stack->EnqueueUpgradeReaction(aElement, aDefinition);
10401}
10402
10403/* static */
10404void nsContentUtils::EnqueueLifecycleCallback(
10405 ElementCallbackType aType, Element* aCustomElement,
10406 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
10407 // No DocGroup means no custom element reactions stack.
10408 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
10409 return;
10410 }
10411
10412 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
10413 aDefinition);
10414}
10415
10416/* static */
10417CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
10418 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
10419 if (aState.IsNull()) {
10420 return void_t{};
10421 }
10422 const auto& state = aState.Value();
10423 if (state.IsFile()) {
10424 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
10425 return {std::move(impl)};
10426 }
10427 if (state.IsUSVString()) {
10428 return state.GetAsUSVString();
10429 }
10430 return state.GetAsFormData()->ConvertToCustomElementFormValue();
10431}
10432
10433/* static */
10434Nullable<OwningFileOrUSVStringOrFormData>
10435nsContentUtils::ExtractFormAssociatedCustomElementValue(
10436 nsIGlobalObject* aGlobal,
10437 const mozilla::dom::CustomElementFormValue& aCEValue) {
10438 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"
, 10438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { *((volatile int*)__null) = 10438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10439
10440 OwningFileOrUSVStringOrFormData value;
10441 switch (aCEValue.type()) {
10442 case CustomElementFormValue::TBlobImpl: {
10443 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
10444 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 10444)
) {
10445 return {};
10446 }
10447 value.SetAsFile() = file;
10448 } break;
10449
10450 case CustomElementFormValue::TnsString:
10451 value.SetAsUSVString() = aCEValue.get_nsString();
10452 break;
10453
10454 case CustomElementFormValue::TArrayOfFormDataTuple: {
10455 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
10456 auto formData = MakeRefPtr<FormData>();
10457
10458 for (auto i = 0ul; i < array.Length(); ++i) {
10459 const auto& item = array.ElementAt(i);
10460 switch (item.value().type()) {
10461 case FormDataValue::TnsString:
10462 formData->AddNameValuePair(item.name(),
10463 item.value().get_nsString());
10464 break;
10465
10466 case FormDataValue::TBlobImpl: {
10467 auto blobImpl = item.value().get_BlobImpl();
10468 auto* blob = Blob::Create(aGlobal, blobImpl);
10469 formData->AddNameBlobPair(item.name(), blob);
10470 } break;
10471
10472 default:
10473 continue;
10474 }
10475 }
10476
10477 value.SetAsFormData() = formData;
10478 } break;
10479 case CustomElementFormValue::Tvoid_t:
10480 return {};
10481 default:
10482 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"
, 10482)
;
10483 return {};
10484 }
10485 return value;
10486}
10487
10488/* static */
10489void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
10490 Document* aDocument, nsTArray<nsIContent*>& aElements) {
10491 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"
, 10491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { *((volatile int*)__null) = 10491; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10492#ifdef DEBUG1
10493 size_t oldLength = aElements.Length();
10494#endif
10495
10496 if (PresShell* presShell = aDocument->GetPresShell()) {
10497 if (ScrollContainerFrame* rootScrollContainerFrame =
10498 presShell->GetRootScrollContainerFrame()) {
10499 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
10500 }
10501 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
10502 canvasFrame->AppendAnonymousContentTo(aElements, 0);
10503 }
10504 }
10505
10506#ifdef DEBUG1
10507 for (size_t i = oldLength; i < aElements.Length(); i++) {
10508 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"
, 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10509 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"
, 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10510 "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"
, 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { *((volatile int*)__null) = 10510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10511 }
10512#endif
10513}
10514
10515static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
10516 nsTArray<nsIContent*>& aKids,
10517 uint32_t aFlags) {
10518 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
10519 ac->AppendAnonymousContentTo(aKids, aFlags);
10520 }
10521}
10522
10523/* static */
10524void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
10525 nsTArray<nsIContent*>& aKids,
10526 uint32_t aFlags) {
10527 if (aContent->MayHaveAnonymousChildren()) {
10528 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
10529 // NAC created by the element's primary frame.
10530 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
10531
10532 // NAC created by any other non-primary frames for the element.
10533 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
10534 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
10535 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
10536 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"
, 10536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { *((volatile int*)__null) = 10536; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10537 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
10538 aFlags);
10539 }
10540 }
10541
10542 // Get manually created NAC (editor resize handles, etc.).
10543 if (auto nac = static_cast<ManualNACArray*>(
10544 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
10545 aKids.AppendElements(*nac);
10546 }
10547 }
10548
10549 // The root scroll frame is not the primary frame of the root element.
10550 // Detect and handle this case.
10551 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
10552 aContent == aContent->OwnerDoc()->GetRootElement()) {
10553 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
10554 }
10555}
10556
10557bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
10558 nsIPrincipal* aDefaultTriggeringPrincipal,
10559 CORSMode aCORSMode) {
10560 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10561 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
10562 getter_AddRefs(triggeringPrincipal));
10563 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"
, 10563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "triggeringPrincipal"
")"); do { *((volatile int*)__null) = 10563; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10564
10565 Document* doc = aLoadingNode->OwnerDoc();
10566 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
10567}
10568
10569bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
10570 nsIPrincipal* aTriggeringPrincipal,
10571 CORSMode aCORSMode, Document* aDoc) {
10572 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
10573 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
10574 aDoc);
10575}
10576
10577/* static */
10578bool nsContentUtils::QueryTriggeringPrincipal(
10579 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
10580 nsIPrincipal** aTriggeringPrincipal) {
10581 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"
, 10581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { *((volatile int*)__null) = 10581; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10582 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"
, 10582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
")"); do { *((volatile int*)__null) = 10582; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10583
10584 bool result = false;
10585 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
10586 if (!loadingPrincipal) {
10587 loadingPrincipal = aLoadingNode->NodePrincipal();
10588 }
10589
10590 // If aLoadingNode is content, bail out early.
10591 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
10592 loadingPrincipal.forget(aTriggeringPrincipal);
10593 return result;
10594 }
10595
10596 nsAutoString loadingStr;
10597 if (aLoadingNode->IsElement()) {
10598 aLoadingNode->AsElement()->GetAttr(
10599 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
10600 }
10601
10602 // Fall back if 'triggeringprincipal' isn't specified,
10603 if (loadingStr.IsEmpty()) {
10604 loadingPrincipal.forget(aTriggeringPrincipal);
10605 return result;
10606 }
10607
10608 nsCString binary;
10609 nsCOMPtr<nsIPrincipal> serializedPrin =
10610 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
10611 if (serializedPrin) {
10612 result = true;
10613 serializedPrin.forget(aTriggeringPrincipal);
10614 }
10615
10616 if (!result) {
10617 // Fallback if the deserialization is failed.
10618 loadingPrincipal.forget(aTriggeringPrincipal);
10619 }
10620
10621 return result;
10622}
10623
10624/* static */
10625void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
10626 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
10627 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
10628 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"
, 10628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequestContextID"
")"); do { *((volatile int*)__null) = 10628; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10629
10630 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
10631 if (result) {
10632 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
10633 // indicating it's a favicon loading.
10634 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
10635
10636 nsAutoString requestContextID;
10637 if (aLoadingNode->IsElement()) {
10638 aLoadingNode->AsElement()->GetAttr(
10639 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
10640 }
10641 nsresult rv;
10642 int64_t val = requestContextID.ToInteger64(&rv);
10643 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
10644 } else {
10645 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
10646 }
10647}
10648
10649/* static */
10650nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
10651 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
10652 JS::MutableHandle<JS::Value> aValue) {
10653 if (aTransfer.IsEmpty()) {
10654 return NS_OK;
10655 }
10656
10657 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
10658 if (!array) {
10659 return NS_ERROR_OUT_OF_MEMORY;
10660 }
10661
10662 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
10663 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
10664 if (!object) {
10665 continue;
10666 }
10667
10668 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"
, 10669)
10669 !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"
, 10669)
) {
10670 return NS_ERROR_OUT_OF_MEMORY;
10671 }
10672 }
10673
10674 aValue.setObject(*array);
10675 return NS_OK;
10676}
10677
10678/* static */
10679void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
10680 JS::Handle<JS::Value> aValue,
10681 const StructuredSerializeOptions& aOptions,
10682 JS::MutableHandle<JS::Value> aRetval,
10683 ErrorResult& aError) {
10684 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
10685 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
10686 aCx, aOptions.mTransfer, &transferArray);
10687 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"
, 10687)
) {
10688 return;
10689 }
10690
10691 JS::CloneDataPolicy clonePolicy;
10692 // We are definitely staying in the same agent cluster.
10693 clonePolicy.allowIntraClusterClonableSharedObjects();
10694 if (aGlobal->IsSharedMemoryAllowed()) {
10695 clonePolicy.allowSharedMemoryObjects();
10696 }
10697
10698 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
10699 StructuredCloneHolder::TransferringSupported,
10700 JS::StructuredCloneScope::SameProcess);
10701 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
10702 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"
, 10702)
) {
10703 return;
10704 }
10705
10706 holder.Read(aGlobal, aCx, aRetval, clonePolicy, aError);
10707 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"
, 10707)
) {
10708 return;
10709 }
10710
10711 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
10712 Unused << ports;
10713}
10714
10715/* static */
10716bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
10717 nsCOMPtr<nsIPrincipal> principal;
10718 RefPtr<Element> targetElement =
10719 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
10720 nsCOMPtr<nsIBrowser> targetBrowser;
10721 if (targetElement) {
10722 targetBrowser = targetElement->AsBrowser();
10723 }
10724 bool isRemoteBrowser = false;
10725 if (targetBrowser) {
10726 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
10727 }
10728
10729 if (isRemoteBrowser) {
10730 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
10731 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
10732 : false;
10733 }
10734
10735 if (targetElement) {
10736 Document* doc = targetElement->GetUncomposedDoc();
10737 if (doc) {
10738 RefPtr<WindowContext> wc = doc->GetWindowContext();
10739 if (wc) {
10740 return wc->TopWindowContext()->GetShortcutsPermission() ==
10741 nsIPermissionManager::DENY_ACTION;
10742 }
10743 }
10744 }
10745
10746 return false;
10747}
10748
10749/**
10750 * Checks whether the given type is a supported document type for
10751 * loading within the nsObjectLoadingContent specified by aContent.
10752 *
10753 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
10754 * NOTE Does not take content policy or capabilities into account
10755 */
10756static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
10757 nsCOMPtr<nsIWebNavigationInfo> info(
10758 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
10759 if (!info) {
10760 return false;
10761 }
10762
10763 uint32_t supported;
10764 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
10765
10766 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10767 return false;
10768 }
10769
10770 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
10771 // Don't want to support plugins as documents
10772 return supported != nsIWebNavigationInfo::FALLBACK;
10773 }
10774
10775 // Try a stream converter
10776 // NOTE: We treat any type we can convert from as a supported type. If a
10777 // type is not actually supported, the URI loader will detect that and
10778 // return an error, and we'll fallback.
10779 nsCOMPtr<nsIStreamConverterService> convServ =
10780 do_GetService("@mozilla.org/streamConverters;1");
10781 bool canConvert = false;
10782 if (convServ) {
10783 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
10784 }
10785 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
10786}
10787
10788/* static */
10789uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
10790 const nsCString& aMIMEType) {
10791 if (aMIMEType.IsEmpty()) {
10792 return nsIObjectLoadingContent::TYPE_FALLBACK;
10793 }
10794
10795 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
10796 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10797 }
10798
10799 // Faking support of the PDF content as a document for EMBED tags
10800 // when internal PDF viewer is enabled.
10801 if (aMIMEType.LowerCaseEqualsLiteral("application/pdf") && IsPDFJSEnabled()) {
10802 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10803 }
10804
10805 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
10806 return nsIObjectLoadingContent::TYPE_DOCUMENT;
10807 }
10808
10809 return nsIObjectLoadingContent::TYPE_FALLBACK;
10810}
10811
10812/* static */
10813bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
10814 return !aString.IsEmpty() && aString[0] == '#';
10815}
10816
10817// We use only 53 bits for the ID so that it can be converted to and from a JS
10818// value without loss of precision. The upper bits of the ID hold the process
10819// ID. The lower bits identify the object itself.
10820static constexpr uint64_t kIdTotalBits = 53;
10821static constexpr uint64_t kIdProcessBits = 22;
10822static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
10823
10824/* static */
10825uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
10826 uint64_t processId = 0;
10827 if (XRE_IsContentProcess()) {
10828 ContentChild* cc = ContentChild::GetSingleton();
10829 processId = cc->GetID();
10830 }
10831
10832 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"
, 10832); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { *((volatile int*)__null) = 10832; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10833 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
10834
10835 uint64_t id = aId;
10836 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"
, 10836); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { *((volatile int*)__null) = 10836; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10837 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
10838
10839 return (processBits << kIdBits) | bits;
10840}
10841
10842/* static */
10843std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId(
10844 uint64_t aId) {
10845 return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)};
10846}
10847
10848// Next process-local Tab ID.
10849static uint64_t gNextTabId = 0;
10850
10851/* static */
10852uint64_t nsContentUtils::GenerateTabId() {
10853 return GenerateProcessSpecificId(++gNextTabId);
10854}
10855
10856// Next process-local Browser ID.
10857static uint64_t gNextBrowserId = 0;
10858
10859/* static */
10860uint64_t nsContentUtils::GenerateBrowserId() {
10861 return GenerateProcessSpecificId(++gNextBrowserId);
10862}
10863
10864// Next process-local Browsing Context ID.
10865static uint64_t gNextBrowsingContextId = 0;
10866
10867/* static */
10868uint64_t nsContentUtils::GenerateBrowsingContextId() {
10869 return GenerateProcessSpecificId(++gNextBrowsingContextId);
10870}
10871
10872// Next process-local Window ID.
10873static uint64_t gNextWindowId = 0;
10874
10875/* static */
10876uint64_t nsContentUtils::GenerateWindowId() {
10877 return GenerateProcessSpecificId(++gNextWindowId);
10878}
10879
10880// Next process-local load.
10881static Atomic<uint64_t> gNextLoadIdentifier(0);
10882
10883/* static */
10884uint64_t nsContentUtils::GenerateLoadIdentifier() {
10885 return GenerateProcessSpecificId(++gNextLoadIdentifier);
10886}
10887
10888/* static */
10889bool nsContentUtils::GetUserIsInteracting() {
10890 return UserInteractionObserver::sUserActive;
10891}
10892
10893/* static */
10894bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
10895 nsACString& aResult) {
10896 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
10897 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10898 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
10899 }
10900 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
10901}
10902
10903/* static */
10904bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
10905 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10906 mozilla::dom::PBrowser::PBrowserStart) {
10907 switch (aMsg.type()) {
10908 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
10909 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10910 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
10911 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10912 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10913 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10914 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
10915 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10916 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
10917 return true;
10918 }
10919 }
10920 return false;
10921}
10922
10923/* static */
10924bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) {
10925 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
10926 mozilla::dom::PBrowser::PBrowserStart) {
10927 switch (aMsg.type()) {
10928 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
10929 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
10930 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
10931 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
10932 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
10933 return true;
10934 }
10935 }
10936 return false;
10937}
10938
10939static const char* kUserInteractionInactive = "user-interaction-inactive";
10940static const char* kUserInteractionActive = "user-interaction-active";
10941
10942void nsContentUtils::UserInteractionObserver::Init() {
10943 // Listen for the observer messages from EventStateManager which are telling
10944 // us whether or not the user is interacting.
10945 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10946 obs->AddObserver(this, kUserInteractionInactive, false);
10947 obs->AddObserver(this, kUserInteractionActive, false);
10948
10949 // We can't register ourselves as an annotator yet, as the
10950 // BackgroundHangMonitor hasn't started yet. It will have started by the
10951 // time we have the chance to spin the event loop.
10952 RefPtr<UserInteractionObserver> self = this;
10953 NS_DispatchToMainThread(NS_NewRunnableFunction(
10954 "nsContentUtils::UserInteractionObserver::Init",
10955 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
10956}
10957
10958void nsContentUtils::UserInteractionObserver::Shutdown() {
10959 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10960 if (obs) {
10961 obs->RemoveObserver(this, kUserInteractionInactive);
10962 obs->RemoveObserver(this, kUserInteractionActive);
10963 }
10964
10965 BackgroundHangMonitor::UnregisterAnnotator(*this);
10966}
10967
10968/**
10969 * NB: This function is always called by the BackgroundHangMonitor thread.
10970 * Plan accordingly
10971 */
10972void nsContentUtils::UserInteractionObserver::AnnotateHang(
10973 BackgroundHangAnnotations& aAnnotations) {
10974 // NOTE: Only annotate the hang report if the user is known to be interacting.
10975 if (sUserActive) {
10976 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
10977 }
10978}
10979
10980NS_IMETHODIMPnsresult
10981nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
10982 const char* aTopic,
10983 const char16_t* aData) {
10984 if (!strcmp(aTopic, kUserInteractionInactive)) {
10985 if (sUserActive && XRE_IsParentProcess()) {
10986 glean::RecordPowerMetrics();
10987 }
10988 sUserActive = false;
10989 } else if (!strcmp(aTopic, kUserInteractionActive)) {
10990 if (!sUserActive && XRE_IsParentProcess()) {
10991 glean::RecordPowerMetrics();
10992
10993 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
10994 do_GetService("@mozilla.org/widget/useridleservice;1");
10995 if (idleService) {
10996 idleService->ResetIdleTimeOut(0);
10997 }
10998 }
10999
11000 sUserActive = true;
11001 } else {
11002 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"
, 11002)
;
11003 }
11004 return NS_OK;
11005}
11006
11007Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
11008NS_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"
, 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
11008; __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"
, 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 11008; __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"
, 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 11008
; __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"
, 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 11008; __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"
, 11008); 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; }
11009
11010/* static */
11011bool nsContentUtils::IsSpecialName(const nsAString& aName) {
11012 return aName.LowerCaseEqualsLiteral("_blank") ||
11013 aName.LowerCaseEqualsLiteral("_top") ||
11014 aName.LowerCaseEqualsLiteral("_parent") ||
11015 aName.LowerCaseEqualsLiteral("_self");
11016}
11017
11018/* static */
11019bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
11020 return !aName.IsEmpty() && !IsSpecialName(aName);
11021}
11022
11023// Unfortunately, we can't unwrap an IDL object using only a concrete type.
11024// We need to calculate type data based on the IDL typename. Which means
11025// wrapping our templated function in a macro.
11026#define EXTRACT_EXN_VALUES(T, ...) \
11027 ExtractExceptionValues<mozilla::dom::prototypes::id::T, \
11028 T##_Binding::NativeType, T>(__VA_ARGS__) \
11029 .isOk()
11030
11031template <prototypes::ID PrototypeID, class NativeType, typename T>
11032static Result<Ok, nsresult> ExtractExceptionValues(
11033 JSContext* aCx, JS::Handle<JSObject*> aObj, nsAString& aSourceSpecOut,
11034 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11035 AssertStaticUnwrapOK<PrototypeID>();
11036 RefPtr<T> exn;
11037 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)
;
11038
11039 exn->GetFilename(aCx, aSourceSpecOut);
11040 if (!aSourceSpecOut.IsEmpty()) {
11041 *aLineOut = exn->LineNumber(aCx);
11042 *aColumnOut = exn->ColumnNumber();
11043 }
11044
11045 exn->GetName(aMessageOut);
11046 aMessageOut.AppendLiteral(": ");
11047
11048 nsAutoString message;
11049 exn->GetMessageMoz(message);
11050 aMessageOut.Append(message);
11051 return Ok();
11052}
11053
11054/* static */
11055void nsContentUtils::ExtractErrorValues(
11056 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
11057 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11058 nsAutoString sourceSpec;
11059 ExtractErrorValues(aCx, aValue, sourceSpec, aLineOut, aColumnOut,
11060 aMessageOut);
11061 CopyUTF16toUTF8(sourceSpec, aSourceSpecOut);
11062}
11063
11064/* static */
11065void nsContentUtils::ExtractErrorValues(
11066 JSContext* aCx, JS::Handle<JS::Value> aValue, nsAString& aSourceSpecOut,
11067 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
11068 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"
, 11068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { *((volatile int*)__null) = 11068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11069 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"
, 11069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { *((volatile int*)__null) = 11069; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11070
11071 if (aValue.isObject()) {
11072 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
11073
11074 // Try to process as an Error object. Use the file/line/column values
11075 // from the Error as they will be more specific to the root cause of
11076 // the problem.
11077 JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr;
11078 if (err) {
11079 // Use xpc to extract the error message only. We don't actually send
11080 // this report anywhere.
11081 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
11082 report->Init(err,
11083 nullptr, // toString result
11084 false, // chrome
11085 0); // window ID
11086
11087 if (!report->mFileName.IsEmpty()) {
11088 aSourceSpecOut = report->mFileName;
11089 *aLineOut = report->mLineNumber;
11090 *aColumnOut = report->mColumn;
11091 }
11092 aMessageOut.Assign(report->mErrorMsg);
11093 }
11094
11095 // Next, try to unwrap the rejection value as a DOMException.
11096 else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
11097 aLineOut, aColumnOut, aMessageOut)) {
11098 return;
11099 }
11100
11101 // Next, try to unwrap the rejection value as an XPC Exception.
11102 else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut, aLineOut,
11103 aColumnOut, aMessageOut)) {
11104 return;
11105 }
11106 }
11107
11108 // If we could not unwrap a specific error type, then perform default safe
11109 // string conversions on primitives. Objects will result in "[Object]"
11110 // unfortunately.
11111 if (aMessageOut.IsEmpty()) {
11112 nsAutoJSString jsString;
11113 if (jsString.init(aCx, aValue)) {
11114 aMessageOut = jsString;
11115 } else {
11116 JS_ClearPendingException(aCx);
11117 }
11118 }
11119}
11120
11121#undef EXTRACT_EXN_VALUES
11122
11123/* static */
11124bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
11125 if (!aContent || !aContent->IsElement()) {
11126 return false;
11127 }
11128
11129 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
11130 return true;
11131 }
11132
11133 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
11134 nsGkAtoms::simple, eCaseMatters);
11135}
11136
11137/* static */
11138already_AddRefed<ContentFrameMessageManager>
11139nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
11140 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
11141 if (!frameLoaderOwner) {
11142 return nullptr;
11143 }
11144
11145 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
11146 if (!frameLoader) {
11147 return nullptr;
11148 }
11149
11150 RefPtr<ContentFrameMessageManager> manager =
11151 frameLoader->GetBrowserChildMessageManager();
11152 return manager.forget();
11153}
11154
11155/* static */
11156uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
11157 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"
, 11157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11157; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11158 ++sInnerOrOuterWindowCount;
11159 return ++sInnerOrOuterWindowSerialCounter;
11160}
11161
11162/* static */
11163void nsContentUtils::InnerOrOuterWindowDestroyed() {
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 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"
, 11165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { *((volatile int*)__null) = 11165; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11166 --sInnerOrOuterWindowCount;
11167}
11168
11169/* static */
11170nsresult nsContentUtils::AnonymizeURI(nsIURI* aURI, nsCString& aAnonymizedURI) {
11171 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"
, 11171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 11171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11172
11173 if (aURI->SchemeIs("data")) {
11174 aAnonymizedURI.Assign("data:..."_ns);
11175 return NS_OK;
11176 }
11177 // Anonymize the URL.
11178 // Strip the URL of any possible username/password and make it ready to be
11179 // presented in the UI.
11180 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(aURI);
11181 return exposableURI->GetSpec(aAnonymizedURI);
11182}
11183
11184static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
11185 nsAString* result = static_cast<nsAString*>(aData);
11186 return result->Append(aBuf, aLen, fallible);
11187}
11188
11189/* static */
11190bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
11191 nsAString& aOutStr, JSONBehavior aBehavior) {
11192 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"
, 11192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { *((volatile int*)__null) = 11192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11193 switch (aBehavior) {
11194 case UndefinedIsNullStringLiteral: {
11195 aOutStr.Truncate();
11196 JS::Rooted<JS::Value> value(aCx, aValue);
11197 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
11198 JSONCreator, &aOutStr);
11199 }
11200 case UndefinedIsVoidString: {
11201 aOutStr.SetIsVoid(true);
11202 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
11203 &aOutStr);
11204 }
11205 default:
11206 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"
, 11206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { *((volatile int*)__null) = 11206; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11207 return false;
11208 }
11209}
11210
11211/* static */
11212bool nsContentUtils::
11213 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
11214 Document* aDocument) {
11215 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"
, 11216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11216; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11216 "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"
, 11216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "This function only makes sense in content processes" ")"
); do { *((volatile int*)__null) = 11216; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11217
11218 if (aDocument && !aDocument->IsLoadedAsData()) {
11219 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
11220 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"
, 11221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11221; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11221 "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"
, 11221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { *((volatile int*)__null) = 11221; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11222
11223 return !presContext->GetInProcessRootContentDocumentPresContext()
11224 ->HadFirstContentfulPaint() &&
11225 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
11226 }
11227 }
11228 return false;
11229}
11230
11231static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
11232 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"
, 11232); return nullptr; } } while (false)
;
11233
11234 if (auto* window = aGlobal->GetAsInnerWindow()) {
11235 return nsGlobalWindowInner::Cast(window);
11236 }
11237
11238 // When Extensions run content scripts inside a sandbox, it uses
11239 // sandboxPrototype to make them appear as though they're running in the
11240 // scope of the page. So when a content script invokes postMessage, it expects
11241 // the |source| of the received message to be the window set as the
11242 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
11243 // now we need to do some special handling to support it.
11244 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
11245 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"
, 11245); return nullptr; } } while (false)
;
11246
11247 if (xpc::IsSandbox(scope)) {
11248 AutoJSAPI jsapi;
11249 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"
, 11249); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "jsapi.Init(scope)" ")"); do { *((volatile int*)__null
) = 11249; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); } } while (false)
;
11250 JSContext* cx = jsapi.cx();
11251 // Our current Realm on aCx is the sandbox. Using that for unwrapping
11252 // makes sense: if the sandbox can unwrap the window, we can use it.
11253 return xpc::SandboxWindowOrNull(scope, cx);
11254 }
11255
11256 // The calling window must be holding a reference, so we can return a weak
11257 // pointer.
11258 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
11259}
11260
11261/* static */
11262nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
11263 return GetInnerWindowForGlobal(GetIncumbentGlobal());
11264}
11265
11266/* static */
11267nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
11268 return GetInnerWindowForGlobal(GetEntryGlobal());
11269}
11270
11271/* static */
11272bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
11273 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"
, 11273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { *((volatile int*)__null) = 11273; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11274
11275 nsAutoCString list;
11276 Preferences::GetCString(aPrefName, list);
11277 ToLowerCase(list);
11278 return IsURIInList(aURI, list);
11279}
11280
11281/* static */
11282bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
11283#ifdef DEBUG1
11284 nsAutoCString listLowerCase(aList);
11285 ToLowerCase(listLowerCase);
11286 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"
, 11287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11287; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
11287 "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"
, 11287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { *
((volatile int*)__null) = 11287; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
11288#endif
11289
11290 if (!aURI) {
11291 return false;
11292 }
11293
11294 nsAutoCString scheme;
11295 aURI->GetScheme(scheme);
11296 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
11297 return false;
11298 }
11299
11300 if (aList.IsEmpty()) {
11301 return false;
11302 }
11303
11304 // The list is comma separated domain list. Each item may start with "*.".
11305 // If starts with "*.", it matches any sub-domains.
11306
11307 nsCCharSeparatedTokenizer tokenizer(aList, ',');
11308 while (tokenizer.hasMoreTokens()) {
11309 const nsCString token(tokenizer.nextToken());
11310
11311 nsAutoCString host;
11312 aURI->GetHost(host);
11313 if (host.IsEmpty()) {
11314 return false;
11315 }
11316 ToLowerCase(host);
11317
11318 for (;;) {
11319 int32_t index = token.Find(host);
11320 if (index >= 0 &&
11321 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
11322 // If we found a full match, return true.
11323 size_t indexAfterHost = index + host.Length();
11324 if (index == 0 && indexAfterHost == token.Length()) {
11325 return true;
11326 }
11327 // If next character is '/', we need to check the path too.
11328 // We assume the path in the list means "/foo" + "*".
11329 if (token[indexAfterHost] == '/') {
11330 nsDependentCSubstring pathInList(
11331 token, indexAfterHost,
11332 static_cast<nsDependentCSubstring::size_type>(-1));
11333 nsAutoCString filePath;
11334 aURI->GetFilePath(filePath);
11335 ToLowerCase(filePath);
11336 if (StringBeginsWith(filePath, pathInList) &&
11337 (filePath.Length() == pathInList.Length() ||
11338 pathInList.EqualsLiteral("/") ||
11339 filePath[pathInList.Length() - 1] == '/' ||
11340 filePath[pathInList.Length() - 1] == '?' ||
11341 filePath[pathInList.Length() - 1] == '#')) {
11342 return true;
11343 }
11344 }
11345 }
11346 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
11347 int32_t startIndexOfNextLevel =
11348 host.Find(".", startIndexOfCurrentLevel + 1);
11349 if (startIndexOfNextLevel <= 0) {
11350 break;
11351 }
11352 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
11353 }
11354 }
11355
11356 return false;
11357}
11358
11359/* static */
11360ScreenIntMargin nsContentUtils::GetWindowSafeAreaInsets(
11361 nsIScreen* aScreen, const ScreenIntMargin& aSafeAreaInsets,
11362 const LayoutDeviceIntRect& aWindowRect) {
11363 // This calculates safe area insets of window from screen rectangle, window
11364 // rectangle and safe area insets of screen.
11365 //
11366 // +----------------------------------------+ <-- screen
11367 // | +-------------------------------+ <------- window
11368 // | | window's safe area inset top) | |
11369 // +--+-------------------------------+--+ |
11370 // | | | |<------ safe area rectangle of
11371 // | | | | | screen
11372 // +--+-------------------------------+--+ |
11373 // | |window's safe area inset bottom| |
11374 // | +-------------------------------+ |
11375 // +----------------------------------------+
11376 //
11377 ScreenIntMargin windowSafeAreaInsets;
11378
11379 if (windowSafeAreaInsets == aSafeAreaInsets) {
11380 // no safe area insets.
11381 return windowSafeAreaInsets;
11382 }
11383
11384 int32_t screenLeft, screenTop, screenWidth, screenHeight;
11385 nsresult rv =
11386 aScreen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
11387 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"
, 11387)
) {
11388 return windowSafeAreaInsets;
11389 }
11390
11391 const ScreenIntRect screenRect(screenLeft, screenTop, screenWidth,
11392 screenHeight);
11393
11394 ScreenIntRect safeAreaRect = screenRect;
11395 safeAreaRect.Deflate(aSafeAreaInsets);
11396
11397 ScreenIntRect windowRect = ViewAs<ScreenPixel>(
11398 aWindowRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
11399
11400 // FIXME(bug 1754323): This can trigger because the screen rect is not
11401 // orientation-aware.
11402 // MOZ_ASSERT(screenRect.Contains(windowRect),
11403 // "Screen doesn't contain window rect? Something seems off");
11404
11405 // window's rect of safe area
11406 safeAreaRect = safeAreaRect.Intersect(windowRect);
11407
11408 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
11409 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
11410 windowSafeAreaInsets.right =
11411 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
11412 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
11413 (safeAreaRect.y + safeAreaRect.height);
11414
11415 windowSafeAreaInsets.EnsureAtLeast(ScreenIntMargin());
11416 // This shouldn't be needed, but it wallpapers orientation issues, see bug
11417 // 1754323.
11418 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
11419
11420 return windowSafeAreaInsets;
11421}
11422
11423/* static */
11424nsContentUtils::SubresourceCacheValidationInfo
11425nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
11426 nsIURI* aURI) {
11427 SubresourceCacheValidationInfo info;
11428 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
11429 uint32_t value = 0;
11430 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
11431 info.mExpirationTime.emplace(value);
11432 }
11433 }
11434
11435 // Determine whether the cache entry must be revalidated when we try to use
11436 // it. Currently, only HTTP specifies this information...
11437 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
11438 Unused << httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
11439
11440 if (!info.mMustRevalidate) {
11441 Unused << httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
11442 }
11443 }
11444
11445 // data: URIs are safe to cache across documents under any circumstance, so we
11446 // special-case them here even though the channel itself doesn't have any
11447 // caching policy. Same for chrome:// uris.
11448 //
11449 // TODO(emilio): Figure out which other schemes that don't have caching
11450 // policies are safe to cache. Blobs should be...
11451 const bool knownCacheable = [&] {
11452 if (!aURI) {
11453 return false;
11454 }
11455 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
11456 aURI->SchemeIs("moz-extension")) {
11457 return true;
11458 }
11459 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
11460 return !StaticPrefs::nglayout_debug_disable_xul_cache();
11461 }
11462 return false;
11463 }();
11464
11465 if (knownCacheable) {
11466 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"
, 11466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mExpirationTime"
")"); do { *((volatile int*)__null) = 11466; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11467 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"
, 11467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mMustRevalidate"
")"); do { *((volatile int*)__null) = 11467; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11468 info.mExpirationTime = Some(0); // 0 means "doesn't expire".
11469 }
11470
11471 return info;
11472}
11473
11474/* static */
11475bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
11476 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
11477 if (!lg) {
11478 return false;
11479 }
11480 nsLoadFlags flags;
11481 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
11482 return false;
11483 }
11484 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
11485 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
11486}
11487
11488nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
11489 nsCString spec;
11490 if (aURL) {
11491 aURL->GetSpec(spec);
11492 spec.Truncate(std::min(aMaxLen, spec.Length()));
11493 }
11494 return spec;
11495}
11496
11497/* static */
11498nsresult nsContentUtils::AnonymizeId(nsAString& aId,
11499 const nsACString& aOriginKey,
11500 OriginFormat aFormat) {
11501 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"
, 11501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 11501; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11502
11503 nsresult rv;
11504 nsCString rawKey;
11505 if (aFormat == OriginFormat::Base64) {
11506 rv = Base64Decode(aOriginKey, rawKey);
11507 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"
, 11507); return rv; } } while (false)
;
11508 } else {
11509 rawKey = aOriginKey;
11510 }
11511
11512 HMAC hmac;
11513 rv = hmac.Begin(
11514 SEC_OID_SHA256,
11515 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
11516 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"
, 11516); return rv; } } while (false)
;
11517
11518 NS_ConvertUTF16toUTF8 id(aId);
11519 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
11520 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"
, 11520); return rv; } } while (false)
;
11521
11522 nsTArray<uint8_t> macBytes;
11523 rv = hmac.End(macBytes);
11524 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"
, 11524); return rv; } } while (false)
;
11525
11526 nsCString macBase64;
11527 rv = Base64Encode(
11528 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
11529 macBytes.Length()),
11530 macBase64);
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 CopyUTF8toUTF16(macBase64, aId);
11534 return NS_OK;
11535}
11536
11537void nsContentUtils::RequestGeckoTaskBurst() {
11538 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{ 0x2d96b3df, 0xc051, 0x11d1, { 0xa8, 0x27, 0x00, 0x40, 0x95,
0x9a, 0x28, 0xc9 } }
);
11539 if (appShell) {
11540 appShell->GeckoTaskBurst();
11541 }
11542}
11543
11544nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
11545 for (nsIContent* content = aContent; content;
11546 content = content->GetFlattenedTreeParent()) {
11547 if (nsContentUtils::IsDraggableLink(content)) {
11548 return content;
11549 }
11550 }
11551 return nullptr;
11552}
11553
11554template <TreeKind aKind>
11555MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
11556 if constexpr (aKind == TreeKind::DOM) {
11557 return aNode->GetParentNode();
11558 } else {
11559 return aNode->GetFlattenedTreeParentNode();
11560 }
11561}
11562
11563template <TreeKind aKind>
11564MOZ_ALWAYS_INLINEinline Maybe<uint32_t> GetIndexInParent(const nsINode* aParent,
11565 const nsINode* aNode) {
11566 if constexpr (aKind == TreeKind::DOM) {
11567 return aParent->ComputeIndexOf(aNode);
11568 } else {
11569 return aParent->ComputeFlatTreeIndexOf(aNode);
11570 }
11571}
11572
11573template <TreeKind aTreeKind>
11574int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
11575 const nsINode* aNode2,
11576 const nsINode* aCommonAncestor) {
11577 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"
, 11577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") ("
"aNode1 must not be null" ")"); do { *((volatile int*)__null
) = 11577; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11578 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"
, 11578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") ("
"aNode2 must not be null" ")"); do { *((volatile int*)__null
) = 11578; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11579
11580 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"
, 11580)
) {
11581 return 0;
11582 }
11583
11584 AutoTArray<const nsINode*, 32> node1Ancestors;
11585 const nsINode* c1;
11586 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
11587 c1 = GetParent<aTreeKind>(c1)) {
11588 node1Ancestors.AppendElement(c1);
11589 }
11590 if (!c1 && aCommonAncestor) {
11591 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
11592 // Never mind. We can continue as if aCommonAncestor was null.
11593 aCommonAncestor = nullptr;
11594 }
11595
11596 AutoTArray<const nsINode*, 32> node2Ancestors;
11597 const nsINode* c2;
11598 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
11599 c2 = GetParent<aTreeKind>(c2)) {
11600 node2Ancestors.AppendElement(c2);
11601 }
11602 if (!c2 && aCommonAncestor) {
11603 // So, it turns out aCommonAncestor was not an ancestor of c2.
11604 // We need to retry with no common ancestor hint.
11605 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr);
11606 }
11607
11608 int last1 = node1Ancestors.Length() - 1;
11609 int last2 = node2Ancestors.Length() - 1;
11610 const nsINode* node1Ancestor = nullptr;
11611 const nsINode* node2Ancestor = nullptr;
11612 while (last1 >= 0 && last2 >= 0 &&
11613 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
11614 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
11615 last1--;
11616 last2--;
11617 }
11618
11619 if (last1 < 0) {
11620 if (last2 < 0) {
11621 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"
, 11621); MOZ_PretendNoReturn(); } } while (0)
;
11622 return 0;
11623 }
11624 // aContent1 is an ancestor of aContent2
11625 return -1;
11626 }
11627
11628 if (last2 < 0) {
11629 // aContent2 is an ancestor of aContent1
11630 return 1;
11631 }
11632
11633 // node1Ancestor != node2Ancestor, so they must be siblings with the
11634 // same parent
11635 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
11636 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 11636)
) { // different documents??
11637 return 0;
11638 }
11639
11640 const Maybe<uint32_t> index1 =
11641 GetIndexInParent<aTreeKind>(parent, node1Ancestor);
11642 const Maybe<uint32_t> index2 =
11643 GetIndexInParent<aTreeKind>(parent, node2Ancestor);
11644
11645 // None of the nodes are anonymous, just do a regular comparison.
11646 if (index1.isSome() && index2.isSome()) {
11647 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
11648 }
11649
11650 // Otherwise handle pseudo-element and anonymous node ordering.
11651 // ::marker -> ::before -> anon siblings -> regular siblings -> ::after
11652 auto PseudoIndex = [](const nsINode* aNode,
11653 const Maybe<uint32_t>& aNodeIndex) -> int32_t {
11654 if (aNodeIndex.isSome()) {
11655 return 1; // Not a pseudo.
11656 }
11657 if (aNode->IsGeneratedContentContainerForMarker()) {
11658 return -2;
11659 }
11660 if (aNode->IsGeneratedContentContainerForBefore()) {
11661 return -1;
11662 }
11663 if (aNode->IsGeneratedContentContainerForAfter()) {
11664 return 2;
11665 }
11666 return 0;
11667 };
11668
11669 return PseudoIndex(node1Ancestor, index1) -
11670 PseudoIndex(node2Ancestor, index2);
11671}
11672
11673nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost,
11674 ShadowRootMode aMode,
11675 bool aIsClonable,
11676 bool aIsSerializable,
11677 bool aDelegatesFocus) {
11678 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
11679 if (!host || host->GetShadowRoot()) {
11680 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
11681 return nullptr;
11682 }
11683
11684 ShadowRootInit init;
11685 init.mMode = aMode;
11686 init.mDelegatesFocus = aDelegatesFocus;
11687 init.mSlotAssignment = SlotAssignmentMode::Named;
11688 init.mClonable = aIsClonable;
11689 init.mSerializable = aIsSerializable;
11690
11691 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
11692 if (shadowRoot) {
11693 shadowRoot->SetIsDeclarative(
11694 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
11695 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
11696 shadowRoot->SetAvailableToElementInternals();
11697 }
11698 return shadowRoot;
11699}
11700
11701template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
11702 const nsINode*, const nsINode*, const nsINode*);
11703template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
11704 const nsINode*, const nsINode*, const nsINode*);
11705
11706namespace mozilla {
11707std::ostream& operator<<(std::ostream& aOut,
11708 const PreventDefaultResult aPreventDefaultResult) {
11709 switch (aPreventDefaultResult) {
11710 case PreventDefaultResult::No:
11711 aOut << "unhandled";
11712 break;
11713 case PreventDefaultResult::ByContent:
11714 aOut << "handled-by-content";
11715 break;
11716 case PreventDefaultResult::ByChrome:
11717 aOut << "handled-by-chrome";
11718 break;
11719 }
11720 return aOut;
11721}
11722} // namespace mozilla