Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsContentUtils.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D 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/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/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/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../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-05-16-034744-15991-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/ShutdownPhase.h"
115#include "mozilla/Span.h"
116#include "mozilla/StaticAnalysisFunctions.h"
117#include "mozilla/StaticPrefs_browser.h"
118#include "mozilla/StaticPrefs_dom.h"
119#ifdef FUZZING
120# include "mozilla/StaticPrefs_fuzzing.h"
121#endif
122#include "mozilla/StaticPrefs_nglayout.h"
123#include "mozilla/StaticPrefs_privacy.h"
124#include "mozilla/StaticPrefs_test.h"
125#include "mozilla/StaticPrefs_ui.h"
126#include "mozilla/StaticPtr.h"
127#include "mozilla/TextControlState.h"
128#include "mozilla/TextEditor.h"
129#include "mozilla/TextEvents.h"
130#include "mozilla/UniquePtr.h"
131#include "mozilla/Unused.h"
132#include "mozilla/Variant.h"
133#include "mozilla/ViewportUtils.h"
134#include "mozilla/dom/AncestorIterator.h"
135#include "mozilla/dom/AutoEntryScript.h"
136#include "mozilla/dom/AutocompleteInfoBinding.h"
137#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
138#include "mozilla/dom/BindingDeclarations.h"
139#include "mozilla/dom/BindingUtils.h"
140#include "mozilla/dom/BlobImpl.h"
141#include "mozilla/dom/BlobURLProtocolHandler.h"
142#include "mozilla/dom/BorrowedAttrInfo.h"
143#include "mozilla/dom/BrowserBridgeParent.h"
144#include "mozilla/dom/BrowserParent.h"
145#include "mozilla/dom/BrowsingContext.h"
146#include "mozilla/dom/BrowsingContextGroup.h"
147#include "mozilla/dom/CallbackFunction.h"
148#include "mozilla/dom/CallbackObject.h"
149#include "mozilla/dom/ChromeMessageBroadcaster.h"
150#include "mozilla/dom/ContentChild.h"
151#include "mozilla/dom/ContentFrameMessageManager.h"
152#include "mozilla/dom/ContentParent.h"
153#include "mozilla/dom/CustomElementRegistry.h"
154#include "mozilla/dom/CustomElementRegistryBinding.h"
155#include "mozilla/dom/CustomElementTypes.h"
156#include "mozilla/dom/DOMArena.h"
157#include "mozilla/dom/DOMException.h"
158#include "mozilla/dom/DOMExceptionBinding.h"
159#include "mozilla/dom/DOMSecurityMonitor.h"
160#include "mozilla/dom/DOMTypes.h"
161#include "mozilla/dom/DataTransfer.h"
162#include "mozilla/dom/DocGroup.h"
163#include "mozilla/dom/Document.h"
164#include "mozilla/dom/DocumentFragment.h"
165#include "mozilla/dom/DocumentInlines.h"
166#include "mozilla/dom/Element.h"
167#include "mozilla/dom/ElementBinding.h"
168#include "mozilla/dom/ElementInlines.h"
169#include "mozilla/dom/Event.h"
170#include "mozilla/dom/EventTarget.h"
171#include "mozilla/dom/FileBlobImpl.h"
172#include "mozilla/dom/FileSystemSecurity.h"
173#include "mozilla/dom/FilteredNodeIterator.h"
174#include "mozilla/dom/FormData.h"
175#include "mozilla/dom/FragmentOrElement.h"
176#include "mozilla/dom/FromParser.h"
177#include "mozilla/dom/HTMLElement.h"
178#include "mozilla/dom/HTMLFormElement.h"
179#include "mozilla/dom/HTMLImageElement.h"
180#include "mozilla/dom/HTMLInputElement.h"
181#include "mozilla/dom/HTMLTextAreaElement.h"
182#include "mozilla/dom/IPCBlob.h"
183#include "mozilla/dom/IPCBlobUtils.h"
184#include "mozilla/dom/MessageBroadcaster.h"
185#include "mozilla/dom/MessageListenerManager.h"
186#include "mozilla/dom/MessagePort.h"
187#include "mozilla/dom/MouseEventBinding.h"
188#include "mozilla/dom/NameSpaceConstants.h"
189#include "mozilla/dom/NodeBinding.h"
190#include "mozilla/dom/NodeInfo.h"
191#include "mozilla/dom/PBrowser.h"
192#include "mozilla/dom/PContentChild.h"
193#include "mozilla/dom/PrototypeList.h"
194#include "mozilla/dom/ReferrerPolicyBinding.h"
195#include "mozilla/dom/ScriptSettings.h"
196#include "mozilla/dom/Selection.h"
197#include "mozilla/dom/ShadowRoot.h"
198#include "mozilla/dom/Text.h"
199#include "mozilla/dom/UserActivation.h"
200#include "mozilla/dom/WindowContext.h"
201#include "mozilla/dom/WorkerCommon.h"
202#include "mozilla/dom/WorkerPrivate.h"
203#include "mozilla/dom/WorkerRunnable.h"
204#include "mozilla/dom/XULCommandEvent.h"
205#include "mozilla/glean/GleanPings.h"
206#include "mozilla/fallible.h"
207#include "mozilla/gfx/2D.h"
208#include "mozilla/gfx/BaseMargin.h"
209#include "mozilla/gfx/BasePoint.h"
210#include "mozilla/gfx/BaseSize.h"
211#include "mozilla/gfx/DataSurfaceHelpers.h"
212#include "mozilla/gfx/Point.h"
213#include "mozilla/gfx/Rect.h"
214#include "mozilla/gfx/Types.h"
215#include "mozilla/ipc/ProtocolUtils.h"
216#include "mozilla/ipc/SharedMemory.h"
217#include "mozilla/net/UrlClassifierCommon.h"
218#include "mozilla/Tokenizer.h"
219#include "mozilla/widget/IMEData.h"
220#include "nsAboutProtocolUtils.h"
221#include "nsAlgorithm.h"
222#include "nsArrayUtils.h"
223#include "nsAtomHashKeys.h"
224#include "nsAttrName.h"
225#include "nsAttrValue.h"
226#include "nsAttrValueInlines.h"
227#include "nsBaseHashtable.h"
228#include "nsCCUncollectableMarker.h"
229#include "nsCOMPtr.h"
230#include "nsCRT.h"
231#include "nsCRTGlue.h"
232#include "nsCanvasFrame.h"
233#include "nsCaseTreatment.h"
234#include "nsCharSeparatedTokenizer.h"
235#include "nsCharTraits.h"
236#include "nsCompatibility.h"
237#include "nsComponentManagerUtils.h"
238#include "nsContainerFrame.h"
239#include "nsContentCreatorFunctions.h"
240#include "nsContentDLF.h"
241#include "nsContentList.h"
242#include "nsContentListDeclarations.h"
243#include "nsContentPolicyUtils.h"
244#include "nsCoord.h"
245#include "nsCycleCollectionNoteChild.h"
246#include "nsDOMMutationObserver.h"
247#include "nsDOMString.h"
248#include "nsTHashMap.h"
249#include "nsDebug.h"
250#include "nsDocShell.h"
251#include "nsDocShellCID.h"
252#include "nsError.h"
253#include "nsFocusManager.h"
254#include "nsFrameList.h"
255#include "nsFrameLoader.h"
256#include "nsFrameLoaderOwner.h"
257#include "nsGenericHTMLElement.h"
258#include "nsGkAtoms.h"
259#include "nsGlobalWindowInner.h"
260#include "nsGlobalWindowOuter.h"
261#include "nsHTMLDocument.h"
262#include "nsHTMLTags.h"
263#include "nsHashKeys.h"
264#include "nsHtml5StringParser.h"
265#include "nsIAboutModule.h"
266#include "nsIAnonymousContentCreator.h"
267#include "nsIAppShell.h"
268#include "nsIArray.h"
269#include "nsIAsyncVerifyRedirectCallback.h"
270#include "nsIBidiKeyboard.h"
271#include "nsIBrowser.h"
272#include "nsICacheInfoChannel.h"
273#include "nsICategoryManager.h"
274#include "nsIChannel.h"
275#include "nsIChannelEventSink.h"
276#include "nsIClassifiedChannel.h"
277#include "nsIConsoleService.h"
278#include "nsIContent.h"
279#include "nsIContentInlines.h"
280#include "nsIContentPolicy.h"
281#include "nsIContentSecurityPolicy.h"
282#include "nsIContentSink.h"
283#include "nsIDOMWindowUtils.h"
284#include "nsIDocShell.h"
285#include "nsIDocShellTreeItem.h"
286#include "nsIDocumentEncoder.h"
287#include "nsIDocumentLoaderFactory.h"
288#include "nsIDocumentViewer.h"
289#include "nsIDragService.h"
290#include "nsIDragSession.h"
291#include "nsIFile.h"
292#include "nsIFocusManager.h"
293#include "nsIFormControl.h"
294#include "nsIFragmentContentSink.h"
295#include "nsIFrame.h"
296#include "nsIGlobalObject.h"
297#include "nsIHttpChannel.h"
298#include "nsIHttpChannelInternal.h"
299#include "nsIIOService.h"
300#include "nsIImageLoadingContent.h"
301#include "nsIInputStream.h"
302#include "nsIInterfaceRequestor.h"
303#include "nsIInterfaceRequestorUtils.h"
304#include "nsILoadContext.h"
305#include "nsILoadGroup.h"
306#include "nsILoadInfo.h"
307#include "nsIMIMEService.h"
308#include "nsIMemoryReporter.h"
309#include "nsINetUtil.h"
310#include "nsINode.h"
311#include "nsIObjectLoadingContent.h"
312#include "nsIObserver.h"
313#include "nsIObserverService.h"
314#include "nsIParserUtils.h"
315#include "nsIPermissionManager.h"
316#include "nsIPrincipal.h"
317#include "nsIProperties.h"
318#include "nsIProtocolHandler.h"
319#include "nsIRequest.h"
320#include "nsIRunnable.h"
321#include "nsIScreen.h"
322#include "nsIScriptError.h"
323#include "nsIScriptGlobalObject.h"
324#include "nsIScriptObjectPrincipal.h"
325#include "nsIScriptSecurityManager.h"
326#include "nsISerialEventTarget.h"
327#include "nsIStreamConverter.h"
328#include "nsIStreamConverterService.h"
329#include "nsIStringBundle.h"
330#include "nsISupports.h"
331#include "nsISupportsPrimitives.h"
332#include "nsISupportsUtils.h"
333#include "nsITransferable.h"
334#include "nsIURI.h"
335#include "nsIURIMutator.h"
336#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
337# include "nsIURIWithSpecialOrigin.h"
338#endif
339#include "nsIUserIdleServiceInternal.h"
340#include "nsIWeakReferenceUtils.h"
341#include "nsIWebNavigation.h"
342#include "nsIWebNavigationInfo.h"
343#include "nsIWidget.h"
344#include "nsIWindowMediator.h"
345#include "nsIXPConnect.h"
346#include "nsJSPrincipals.h"
347#include "nsJSUtils.h"
348#include "nsLayoutUtils.h"
349#include "nsLiteralString.h"
350#include "nsMargin.h"
351#include "nsMimeTypes.h"
352#include "nsNameSpaceManager.h"
353#include "nsNetCID.h"
354#include "nsNetUtil.h"
355#include "nsNodeInfoManager.h"
356#include "nsPIDOMWindow.h"
357#include "nsPIDOMWindowInlines.h"
358#include "nsParser.h"
359#include "nsParserConstants.h"
360#include "nsPoint.h"
361#include "nsPointerHashKeys.h"
362#include "nsPresContext.h"
363#include "nsQueryFrame.h"
364#include "nsQueryObject.h"
365#include "nsRange.h"
366#include "nsRefPtrHashtable.h"
367#include "nsSandboxFlags.h"
368#include "nsScriptSecurityManager.h"
369#include "nsServiceManagerUtils.h"
370#include "nsStreamUtils.h"
371#include "nsString.h"
372#include "nsStringBundle.h"
373#include "nsStringFlags.h"
374#include "nsStringFwd.h"
375#include "nsStringIterator.h"
376#include "nsStringStream.h"
377#include "nsTArray.h"
378#include "nsTLiteralString.h"
379#include "nsTPromiseFlatString.h"
380#include "nsTStringRepr.h"
381#include "nsTextFragment.h"
382#include "nsTextNode.h"
383#include "nsThreadManager.h"
384#include "nsThreadUtils.h"
385#include "nsTreeSanitizer.h"
386#include "nsUGenCategory.h"
387#include "nsURLHelper.h"
388#include "nsUnicodeProperties.h"
389#include "nsVariant.h"
390#include "nsWidgetsCID.h"
391#include "nsView.h"
392#include "nsViewManager.h"
393#include "nsXPCOM.h"
394#include "nsXPCOMCID.h"
395#include "nsXULAppAPI.h"
396#include "nsXULElement.h"
397#include "nsXULPopupManager.h"
398#include "nscore.h"
399#include "prinrval.h"
400#include "xpcprivate.h"
401#include "xpcpublic.h"
402
403#if defined(XP_WIN)
404// Undefine LoadImage to prevent naming conflict with Windows.
405# undef LoadImage
406#endif
407
408extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
409 const char** next, char16_t* result);
410extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
411 const char** colon);
412
413using namespace mozilla::dom;
414using namespace mozilla::ipc;
415using namespace mozilla::gfx;
416using namespace mozilla::layers;
417using namespace mozilla::widget;
418using namespace mozilla;
419
420const char kLoadAsData[] = "loadAsData";
421
422nsIXPConnect* nsContentUtils::sXPConnect;
423nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
424nsIPrincipal* nsContentUtils::sSystemPrincipal;
425nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
426nsIConsoleService* nsContentUtils::sConsoleService;
427
428static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
429static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
430static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
431nsIStringBundleService* nsContentUtils::sStringBundleService;
432
433static StaticRefPtr<nsIStringBundle>
434 sStringBundles[nsContentUtils::PropertiesFile_COUNT];
435
436nsIContentPolicy* nsContentUtils::sContentPolicyService;
437bool nsContentUtils::sTriedToGetContentPolicy = false;
438StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
439uint32_t nsContentUtils::sScriptBlockerCount = 0;
440uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
441AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
442 nullptr;
443uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
444nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
445
446bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
447
448nsString* nsContentUtils::sShiftText = nullptr;
449nsString* nsContentUtils::sControlText = nullptr;
450nsString* nsContentUtils::sCommandOrWinText = nullptr;
451nsString* nsContentUtils::sAltText = nullptr;
452nsString* nsContentUtils::sModifierSeparator = nullptr;
453
454bool nsContentUtils::sInitialized = false;
455#ifndef RELEASE_OR_BETA
456bool nsContentUtils::sBypassCSSOMOriginCheck = false;
457#endif
458
459nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
460nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
461
462nsContentUtils::UserInteractionObserver*
463 nsContentUtils::sUserInteractionObserver = nullptr;
464
465nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
466nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
467nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
468bool nsContentUtils::sFragmentParsingActive = false;
469
470bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false;
471bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false;
472
473mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
474 "nsResistFingerprinting");
475mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
476
477int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
478uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
479
480template Maybe<int32_t> nsContentUtils::ComparePoints(
481 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary);
482template Maybe<int32_t> nsContentUtils::ComparePoints(
483 const RangeBoundary& aFirstBoundary,
484 const RawRangeBoundary& aSecondBoundary);
485template Maybe<int32_t> nsContentUtils::ComparePoints(
486 const RawRangeBoundary& aFirstBoundary,
487 const RangeBoundary& aSecondBoundary);
488template Maybe<int32_t> nsContentUtils::ComparePoints(
489 const RawRangeBoundary& aFirstBoundary,
490 const RawRangeBoundary& aSecondBoundary);
491
492template int32_t nsContentUtils::ComparePoints_Deprecated(
493 const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary,
494 bool* aDisconnected);
495template int32_t nsContentUtils::ComparePoints_Deprecated(
496 const RangeBoundary& aFirstBoundary,
497 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
498template int32_t nsContentUtils::ComparePoints_Deprecated(
499 const RawRangeBoundary& aFirstBoundary,
500 const RangeBoundary& aSecondBoundary, bool* aDisconnected);
501template int32_t nsContentUtils::ComparePoints_Deprecated(
502 const RawRangeBoundary& aFirstBoundary,
503 const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
504
505// Subset of
506// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
507enum AutocompleteUnsupportedFieldName : uint8_t {
508#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
509 eAutocompleteUnsupportedFieldName_##name_,
510#include "AutocompleteFieldList.h"
511#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
512};
513
514enum AutocompleteNoPersistFieldName : uint8_t {
515#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
516 eAutocompleteNoPersistFieldName_##name_,
517#include "AutocompleteFieldList.h"
518#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
519};
520
521enum AutocompleteUnsupportFieldContactHint : uint8_t {
522#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
523 eAutocompleteUnsupportedFieldContactHint_##name_,
524#include "AutocompleteFieldList.h"
525#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
526};
527
528enum AutocompleteFieldName : uint8_t {
529#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
530#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
531 AUTOCOMPLETE_FIELD_NAME(name_, value_)
532#include "AutocompleteFieldList.h"
533#undef AUTOCOMPLETE_FIELD_NAME
534#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
535};
536
537enum AutocompleteFieldHint : uint8_t {
538#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
539#include "AutocompleteFieldList.h"
540#undef AUTOCOMPLETE_FIELD_HINT
541};
542
543enum AutocompleteFieldContactHint : uint8_t {
544#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
545 eAutocompleteFieldContactHint_##name_,
546#include "AutocompleteFieldList.h"
547#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
548};
549
550enum AutocompleteCredentialType : uint8_t {
551#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
552 eAutocompleteCredentialType_##name_,
553#include "AutocompleteFieldList.h"
554#undef AUTOCOMPLETE_CREDENTIAL_TYPE
555};
556
557enum AutocompleteCategory {
558#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
559#include "AutocompleteFieldList.h"
560#undef AUTOCOMPLETE_CATEGORY
561};
562
563static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
564#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
565 {value_, eAutocompleteUnsupportedFieldName_##name_},
566#include "AutocompleteFieldList.h"
567#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
568 {nullptr, 0}};
569
570static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = {
571#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
572 {value_, eAutocompleteNoPersistFieldName_##name_},
573#include "AutocompleteFieldList.h"
574#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
575 {nullptr, 0}};
576
577static const nsAttrValue::EnumTable
578 kAutocompleteUnsupportedContactFieldHintTable[] = {
579#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
580 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
581#include "AutocompleteFieldList.h"
582#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
583 {nullptr, 0}};
584
585static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
586#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
587 {value_, eAutocompleteFieldName_##name_},
588#include "AutocompleteFieldList.h"
589#undef AUTOCOMPLETE_FIELD_NAME
590 {nullptr, 0}};
591
592static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
593#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
594 {value_, eAutocompleteFieldName_##name_},
595#include "AutocompleteFieldList.h"
596#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
597 {nullptr, 0}};
598
599static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
600#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
601 {value_, eAutocompleteFieldHint_##name_},
602#include "AutocompleteFieldList.h"
603#undef AUTOCOMPLETE_FIELD_HINT
604 {nullptr, 0}};
605
606static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
607#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
608 {value_, eAutocompleteFieldContactHint_##name_},
609#include "AutocompleteFieldList.h"
610#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
611 {nullptr, 0}};
612
613static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = {
614#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
615 {value_, eAutocompleteCredentialType_##name_},
616#include "AutocompleteFieldList.h"
617#undef AUTOCOMPLETE_CREDENTIAL_TYPE
618 {nullptr, 0}};
619
620namespace {
621
622static PLDHashTable* sEventListenerManagersHash;
623
624// A global hashtable to for keeping the arena alive for cross docGroup node
625// adoption.
626static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
627 sDOMArenaHashtable;
628
629class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter {
630 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)static size_t MallocSizeOf(const void* aPtr) { mozilla::dmd::
Report(aPtr); return moz_malloc_size_of(aPtr); }
631
632 ~DOMEventListenerManagersHashReporter() = default;
633
634 public:
635 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:
636
637 NS_IMETHODvirtual nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
638 nsISupports* aData, bool aAnonymize) override {
639 // We don't measure the |EventListenerManager| objects pointed to by the
640 // entries because those references are non-owning.
641 int64_t amount =
642 sEventListenerManagersHash
643 ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
644 MallocSizeOf)
645 : 0;
646
647 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)
648 "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)
649 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)
;
650
651 return NS_OK;
652 }
653};
654
655NS_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"
, 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
655; __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"
, 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 655; __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"
, 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 655
; __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"
, 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 655; __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"
, 655); 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; }
656
657class EventListenerManagerMapEntry : public PLDHashEntryHdr {
658 public:
659 explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {}
660
661 ~EventListenerManagerMapEntry() {
662 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"
, 662); MOZ_PretendNoReturn(); } } while (0)
;
663 }
664
665 protected: // declared protected to silence clang warnings
666 const void* mKey; // must be first, to look like PLDHashEntryStub
667
668 public:
669 RefPtr<EventListenerManager> mListenerManager;
670};
671
672static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry,
673 const void* key) {
674 // Initialize the entry with placement new
675 new (entry) EventListenerManagerMapEntry(key);
676}
677
678static void EventListenerManagerHashClearEntry(PLDHashTable* table,
679 PLDHashEntryHdr* entry) {
680 EventListenerManagerMapEntry* lm =
681 static_cast<EventListenerManagerMapEntry*>(entry);
682
683 // Let the EventListenerManagerMapEntry clean itself up...
684 lm->~EventListenerManagerMapEntry();
685}
686
687class SameOriginCheckerImpl final : public nsIChannelEventSink,
688 public nsIInterfaceRequestor {
689 ~SameOriginCheckerImpl() = default;
690
691 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:
692 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
693 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
694};
695
696} // namespace
697
698void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
699 // Note: Document::SuppressEventHandling will also automatically suppress
700 // event handling for any in-process sub-documents. However, since we need
701 // to deal with cases where remote BrowsingContexts may be interleaved
702 // with in-process ones, we still need to walk the entire tree ourselves.
703 // This may be slightly redundant in some cases, but since event handling
704 // suppressions maintain a count of current blockers, it does not cause
705 // any problems.
706 aDoc->SuppressEventHandling();
707}
708
709void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
710 aDoc->UnsuppressEventHandlingAndFireEvents(true);
711}
712
713AutoSuppressEventHandling::~AutoSuppressEventHandling() {
714 UnsuppressDocuments();
715}
716
717void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
718 AutoSuppressEventHandling::SuppressDocument(aDoc);
719 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
720 win->Suspend();
721 mWindows.AppendElement(win);
722 }
723}
724
725AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
726 for (const auto& win : mWindows) {
727 win->Resume();
728 }
729}
730
731/**
732 * This class is used to determine whether or not the user is currently
733 * interacting with the browser. It listens to observer events to toggle the
734 * value of the sUserActive static.
735 *
736 * This class is an internal implementation detail.
737 * nsContentUtils::GetUserIsInteracting() should be used to access current
738 * user interaction status.
739 */
740class nsContentUtils::UserInteractionObserver final
741 : public nsIObserver,
742 public BackgroundHangAnnotator {
743 public:
744 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:
745 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
746
747 void Init();
748 void Shutdown();
749 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
750
751 static Atomic<bool> sUserActive;
752
753 private:
754 ~UserInteractionObserver() = default;
755};
756
757static constexpr nsLiteralCString kRfpPrefs[] = {
758 "privacy.resistFingerprinting"_ns,
759 "privacy.resistFingerprinting.pbmode"_ns,
760 "privacy.fingerprintingProtection"_ns,
761 "privacy.fingerprintingProtection.pbmode"_ns,
762 "privacy.fingerprintingProtection.overrides"_ns,
763};
764
765static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
766 AutoTArray<RefPtr<BrowsingContextGroup>, 5> bcGroups;
767 BrowsingContextGroup::GetAllGroups(bcGroups);
768 for (auto& bcGroup : bcGroups) {
769 AutoTArray<DocGroup*, 5> docGroups;
770 bcGroup->GetDocGroups(docGroups);
771 for (auto* docGroup : docGroups) {
772 for (Document* doc : *docGroup) {
773 if (doc->RecomputeResistFingerprinting()) {
774 if (auto* pc = doc->GetPresContext()) {
775 pc->MediaFeatureValuesChanged(
776 {MediaFeatureChangeReason::PreferenceChange},
777 MediaFeatureChangePropagation::JustThisDocument);
778 }
779 }
780 }
781 }
782 }
783}
784
785// static
786nsresult nsContentUtils::Init() {
787 if (sInitialized) {
788 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"
, 788)
;
789
790 return NS_OK;
791 }
792
793 nsHTMLTags::AddRefTable();
794
795 sXPConnect = nsXPConnect::XPConnect();
796 // We hold a strong ref to sXPConnect to ensure that it does not go away until
797 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
798 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
799 // various stuff already being torn down by then. Note that this means that
800 // we are effectively making sure that if we leak nsLayoutStatics then we also
801 // leak nsXPConnect.
802 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
803
804 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
805 if (!sSecurityManager) return NS_ERROR_FAILURE;
806 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
807
808 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
809 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"
, 809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSystemPrincipal"
")"); do { *((volatile int*)__null) = 809; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
810
811 RefPtr<NullPrincipal> nullPrincipal =
812 NullPrincipal::CreateWithoutOriginAttributes();
813 if (!nullPrincipal) {
814 return NS_ERROR_FAILURE;
815 }
816
817 nullPrincipal.forget(&sNullSubjectPrincipal);
818
819 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
820
821 if (!sEventListenerManagersHash) {
822 static const PLDHashTableOps hash_table_ops = {
823 PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub,
824 PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry,
825 EventListenerManagerHashInitEntry};
826
827 sEventListenerManagersHash =
828 new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
829
830 RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
831 }
832
833 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
834
835#ifndef RELEASE_OR_BETA
836 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
837#endif
838
839 Element::InitCCCallbacks();
840
841 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
842 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"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService" ")"
); do { *((volatile int*)__null) = 842; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
843
844 if (XRE_IsParentProcess()) {
845 AsyncPrecreateStringBundles();
846
847#if defined(MOZ_WIDGET_ANDROID)
848 // On Android, at-shutdown ping submission isn't reliable
849 // (( because, on Android, we usually get killed, not shut down )).
850 // To have a chance at submitting the ping, aim for idle after startup.
851 nsresult rv = NS_DispatchToCurrentThreadQueue(
852 NS_NewRunnableFunction(
853 "AndroidUseCounterPingSubmitter",
854 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
855 EventQueuePriority::Idle);
856 // This is mostly best-effort, so if it goes awry, just log.
857 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"
, 857)
;
858#endif // defined(MOZ_WIDGET_ANDROID)
859
860 RunOnShutdown(
861 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
862 ShutdownPhase::AppShutdownConfirmed);
863 }
864
865 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
866 uio->Init();
867 uio.forget(&sUserInteractionObserver);
868
869 for (const auto& pref : kRfpPrefs) {
870 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
871 }
872
873 sInitialized = true;
874
875 return NS_OK;
876}
877
878bool nsContentUtils::InitJSBytecodeMimeType() {
879 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"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
880 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"
, 880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType"
")"); do { *((volatile int*)__null) = 880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
881 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"
, 881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType"
")"); do { *((volatile int*)__null) = 881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
882
883 JS::BuildIdCharVector jsBuildId;
884 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
885 return false;
886 }
887
888 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
889 sJSScriptBytecodeMimeType =
890 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
891 sJSModuleBytecodeMimeType =
892 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
893 return true;
894}
895
896void nsContentUtils::GetShiftText(nsAString& text) {
897 if (!sShiftText) InitializeModifierStrings();
898 text.Assign(*sShiftText);
899}
900
901void nsContentUtils::GetControlText(nsAString& text) {
902 if (!sControlText) InitializeModifierStrings();
903 text.Assign(*sControlText);
904}
905
906void nsContentUtils::GetCommandOrWinText(nsAString& text) {
907 if (!sCommandOrWinText) {
908 InitializeModifierStrings();
909 }
910 text.Assign(*sCommandOrWinText);
911}
912
913void nsContentUtils::GetAltText(nsAString& text) {
914 if (!sAltText) InitializeModifierStrings();
915 text.Assign(*sAltText);
916}
917
918void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
919 if (!sModifierSeparator) InitializeModifierStrings();
920 text.Assign(*sModifierSeparator);
921}
922
923void nsContentUtils::InitializeModifierStrings() {
924 // load the display strings for the keyboard accelerators
925 nsCOMPtr<nsIStringBundleService> bundleService =
926 mozilla::components::StringBundle::Service();
927 nsCOMPtr<nsIStringBundle> bundle;
928 DebugOnly<nsresult> rv = NS_OK;
929 if (bundleService) {
930 rv = bundleService->CreateBundle(
931 "chrome://global-platform/locale/platformKeys.properties",
932 getter_AddRefs(bundle));
933 }
934
935 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"
, 937); MOZ_PretendNoReturn(); } } while (0)
936 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"
, 937); MOZ_PretendNoReturn(); } } while (0)
937 "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"
, 937); MOZ_PretendNoReturn(); } } while (0)
;
938 nsAutoString shiftModifier;
939 nsAutoString commandOrWinModifier;
940 nsAutoString altModifier;
941 nsAutoString controlModifier;
942 nsAutoString modifierSeparator;
943 if (bundle) {
944 // macs use symbols for each modifier key, so fetch each from the bundle,
945 // which also covers i18n
946 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
947 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
948 bundle->GetStringFromName("VK_ALT", altModifier);
949 bundle->GetStringFromName("VK_CONTROL", controlModifier);
950 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
951 }
952 // if any of these don't exist, we get an empty string
953 sShiftText = new nsString(shiftModifier);
954 sCommandOrWinText = new nsString(commandOrWinModifier);
955 sAltText = new nsString(altModifier);
956 sControlText = new nsString(controlModifier);
957 sModifierSeparator = new nsString(modifierSeparator);
958}
959
960mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
961 EventMessage aEventMessage) {
962 switch (aEventMessage) {
963#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
964 case message_: \
965 return struct_;
966#include "mozilla/EventNameList.h"
967#undef MESSAGE_TO_EVENT
968 default:
969 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"
, 969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ *((volatile int*)__null) = 969; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
970 return eBasicEventClass;
971 }
972}
973
974bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
975 bool doesNotReturnData = false;
976 nsresult rv = NS_URIChainHasFlags(
977 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
978 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
979}
980
981/* static */
982nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
983 switch (aEventMessage) {
984#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
985 case message_: \
986 return nsGkAtoms::on##name_;
987#include "mozilla/EventNameList.h"
988#undef MESSAGE_TO_EVENT
989 default:
990 return nullptr;
991 }
992}
993
994bool nsContentUtils::InitializeEventTable() {
995 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"
, 995); MOZ_PretendNoReturn(); } } while (0)
;
996 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"
, 996); MOZ_PretendNoReturn(); } } while (0)
;
997
998 static const EventNameMapping eventArray[] = {
999#define EVENT(name_, _message, _type, _class) \
1000 {nsGkAtoms::on##name_, _type, _message, _class},
1001#define WINDOW_ONLY_EVENT EVENT
1002#define DOCUMENT_ONLY_EVENTEVENT EVENT
1003#define NON_IDL_EVENT EVENT
1004#include "mozilla/EventNameList.h"
1005#undef WINDOW_ONLY_EVENT
1006#undef NON_IDL_EVENT
1007#undef EVENT
1008 {nullptr}};
1009
1010 sAtomEventTable =
1011 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(ArrayLength(eventArray));
1012 sStringEventTable = new nsTHashMap<nsStringHashKey, EventNameMapping>(
1013 ArrayLength(eventArray));
1014 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1015
1016 // Subtract one from the length because of the trailing null
1017 for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) {
1018 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"
, 1019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1019; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1019 "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"
, 1019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.h"
")"); do { *((volatile int*)__null) = 1019; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1020 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1021 sStringEventTable->InsertOrUpdate(
1022 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1023 eventArray[i]);
1024 }
1025
1026 return true;
1027}
1028
1029void nsContentUtils::InitializeTouchEventTable() {
1030 static bool sEventTableInitialized = false;
1031 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1032 sEventTableInitialized = true;
1033 static const EventNameMapping touchEventArray[] = {
1034#define EVENT(name_, _message, _type, _class)
1035#define TOUCH_EVENT(name_, _message, _type, _class) \
1036 {nsGkAtoms::on##name_, _type, _message, _class},
1037#include "mozilla/EventNameList.h"
1038#undef TOUCH_EVENT
1039#undef EVENT
1040 {nullptr}};
1041 // Subtract one from the length because of the trailing null
1042 for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
1043 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1044 touchEventArray[i]);
1045 sStringEventTable->InsertOrUpdate(
1046 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1047 touchEventArray[i]);
1048 }
1049 }
1050}
1051
1052static bool Is8bit(const nsAString& aString) {
1053 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1054
1055 for (nsAString::const_char_iterator start = aString.BeginReading(),
1056 end = aString.EndReading();
1057 start != end; ++start) {
1058 if (*start & EIGHT_BIT) {
1059 return false;
1060 }
1061 }
1062
1063 return true;
1064}
1065
1066nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1067 nsAString& aAsciiBase64String) {
1068 if (!Is8bit(aBinaryData)) {
1069 aAsciiBase64String.Truncate();
1070 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1071 }
1072
1073 return Base64Encode(aBinaryData, aAsciiBase64String);
1074}
1075
1076nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1077 nsAString& aBinaryData) {
1078 if (!Is8bit(aAsciiBase64String)) {
1079 aBinaryData.Truncate();
1080 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1081 }
1082
1083 const char16_t* start = aAsciiBase64String.BeginReading();
1084 const char16_t* cur = start;
1085 const char16_t* end = aAsciiBase64String.EndReading();
1086 bool hasWhitespace = false;
1087
1088 while (cur < end) {
1089 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1090 hasWhitespace = true;
1091 break;
1092 }
1093 cur++;
1094 }
1095
1096 nsresult rv;
1097
1098 if (hasWhitespace) {
1099 nsString trimmedString;
1100
1101 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1102 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1103 }
1104
1105 trimmedString.Append(start, cur - start);
1106
1107 while (cur < end) {
1108 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1109 trimmedString.Append(*cur);
1110 }
1111 cur++;
1112 }
1113 rv = Base64Decode(trimmedString, aBinaryData);
1114 } else {
1115 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1116 }
1117
1118 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1119 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1120 }
1121 return rv;
1122}
1123
1124bool nsContentUtils::IsAutocompleteEnabled(
1125 mozilla::dom::HTMLInputElement* aInput) {
1126 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"
, 1126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInput" ") ("
"aInput should not be null!" ")"); do { *((volatile int*)__null
) = 1126; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1127
1128 nsAutoString autocomplete;
1129 aInput->GetAutocomplete(autocomplete);
1130
1131 if (autocomplete.IsEmpty()) {
1132 auto* form = aInput->GetForm();
1133 if (!form) {
1134 return true;
1135 }
1136
1137 form->GetAutocomplete(autocomplete);
1138 }
1139
1140 return !autocomplete.EqualsLiteral("off");
1141}
1142
1143nsContentUtils::AutocompleteAttrState
1144nsContentUtils::SerializeAutocompleteAttribute(
1145 const nsAttrValue* aAttr, nsAString& aResult,
1146 AutocompleteAttrState aCachedState) {
1147 if (!aAttr ||
1148 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1149 return aCachedState;
1150 }
1151
1152 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1153 uint32_t atomCount = aAttr->GetAtomCount();
1154 for (uint32_t i = 0; i < atomCount; i++) {
1155 if (i != 0) {
1156 aResult.Append(' ');
1157 }
1158 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1159 }
1160 nsContentUtils::ASCIIToLower(aResult);
1161 return aCachedState;
1162 }
1163
1164 aResult.Truncate();
1165
1166 mozilla::dom::AutocompleteInfo info;
1167 AutocompleteAttrState state =
1168 InternalSerializeAutocompleteAttribute(aAttr, info);
1169 if (state == eAutocompleteAttrState_Valid) {
1170 // Concatenate the info fields.
1171 aResult = info.mSection;
1172
1173 if (!info.mAddressType.IsEmpty()) {
1174 if (!aResult.IsEmpty()) {
1175 aResult += ' ';
1176 }
1177 aResult += info.mAddressType;
1178 }
1179
1180 if (!info.mContactType.IsEmpty()) {
1181 if (!aResult.IsEmpty()) {
1182 aResult += ' ';
1183 }
1184 aResult += info.mContactType;
1185 }
1186
1187 if (!info.mFieldName.IsEmpty()) {
1188 if (!aResult.IsEmpty()) {
1189 aResult += ' ';
1190 }
1191 aResult += info.mFieldName;
1192 }
1193
1194 // The autocomplete attribute value "webauthn" is interpreted as both a
1195 // field name and a credential type. The corresponding IDL-exposed autofill
1196 // value is "webauthn", not "webauthn webauthn".
1197 if (!info.mCredentialType.IsEmpty() &&
1198 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1199 info.mCredentialType.Equals(aResult))) {
1200 if (!aResult.IsEmpty()) {
1201 aResult += ' ';
1202 }
1203 aResult += info.mCredentialType;
1204 }
1205 }
1206
1207 return state;
1208}
1209
1210nsContentUtils::AutocompleteAttrState
1211nsContentUtils::SerializeAutocompleteAttribute(
1212 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1213 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1214 if (!aAttr ||
1215 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1216 return aCachedState;
1217 }
1218
1219 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1220 aGrantAllValidValue);
1221}
1222
1223/**
1224 * Helper to validate the @autocomplete tokens.
1225 *
1226 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1227 */
1228nsContentUtils::AutocompleteAttrState
1229nsContentUtils::InternalSerializeAutocompleteAttribute(
1230 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1231 bool aGrantAllValidValue) {
1232 // No autocomplete attribute so we are done
1233 if (!aAttrVal) {
1234 return eAutocompleteAttrState_Invalid;
1235 }
1236
1237 uint32_t numTokens = aAttrVal->GetAtomCount();
1238 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1239 return eAutocompleteAttrState_Invalid;
1240 }
1241
1242 uint32_t index = numTokens - 1;
1243 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1244 AutocompleteCategory category;
1245 nsAttrValue enumValue;
1246 nsAutoString credentialTypeStr;
1247
1248 bool result = enumValue.ParseEnumValue(
1249 tokenString, kAutocompleteCredentialTypeTable, false);
1250 if (result) {
1251 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1252 return eAutocompleteAttrState_Invalid;
1253 }
1254 enumValue.ToString(credentialTypeStr);
1255 ASCIIToLower(credentialTypeStr);
1256 // category is Credential and the indexth token is "webauthn"
1257 if (index == 0) {
1258 aInfo.mFieldName.Assign(credentialTypeStr);
1259 aInfo.mCredentialType.Assign(credentialTypeStr);
1260 return eAutocompleteAttrState_Valid;
1261 }
1262
1263 --index;
1264 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1265
1266 // Only the Normal and Contact categories are allowed with webauthn
1267 // - disallow Credential
1268 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1269 false)) {
1270 return eAutocompleteAttrState_Invalid;
1271 }
1272 // - disallow Off and Automatic
1273 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1274 false)) {
1275 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1276 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1277 return eAutocompleteAttrState_Invalid;
1278 }
1279 }
1280
1281 // Proceed to process the remaining tokens as if "webauthn" was not present.
1282 // We need to decrement numTokens to enforce the correct per-category limits
1283 // on the maximum number of tokens.
1284 --numTokens;
1285 }
1286
1287 bool unsupported = false;
1288 if (!aGrantAllValidValue) {
1289 unsupported = enumValue.ParseEnumValue(
1290 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1291 if (unsupported) {
1292 return eAutocompleteAttrState_Invalid;
1293 }
1294 }
1295
1296 nsAutoString fieldNameStr;
1297 result =
1298 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1299
1300 if (result) {
1301 // Off/Automatic/Normal categories.
1302 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1303 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1304 if (numTokens > 1) {
1305 return eAutocompleteAttrState_Invalid;
1306 }
1307 enumValue.ToString(fieldNameStr);
1308 ASCIIToLower(fieldNameStr);
1309 aInfo.mFieldName.Assign(fieldNameStr);
1310 aInfo.mCredentialType.Assign(credentialTypeStr);
1311 aInfo.mCanAutomaticallyPersist =
1312 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1313 return eAutocompleteAttrState_Valid;
1314 }
1315
1316 // Only allow on/off if form autofill @autocomplete values aren't enabled
1317 // and it doesn't grant all valid values.
1318 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1319 !aGrantAllValidValue) {
1320 return eAutocompleteAttrState_Invalid;
1321 }
1322
1323 // Normal category
1324 if (numTokens > 3) {
1325 return eAutocompleteAttrState_Invalid;
1326 }
1327 category = eAutocompleteCategory_NORMAL;
1328 } else { // Check if the last token is of the contact category instead.
1329 // Only allow on/off if form autofill @autocomplete values aren't enabled
1330 // and it doesn't grant all valid values.
1331 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1332 !aGrantAllValidValue) {
1333 return eAutocompleteAttrState_Invalid;
1334 }
1335
1336 result = enumValue.ParseEnumValue(
1337 tokenString, kAutocompleteContactFieldNameTable, false);
1338 if (!result || numTokens > 4) {
1339 return eAutocompleteAttrState_Invalid;
1340 }
1341
1342 category = eAutocompleteCategory_CONTACT;
1343 }
1344
1345 enumValue.ToString(fieldNameStr);
1346 ASCIIToLower(fieldNameStr);
1347
1348 aInfo.mFieldName.Assign(fieldNameStr);
1349 aInfo.mCredentialType.Assign(credentialTypeStr);
1350 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1351 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1352
1353 // We are done if this was the only token.
1354 if (numTokens == 1) {
1355 return eAutocompleteAttrState_Valid;
1356 }
1357
1358 --index;
1359 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1360
1361 if (category == eAutocompleteCategory_CONTACT) {
1362 if (!aGrantAllValidValue) {
1363 unsupported = enumValue.ParseEnumValue(
1364 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1365 if (unsupported) {
1366 return eAutocompleteAttrState_Invalid;
1367 }
1368 }
1369
1370 nsAttrValue contactFieldHint;
1371 result = contactFieldHint.ParseEnumValue(
1372 tokenString, kAutocompleteContactFieldHintTable, false);
1373 if (result) {
1374 nsAutoString contactFieldHintString;
1375 contactFieldHint.ToString(contactFieldHintString);
1376 ASCIIToLower(contactFieldHintString);
1377 aInfo.mContactType.Assign(contactFieldHintString);
1378 if (index == 0) {
1379 return eAutocompleteAttrState_Valid;
1380 }
1381 --index;
1382 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1383 }
1384 }
1385
1386 // Check for billing/shipping tokens
1387 nsAttrValue fieldHint;
1388 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1389 false)) {
1390 nsString fieldHintString;
1391 fieldHint.ToString(fieldHintString);
1392 ASCIIToLower(fieldHintString);
1393 aInfo.mAddressType.Assign(fieldHintString);
1394 if (index == 0) {
1395 return eAutocompleteAttrState_Valid;
1396 }
1397 --index;
1398 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1399 }
1400
1401 // Check for section-* token
1402 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1403 if (section.LowerCaseEqualsASCII("section-")) {
1404 ASCIIToLower(tokenString);
1405 aInfo.mSection.Assign(tokenString);
1406 if (index == 0) {
1407 return eAutocompleteAttrState_Valid;
1408 }
1409 }
1410
1411 // Clear the fields as the autocomplete attribute is invalid.
1412 aInfo.mSection.Truncate();
1413 aInfo.mAddressType.Truncate();
1414 aInfo.mContactType.Truncate();
1415 aInfo.mFieldName.Truncate();
1416 aInfo.mCredentialType.Truncate();
1417
1418 return eAutocompleteAttrState_Invalid;
1419}
1420
1421// Parse an integer according to HTML spec
1422template <class CharT>
1423int32_t nsContentUtils::ParseHTMLIntegerImpl(
1424 const CharT* aStart, const CharT* aEnd,
1425 ParseHTMLIntegerResultFlags* aResult) {
1426 int result = eParseHTMLInteger_NoFlags;
1427
1428 const CharT* iter = aStart;
1429
1430 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1431 result |= eParseHTMLInteger_NonStandard;
1432 ++iter;
1433 }
1434
1435 if (iter == aEnd) {
1436 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1437 *aResult = (ParseHTMLIntegerResultFlags)result;
1438 return 0;
1439 }
1440
1441 int sign = 1;
1442 if (*iter == CharT('-')) {
1443 sign = -1;
1444 result |= eParseHTMLInteger_Negative;
1445 ++iter;
1446 } else if (*iter == CharT('+')) {
1447 result |= eParseHTMLInteger_NonStandard;
1448 ++iter;
1449 }
1450
1451 bool foundValue = false;
1452 CheckedInt32 value = 0;
1453
1454 // Check for leading zeros first.
1455 uint64_t leadingZeros = 0;
1456 while (iter != aEnd) {
1457 if (*iter != CharT('0')) {
1458 break;
1459 }
1460
1461 ++leadingZeros;
1462 foundValue = true;
1463 ++iter;
1464 }
1465
1466 while (iter != aEnd) {
1467 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1468 value = (value * 10) + (*iter - CharT('0')) * sign;
1469 ++iter;
1470 if (!value.isValid()) {
1471 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1472 break;
1473 }
1474 foundValue = true;
1475 } else {
1476 break;
1477 }
1478 }
1479
1480 if (!foundValue) {
1481 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1482 }
1483
1484 if (value.isValid() &&
1485 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1486 (sign == -1 && value == 0))) {
1487 result |= eParseHTMLInteger_NonStandard;
1488 }
1489
1490 if (iter != aEnd) {
1491 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1492 }
1493
1494 *aResult = (ParseHTMLIntegerResultFlags)result;
1495 return value.isValid() ? value.value() : 0;
1496}
1497
1498// Parse an integer according to HTML spec
1499int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1500 const char16_t* aEnd,
1501 ParseHTMLIntegerResultFlags* aResult) {
1502 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1503}
1504
1505int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1506 ParseHTMLIntegerResultFlags* aResult) {
1507 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1508}
1509
1510#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
1511 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
1512 ++(iter); \
1513 } \
1514 if ((iter) == (end_iter)) { \
1515 return (end_res); \
1516 }
1517
1518#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
1519 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
1520 *(iter) != '=') { \
1521 ++(iter); \
1522 }
1523
1524bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
1525 nsAtom* aName, nsAString& aValue) {
1526 aValue.Truncate();
1527
1528 const char16_t* start = aSource.get();
1529 const char16_t* end = start + aSource.Length();
1530 const char16_t* iter;
1531
1532 while (start != end) {
1533 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1534 iter = start;
1535 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
1536
1537 if (start == iter) {
1538 return false;
1539 }
1540
1541 // Remember the attr name.
1542 const nsDependentSubstring& attrName = Substring(start, iter);
1543
1544 // Now check whether this is a valid name="value" pair.
1545 start = iter;
1546 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1547 if (*start != '=') {
1548 // No '=', so this is not a name="value" pair. We don't know
1549 // what it is, and we have no way to handle it.
1550 return false;
1551 }
1552
1553 // Have to skip the value.
1554 ++start;
1555 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
1556 char16_t q = *start;
1557 if (q != kQuote && q != kApostrophe) {
1558 // Not a valid quoted value, so bail.
1559 return false;
1560 }
1561
1562 ++start; // Point to the first char of the value.
1563 iter = start;
1564
1565 while (iter != end && *iter != q) {
1566 ++iter;
1567 }
1568
1569 if (iter == end) {
1570 // Oops, unterminated quoted string.
1571 return false;
1572 }
1573
1574 // At this point attrName holds the name of the "attribute" and
1575 // the value is between start and iter.
1576
1577 if (aName->Equals(attrName)) {
1578 // We'll accumulate as many characters as possible (until we hit either
1579 // the end of the string or the beginning of an entity). Chunks will be
1580 // delimited by start and chunkEnd.
1581 const char16_t* chunkEnd = start;
1582 while (chunkEnd != iter) {
1583 if (*chunkEnd == kLessThan) {
1584 aValue.Truncate();
1585
1586 return false;
1587 }
1588
1589 if (*chunkEnd == kAmpersand) {
1590 aValue.Append(start, chunkEnd - start);
1591
1592 const char16_t* afterEntity = nullptr;
1593 char16_t result[2];
1594 uint32_t count = MOZ_XMLTranslateEntity(
1595 reinterpret_cast<const char*>(chunkEnd),
1596 reinterpret_cast<const char*>(iter),
1597 reinterpret_cast<const char**>(&afterEntity), result);
1598 if (count == 0) {
1599 aValue.Truncate();
1600
1601 return false;
1602 }
1603
1604 aValue.Append(result, count);
1605
1606 // Advance to after the entity and begin a new chunk.
1607 start = chunkEnd = afterEntity;
1608 } else {
1609 ++chunkEnd;
1610 }
1611 }
1612
1613 // Append remainder.
1614 aValue.Append(start, iter - start);
1615
1616 return true;
1617 }
1618
1619 // Resume scanning after the end of the attribute value (past the quote
1620 // char).
1621 start = iter + 1;
1622 }
1623
1624 return false;
1625}
1626
1627bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
1628 // Create MIME type as "text/" + given input
1629 nsAutoString mimeType(u"text/");
1630 mimeType.Append(aName);
1631
1632 return IsJavascriptMIMEType(mimeType);
1633}
1634
1635void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
1636 nsString& aParams) {
1637 aType.Truncate();
1638 aParams.Truncate();
1639 int32_t semiIndex = aValue.FindChar(char16_t(';'));
1640 if (-1 != semiIndex) {
1641 aType = Substring(aValue, 0, semiIndex);
1642 aParams =
1643 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
1644 aParams.StripWhitespace();
1645 } else {
1646 aType = aValue;
1647 }
1648 aType.StripWhitespace();
1649}
1650
1651/**
1652 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
1653 * directive) and converts it to the set of flags used internally.
1654 *
1655 * @param aSandboxAttr the sandbox attribute
1656 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
1657 * null)
1658 */
1659uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
1660 const nsAttrValue* aSandboxAttr) {
1661 if (!aSandboxAttr) {
1662 return SANDBOXED_NONE;
1663 }
1664
1665 uint32_t out = SANDBOX_ALL_FLAGS;
1666
1667#define SANDBOX_KEYWORD(string, atom, flags) \
1668 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
1669 out &= ~(flags); \
1670 }
1671#include "IframeSandboxKeywordList.h"
1672#undef SANDBOX_KEYWORD
1673
1674 return out;
1675}
1676
1677/**
1678 * A helper function that checks if a string matches a valid sandbox flag.
1679 *
1680 * @param aFlag the potential sandbox flag.
1681 * @return true if the flag is a sandbox flag.
1682 */
1683bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
1684#define SANDBOX_KEYWORD(string, atom, flags) \
1685 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
1686 return true; \
1687 }
1688#include "IframeSandboxKeywordList.h"
1689#undef SANDBOX_KEYWORD
1690 return false;
1691}
1692
1693/**
1694 * A helper function that returns a string attribute corresponding to the
1695 * sandbox flags.
1696 *
1697 * @param aFlags the sandbox flags
1698 * @param aString the attribute corresponding to the flags (null if aFlags
1699 * is zero)
1700 */
1701void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
1702 if (!aFlags) {
1703 SetDOMStringToNull(aString);
1704 return;
1705 }
1706
1707 aString.Truncate();
1708
1709#define SANDBOX_KEYWORD(string, atom, flags) \
1710 if (!(aFlags & (flags))) { \
1711 if (!aString.IsEmpty()) { \
1712 aString.AppendLiteral(u" "); \
1713 } \
1714 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
1715 }
1716#include "IframeSandboxKeywordList.h"
1717#undef SANDBOX_KEYWORD
1718}
1719
1720nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
1721 if (!sBidiKeyboard) {
1722 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
1723 }
1724 return sBidiKeyboard;
1725}
1726
1727/**
1728 * This is used to determine whether a character is in one of the classes
1729 * which CSS says should be part of the first-letter. Currently, that is
1730 * all punctuation classes (P*). Note that this is a change from CSS2
1731 * which excluded Pc and Pd.
1732 *
1733 * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
1734 * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
1735 * general category [UAX44]) [...]"
1736 */
1737
1738// static
1739bool nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar) {
1740 switch (mozilla::unicode::GetGeneralCategory(aChar)) {
1741 case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
1742 case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */
1743 case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */
1744 case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */
1745 case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
1746 case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */
1747 case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */
1748 return true;
1749 default:
1750 return false;
1751 }
1752}
1753
1754// static
1755bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
1756 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1757
1758 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
1759}
1760
1761// static
1762bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
1763 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1764
1765 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
1766 cat == nsUGenCategory::kSymbol;
1767}
1768
1769// static
1770bool nsContentUtils::IsHyphen(uint32_t aChar) {
1771 // Characters treated as hyphens for the purpose of "emergency" breaking
1772 // when the content would otherwise overflow.
1773 return aChar == uint32_t('-') || // HYPHEN-MINUS
1774 aChar == 0x2010 || // HYPHEN
1775 aChar == 0x2012 || // FIGURE DASH
1776 aChar == 0x2013 || // EN DASH
1777 aChar == 0x058A; // ARMENIAN HYPHEN
1778}
1779
1780/* static */
1781bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
1782 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
1783 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
1784 aChar == char16_t(0x0020);
1785}
1786
1787/* static */
1788bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
1789 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
1790}
1791
1792/* static */
1793bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
1794 return aContent->IsAnyOfHTMLElements(
1795 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
1796 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
1797 nsGkAtoms::dl, // XXX why not dt and dd?
1798 nsGkAtoms::fieldset,
1799 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
1800 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
1801 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
1802 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
1803 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
1804 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
1805 nsGkAtoms::ul, nsGkAtoms::xmp);
1806}
1807
1808/* static */
1809bool nsContentUtils::ParseIntMarginValue(const nsAString& aString,
1810 nsIntMargin& result) {
1811 nsAutoString marginStr(aString);
1812 marginStr.CompressWhitespace(true, true);
1813 if (marginStr.IsEmpty()) {
1814 return false;
1815 }
1816
1817 int32_t start = 0, end = 0;
1818 for (int count = 0; count < 4; count++) {
1819 if ((uint32_t)end >= marginStr.Length()) return false;
1820
1821 // top, right, bottom, left
1822 if (count < 3)
1823 end = Substring(marginStr, start).FindChar(',');
1824 else
1825 end = Substring(marginStr, start).Length();
1826
1827 if (end <= 0) return false;
1828
1829 nsresult ec;
1830 int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec);
1831 if (NS_FAILED(ec)((bool)(__builtin_expect(!!(NS_FAILED_impl(ec)), 0)))) return false;
1832
1833 switch (count) {
1834 case 0:
1835 result.top = val;
1836 break;
1837 case 1:
1838 result.right = val;
1839 break;
1840 case 2:
1841 result.bottom = val;
1842 break;
1843 case 3:
1844 result.left = val;
1845 break;
1846 }
1847 start += end + 1;
1848 }
1849 return true;
1850}
1851
1852// static
1853int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
1854 nsAString::const_iterator iter, end;
1855 aValue.BeginReading(iter);
1856 aValue.EndReading(end);
1857
1858 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
1859 ++iter;
1860 }
1861
1862 if (iter == end) {
1863 return 0;
1864 }
1865
1866 bool relative = false;
1867 bool negate = false;
1868 if (*iter == char16_t('-')) {
1869 relative = true;
1870 negate = true;
1871 ++iter;
1872 } else if (*iter == char16_t('+')) {
1873 relative = true;
1874 ++iter;
1875 }
1876
1877 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
1878 return 0;
1879 }
1880
1881 // We don't have to worry about overflow, since we can bail out as soon as
1882 // we're bigger than 7.
1883 int32_t value = 0;
1884 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
1885 value = 10 * value + (*iter - char16_t('0'));
1886 if (value >= 7) {
1887 break;
1888 }
1889 ++iter;
1890 }
1891
1892 if (relative) {
1893 if (negate) {
1894 value = 3 - value;
1895 } else {
1896 value = 3 + value;
1897 }
1898 }
1899
1900 return clamped(value, 1, 7);
1901}
1902
1903/* static */
1904void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
1905 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"
, 1905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1905; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1906 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"
, 1906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 1906; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1907 *aURI = nullptr;
1908
1909 if (aDocument->GetController().isSome()) {
1910 return;
1911 }
1912
1913 Element* docElement = aDocument->GetRootElement();
1914 if (!docElement) {
1915 return;
1916 }
1917
1918 nsAutoString manifestSpec;
1919 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
1920
1921 // Manifest URIs can't have fragment identifiers.
1922 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
1923 return;
1924 }
1925
1926 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
1927 aDocument->GetDocBaseURI());
1928}
1929
1930/* static */
1931bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
1932
1933/* static */
1934bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
1935 return false;
1936}
1937// Static
1938bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
1939 if (!aURI) {
1940 return false;
1941 }
1942
1943 if (!aURI->SchemeIs("about")) {
1944 return false;
1945 }
1946
1947 nsAutoCString name;
1948 nsresult rv = NS_GetAboutModuleName(aURI, name);
1949 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"
, 1949); return false; } } while (false)
;
1950
1951 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
1952 name.EqualsLiteral("blocked");
1953}
1954
1955// static
1956void nsContentUtils::Shutdown() {
1957 sInitialized = false;
1958
1959 nsHTMLTags::ReleaseTable();
1960
1961 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
1962 sTriedToGetContentPolicy = false;
1963 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
1964 bundle = nullptr;
1965 }
1966
1967 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
1968 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
1969 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
1970 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
1971 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
1972 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
1973
1974 sBidiKeyboard = nullptr;
1975
1976 delete sAtomEventTable;
1977 sAtomEventTable = nullptr;
1978 delete sStringEventTable;
1979 sStringEventTable = nullptr;
1980 delete sUserDefinedEvents;
1981 sUserDefinedEvents = nullptr;
1982
1983 if (sEventListenerManagersHash) {
1984 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"
, 1985); MOZ_PretendNoReturn(); } } while (0)
1985 "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"
, 1985); MOZ_PretendNoReturn(); } } while (0)
;
1986
1987 // See comment above.
1988
1989 // However, we have to handle this table differently. If it still
1990 // has entries, we want to leak it too, so that we can keep it alive
1991 // in case any elements are destroyed. Because if they are, we need
1992 // their event listener managers to be destroyed too, or otherwise
1993 // it could leave dangling references in DOMClassInfo's preserved
1994 // wrapper table.
1995
1996 if (sEventListenerManagersHash->EntryCount() == 0) {
1997 delete sEventListenerManagersHash;
1998 sEventListenerManagersHash = nullptr;
1999 }
2000 }
2001
2002 if (sDOMArenaHashtable) {
2003 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"
, 2003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0"
")"); do { *((volatile int*)__null) = 2003; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2004 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"
, 2004); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 2004; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2005 delete sDOMArenaHashtable;
2006 sDOMArenaHashtable = nullptr;
2007 }
2008
2009 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"
, 2010); MOZ_PretendNoReturn(); } } while (0)
2010 "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"
, 2010); MOZ_PretendNoReturn(); } } while (0)
;
2011 delete sBlockedScriptRunners;
2012 sBlockedScriptRunners = nullptr;
2013
2014 delete sShiftText;
2015 sShiftText = nullptr;
2016 delete sControlText;
2017 sControlText = nullptr;
2018 delete sCommandOrWinText;
2019 sCommandOrWinText = nullptr;
2020 delete sAltText;
2021 sAltText = nullptr;
2022 delete sModifierSeparator;
2023 sModifierSeparator = nullptr;
2024
2025 delete sJSScriptBytecodeMimeType;
2026 sJSScriptBytecodeMimeType = nullptr;
2027
2028 delete sJSModuleBytecodeMimeType;
2029 sJSModuleBytecodeMimeType = nullptr;
2030
2031 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2032
2033 if (sUserInteractionObserver) {
2034 sUserInteractionObserver->Shutdown();
2035 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2036 }
2037
2038 for (const auto& pref : kRfpPrefs) {
2039 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2040 }
2041
2042 TextControlState::Shutdown();
2043}
2044
2045/**
2046 * Checks whether two nodes come from the same origin. aTrustedNode is
2047 * considered 'safe' in that a user can operate on it.
2048 */
2049// static
2050nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2051 const nsINode* unTrustedNode) {
2052 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"
, 2052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { *((volatile int*)__null) = 2052; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2053 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"
, 2053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "unTrustedNode"
")"); do { *((volatile int*)__null) = 2053; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2054
2055 /*
2056 * Get hold of each node's principal
2057 */
2058
2059 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2060 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2061
2062 if (trustedPrincipal == unTrustedPrincipal) {
2063 return NS_OK;
2064 }
2065
2066 bool equal;
2067 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2068 // a separate method for that, with callers using one or the other?
2069 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2070 !equal) {
2071 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2072 }
2073
2074 return NS_OK;
2075}
2076
2077// static
2078bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2079 nsIPrincipal* aPrincipal) {
2080 bool subsumes;
2081 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2082 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"
, 2082); return false; } } while (false)
;
2083
2084 if (subsumes) {
2085 return true;
2086 }
2087
2088 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2089 // is chrome.
2090 return IsCallerChrome();
2091}
2092
2093// static
2094bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2095 nsIPrincipal* subject = SubjectPrincipal();
2096 if (subject->IsSystemPrincipal()) {
2097 return true;
2098 }
2099
2100 if (aNode->ChromeOnlyAccess()) {
2101 return false;
2102 }
2103
2104 return CanCallerAccess(subject, aNode->NodePrincipal());
2105}
2106
2107// static
2108bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2109 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2110 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"
, 2110); return false; } } while (false)
;
2111
2112 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2113}
2114
2115// static
2116bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2117 const nsAtom* aPerm) {
2118 // Chrome gets access by default.
2119 if (aPrincipal.IsSystemPrincipal()) {
2120 return true;
2121 }
2122
2123 // Otherwise, only allow if caller is an addon with the permission.
2124 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2125}
2126
2127// static
2128bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2129 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2130}
2131
2132// static
2133nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2134 nsIContent* aContent, const nsAString& aAttrValue,
2135 nsIPrincipal* aSubjectPrincipal) {
2136 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2137
2138 // If the subject principal is the same as the content principal, or no
2139 // explicit subject principal was provided, we don't need to do any further
2140 // checks. Just return the content principal.
2141 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2142 return contentPrin;
2143 }
2144
2145 // Only use the subject principal if the URL string we are going to end up
2146 // fetching is under the control of that principal, which is never the case
2147 // for relative URLs.
2148 if (aAttrValue.IsEmpty() ||
2149 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2150 return contentPrin;
2151 }
2152
2153 // Only use the subject principal as the attr triggering principal if it
2154 // should override the CSP of the node's principal.
2155 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2156 return aSubjectPrincipal;
2157 }
2158
2159 return contentPrin;
2160}
2161
2162// static
2163bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2164 nsAutoCString scheme;
2165 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2166 // If we can't extract a scheme, it's not an absolute URL.
2167 return false;
2168 }
2169
2170 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2171 // so no need to check with the IO service.
2172 if (net_IsAbsoluteURL(aURL)) {
2173 return true;
2174 }
2175
2176 nsresult rv = NS_OK;
2177 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2178 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"
, 2178); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2178; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2179 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2180 return false;
2181 }
2182
2183 uint32_t flags;
2184 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2185 return flags & nsIProtocolHandler::URI_NORELATIVE;
2186 }
2187
2188 return false;
2189}
2190
2191// static
2192bool nsContentUtils::InProlog(nsINode* aNode) {
2193 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"
, 2193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") ("
"missing node to nsContentUtils::InProlog" ")"); do { *((volatile
int*)__null) = 2193; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2194
2195 nsINode* parent = aNode->GetParentNode();
2196 if (!parent || !parent->IsDocument()) {
2197 return false;
2198 }
2199
2200 const Document* doc = parent->AsDocument();
2201 const nsIContent* root = doc->GetRootElement();
2202 if (!root) {
2203 return true;
2204 }
2205 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2206 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2207 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2208 return *indexOfNode < *indexOfRoot;
2209 }
2210 // XXX Keep the odd traditional behavior for now.
2211 return indexOfNode.isNothing() && indexOfRoot.isSome();
2212}
2213
2214bool nsContentUtils::IsCallerChrome() {
2215 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"
, 2215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2215; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2216 return SubjectPrincipal() == sSystemPrincipal;
2217}
2218
2219#ifdef FUZZING
2220bool nsContentUtils::IsFuzzingEnabled() {
2221 return StaticPrefs::fuzzing_enabled();
2222}
2223#endif
2224
2225/* static */
2226bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2227 JSContext* aCx, JSObject*) {
2228 return ThreadsafeIsSystemCaller(aCx) ||
2229 StaticPrefs::dom_element_transform_getters_enabled();
2230}
2231
2232// Older Should RFP Functions ----------------------------------
2233
2234/* static */
2235bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2236 RFPTarget aTarget) {
2237 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2238}
2239
2240/* static */
2241bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2242 RFPTarget aTarget) {
2243 if (!aGlobalObject) {
2244 return ShouldResistFingerprinting("Null Object", aTarget);
2245 }
2246 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2247}
2248
2249// Newer Should RFP Functions ----------------------------------
2250// Utilities ---------------------------------------------------
2251
2252inline void LogDomainAndPrefList(const char* urlType,
2253 const char* exemptedDomainsPrefName,
2254 nsAutoCString& url, bool isExemptDomain) {
2255 nsAutoCString list;
2256 Preferences::GetCString(exemptedDomainsPrefName, list);
2257 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)
2258 ("%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)
2259 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)
2260 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)
;
2261}
2262
2263inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2264 nsILoadInfo* aLoadInfo) {
2265 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2266 nsresult rv =
2267 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2268 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2269 // The TRRLoadInfo in particular does not implement this method
2270 // In that instance. We will return false and let other code decide if
2271 // we shouldRFP for this connection
2272 return nullptr;
2273 }
2274 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"
, 2274)
) {
2275 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)
2276 ("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)
2277 "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)
;
2278 return nullptr;
2279 }
2280
2281 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"
, 2281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cookieJarSettings"
")"); do { *((volatile int*)__null) = 2281; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2282 return cookieJarSettings.forget();
2283}
2284
2285bool ETPSaysShouldNotResistFingerprinting(nsIChannel* aChannel,
2286 nsILoadInfo* aLoadInfo) {
2287 // A positive return from this function should always be obeyed.
2288 // A negative return means we should keep checking things.
2289
2290 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2291 // We do not want this check to apply to RFP, only to FPP
2292 // There is one problematic combination of prefs; however:
2293 // If RFP is enabled in PBMode only and FPP is enabled globally
2294 // (so, in non-PBM mode) - we need to know if we're in PBMode or not.
2295 // But that's kind of expensive and we'd like to avoid it if we
2296 // don't have to, so special-case that scenario
2297 if (StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly() &&
2298 !StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2299 StaticPrefs::privacy_resistFingerprinting_pbmode_DoNotUseDirectly()) {
2300 if (isPBM) {
2301 // In PBM (where RFP is enabled) do not exempt based on the ETP toggle
2302 return false;
2303 }
2304 } else if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() ||
2305 (isPBM &&
2306 StaticPrefs::
2307 privacy_resistFingerprinting_pbmode_DoNotUseDirectly())) {
2308 // In RFP, never use the ETP toggle to exempt.
2309 // We can safely return false here even if we are not in PBM mode
2310 // and RFP_pbmode is enabled because we will later see that and
2311 // return false from the ShouldRFP function entirely.
2312 return false;
2313 }
2314
2315 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2316 GetCookieJarSettings(aLoadInfo);
2317 if (!cookieJarSettings) {
2318 return false;
2319 }
2320
2321 return ContentBlockingAllowList::Check(cookieJarSettings);
2322}
2323
2324inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2325 nsILoadInfo* aLoadInfo) {
2326 // A positive return from this function should always be obeyed.
2327 // A negative return means we should keep checking things.
2328
2329 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2330 GetCookieJarSettings(aLoadInfo);
2331 if (!cookieJarSettings) {
2332 return false;
2333 }
2334 return cookieJarSettings->GetShouldResistFingerprinting();
2335}
2336
2337inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2338 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2339 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2340 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2341}
2342
2343inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2344 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2345 aPrincipal->SchemeIs("view-source") ||
2346 aPrincipal->SchemeIs("moz-extension")) {
2347 return true;
2348 }
2349
2350 if (!aPrincipal->SchemeIs("about")) {
2351 return false;
2352 }
2353
2354 bool isContentAccessibleAboutURI;
2355 Unused << aPrincipal->IsContentAccessibleAboutURI(
2356 &isContentAccessibleAboutURI);
2357 return !isContentAccessibleAboutURI;
2358}
2359
2360const char* kExemptedDomainsPrefName =
2361 "privacy.resistFingerprinting.exemptedDomains";
2362
2363inline bool PartionKeyIsAlsoExempted(
2364 const mozilla::OriginAttributes& aOriginAttributes) {
2365 // If we've gotten here we have (probably) passed the CookieJarSettings
2366 // check that would tell us that if we _are_ a subdocument, then we are on
2367 // an exempted top-level domain and we should see if we ourselves are
2368 // exempted. But we may have gotten here because we directly called the
2369 // _dangerous function and we haven't done that check, but we _were_
2370 // instatiated from a state where we could have been partitioned.
2371 // So perform this last-ditch check for that scenario.
2372 // We arbitrarily use https as the scheme, but it doesn't matter.
2373 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2374 nsCOMPtr<nsIURI> uri;
2375 if (StaticPrefs::privacy_firstparty_isolate() &&
2376 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2377 rv = NS_NewURI(getter_AddRefs(uri),
2378 u"https://"_ns + aOriginAttributes.mFirstPartyDomain);
2379 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2380 rv = NS_NewURI(getter_AddRefs(uri),
2381 u"https://"_ns + aOriginAttributes.mPartitionKey);
2382 }
2383
2384 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2385 bool isExemptPartitionKey =
2386 nsContentUtils::IsURIInPrefList(uri, kExemptedDomainsPrefName);
2387 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2388 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2389 nsAutoCString url;
2390 uri->GetHost(url);
2391 LogDomainAndPrefList("Partition Key", kExemptedDomainsPrefName, url,
2392 isExemptPartitionKey);
2393 }
2394 return isExemptPartitionKey;
2395 }
2396 return true;
2397}
2398
2399// Functions ---------------------------------------------------
2400
2401/* static */
2402bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2403 RFPTarget aTarget) {
2404 // See comment in header file for information about usage
2405 // We hardcode PBM to true to be the more restrictive option.
2406 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2407}
2408
2409namespace {
2410
2411// This function is only called within this file for Positive Return Checks
2412bool ShouldResistFingerprinting_(const char* aJustification,
2413 bool aIsPrivateMode, RFPTarget aTarget) {
2414 // See comment in header file for information about usage
2415 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2416}
2417
2418} // namespace
2419
2420/* static */
2421bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2422 nsIGlobalObject* aGlobalObject,
2423 RFPTarget aTarget) {
2424 if (aCallerType == CallerType::System) {
2425 return false;
2426 }
2427 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2428}
2429
2430bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2431 RFPTarget aTarget) {
2432 if (!aDocShell) {
2433 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)
2434 ("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)
2435 "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)
;
2436 return ShouldResistFingerprinting("Null Object", aTarget);
2437 }
2438 Document* doc = aDocShell->GetDocument();
2439 if (!doc) {
2440 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)
2441 ("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)
2442 "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)
;
2443 return ShouldResistFingerprinting("Null Object", aTarget);
2444 }
2445 return doc->ShouldResistFingerprinting(aTarget);
2446}
2447
2448/* static */
2449bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2450 RFPTarget aTarget) {
2451 if (!aChannel) {
2452 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)
2453 ("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)
2454 "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)
;
2455 return ShouldResistFingerprinting("Null Object", aTarget);
2456 }
2457
2458 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
2459 if (!loadInfo) {
2460 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)
2461 ("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)
2462 "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)
;
2463 return ShouldResistFingerprinting("Null Object", aTarget);
2464 }
2465
2466 // With this check, we can ensure that the prefs and target say yes, so only
2467 // an exemption would cause us to return false.
2468 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2469 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2470 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)
2471 ("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)
2472 " 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)
2473 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)
;
2474 return false;
2475 }
2476
2477 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
2478 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)
2479 ("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)
2480 " 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)
;
2481 return false;
2482 }
2483
2484 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
2485 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)
2486 ("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)
2487 " 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)
;
2488 return true;
2489 }
2490
2491 // Document types have no loading principal. Subdocument types do have a
2492 // loading principal, but it is the loading principal of the parent
2493 // document; not the subdocument.
2494 auto contentType = loadInfo->GetExternalContentPolicyType();
2495 // Case 1: Document or Subdocument load
2496 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
2497 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2498 nsCOMPtr<nsIURI> channelURI;
2499 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2500 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"
, 2503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2501 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"
, 2503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2502 "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"
, 2503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2503 "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"
, 2503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { *((volatile int*)__null) = 2503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2504 // this check is to ensure that we do not crash in non-debug builds.
2505 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2506 return true;
2507 }
2508
2509#if 0
2510 if (loadInfo->GetExternalContentPolicyType() == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2511 nsCOMPtr<nsIURI> channelURI;
2512 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2513 nsAutoCString channelSpec;
2514 channelURI->GetSpec(channelSpec);
2515
2516 if (!loadInfo->GetLoadingPrincipal()) {
2517 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)
2518 ("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)
2519 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)
;
2520
2521 } else {
2522 nsAutoCString loadingPrincipalSpec;
2523 loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec);
2524
2525 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)
2526 ("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)
2527 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)
;
2528 }
2529 }
2530
2531#endif
2532
2533 return ShouldResistFingerprinting_dangerous(
2534 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
2535 }
2536
2537 // Case 2: Subresource Load
2538 // Because this code is only used for subresource loads, this
2539 // will check the parent's principal
2540 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
2541
2542 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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2543 !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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2544 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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2545 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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { *((volatile int*)__null) = 2545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2546 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
2547 aTarget);
2548}
2549
2550/* static */
2551bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2552 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
2553 const char* aJustification, RFPTarget aTarget) {
2554 // With this check, we can ensure that the prefs and target say yes, so only
2555 // an exemption would cause us to return false.
2556 bool isPBM = aOriginAttributes.mPrivateBrowsingId !=
2557 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
2558 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2559 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
2560 ("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)
2561 " 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)
2562 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)
;
2563 return false;
2564 }
2565
2566 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)
2567 ("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)
2568 " 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)
2569 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)
;
2570
2571 if (!StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() &&
2572 !StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly()) {
2573 // If neither of the 'regular' RFP prefs are set, then one (or both)
2574 // of the PBM-Only prefs are set (or we would have failed the
2575 // Positive return check.) Therefore, if we are not in PBM, return false
2576 if (aOriginAttributes.mPrivateBrowsingId ==
2577 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID) {
2578 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)
2579 ("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)
2580 " 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)
;
2581 return false;
2582 }
2583 }
2584
2585 // Exclude internal schemes and web extensions
2586 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
2587 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)
2588 ("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)
2589 " 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)
;
2590 return false;
2591 }
2592
2593 bool isExemptDomain = false;
2594 nsAutoCString list;
2595 Preferences::GetCString(kExemptedDomainsPrefName, list);
2596 ToLowerCase(list);
2597 isExemptDomain = IsURIInList(aURI, list);
2598
2599 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2600 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2601 nsAutoCString url;
2602 aURI->GetHost(url);
2603 LogDomainAndPrefList("URI", kExemptedDomainsPrefName, url, isExemptDomain);
2604 }
2605
2606 if (isExemptDomain) {
2607 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
2608 }
2609
2610 return !isExemptDomain;
2611}
2612
2613/* static */
2614bool nsContentUtils::ShouldResistFingerprinting_dangerous(
2615 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
2616 if (!aPrincipal) {
2617 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)
2618 ("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)
2619 "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)
;
2620 return ShouldResistFingerprinting("Null object", aTarget);
2621 }
2622
2623 auto originAttributes =
2624 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
2625 // With this check, we can ensure that the prefs and target say yes, so only
2626 // an exemption would cause us to return false.
2627 bool isPBM = originAttributes.mPrivateBrowsingId ==
2628 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
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
2933nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
2934 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>* aAncestorNodes,
2935 nsTArray<Maybe<uint32_t>>* aAncestorOffsets) {
2936 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"
, 2936); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2937
2938 if (!aNode->IsContent()) {
2939 return NS_ERROR_FAILURE;
2940 }
2941 nsIContent* content = aNode->AsContent();
2942
2943 if (!aAncestorNodes->IsEmpty()) {
2944 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"
, 2944)
;
2945 aAncestorNodes->Clear();
2946 }
2947
2948 if (!aAncestorOffsets->IsEmpty()) {
2949 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"
, 2949)
;
2950 aAncestorOffsets->Clear();
2951 }
2952
2953 // insert the node itself
2954 aAncestorNodes->AppendElement(content);
2955 aAncestorOffsets->AppendElement(Some(aOffset));
2956
2957 // insert all the ancestors
2958 nsIContent* child = content;
2959 nsIContent* parent = child->GetParent();
2960 while (parent) {
2961 aAncestorNodes->AppendElement(parent);
2962 aAncestorOffsets->AppendElement(parent->ComputeIndexOf(child));
2963 child = parent;
2964 parent = parent->GetParent();
2965 }
2966
2967 return NS_OK;
2968}
2969
2970template <typename Node, typename GetParentFunc>
2971static Node* GetCommonAncestorInternal(Node* aNode1, Node* aNode2,
2972 GetParentFunc aGetParentFunc) {
2973 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"
, 2973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1 != aNode2"
")"); do { *((volatile int*)__null) = 2973; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2974
2975 // Build the chain of parents
2976 AutoTArray<Node*, 30> parents1, parents2;
2977 do {
2978 parents1.AppendElement(aNode1);
2979 aNode1 = aGetParentFunc(aNode1);
2980 } while (aNode1);
2981 do {
2982 parents2.AppendElement(aNode2);
2983 aNode2 = aGetParentFunc(aNode2);
2984 } while (aNode2);
2985
2986 // Find where the parent chain differs
2987 uint32_t pos1 = parents1.Length();
2988 uint32_t pos2 = parents2.Length();
2989 Node** data1 = parents1.Elements();
2990 Node** data2 = parents2.Elements();
2991 Node* parent = nullptr;
2992 uint32_t len;
2993 for (len = std::min(pos1, pos2); len > 0; --len) {
2994 Node* child1 = data1[--pos1];
2995 Node* child2 = data2[--pos2];
2996 if (child1 != child2) {
2997 break;
2998 }
2999 parent = child1;
3000 }
3001
3002 return parent;
3003}
3004
3005/* static */
3006nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
3007 nsINode* aNode2) {
3008 return GetCommonAncestorInternal(
3009 aNode1, aNode2, [](nsINode* aNode) { return aNode->GetParentNode(); });
3010}
3011
3012/* static */
3013nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3014 nsINode* aNode1, nsINode* aNode2) {
3015 if (aNode1 == aNode2) {
3016 return aNode1;
3017 }
3018
3019 return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
3020 return aNode->GetParentOrShadowHostNode();
3021 });
3022}
3023
3024/* static */
3025nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3026 nsIContent* aContent1, nsIContent* aContent2) {
3027 return GetCommonAncestorInternal(
3028 aContent1, aContent2,
3029 [](nsIContent* aContent) { return aContent->GetFlattenedTreeParent(); });
3030}
3031
3032/* static */
3033nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3034 nsIContent* aContent1, nsIContent* aContent2) {
3035 return GetCommonAncestorInternal(
3036 aContent1, aContent2, [](nsIContent* aContent) {
3037 return aContent->GetFlattenedTreeParentNodeForSelection();
3038 });
3039}
3040
3041/* static */
3042Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3043 Element* aElement1, Element* aElement2) {
3044 return GetCommonAncestorInternal(aElement1, aElement2, [](Element* aElement) {
3045 return aElement->GetFlattenedTreeParentElementForStyle();
3046 });
3047}
3048
3049/* static */
3050bool nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
3051 Maybe<uint32_t>* aNode1Index,
3052 Maybe<uint32_t>* aNode2Index) {
3053 // Note, CompareDocumentPosition takes the latter params in different order.
3054 return (aNode2->CompareDocumentPosition(*aNode1, aNode2Index, aNode1Index) &
3055 (Node_Binding::DOCUMENT_POSITION_PRECEDING |
3056 Node_Binding::DOCUMENT_POSITION_DISCONNECTED)) ==
3057 Node_Binding::DOCUMENT_POSITION_PRECEDING;
3058}
3059
3060/* static */
3061Maybe<int32_t> nsContentUtils::ComparePoints(const nsINode* aParent1,
3062 uint32_t aOffset1,
3063 const nsINode* aParent2,
3064 uint32_t aOffset2,
3065 NodeIndexCache* aIndexCache) {
3066 bool disconnected{false};
3067
3068 const int32_t order = ComparePoints_Deprecated(
3069 aParent1, aOffset1, aParent2, aOffset2, &disconnected, aIndexCache);
3070 if (disconnected) {
3071 return Nothing();
3072 }
3073
3074 return Some(order);
3075}
3076
3077/* static */
3078int32_t nsContentUtils::ComparePoints_Deprecated(
3079 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
3080 uint32_t aOffset2, bool* aDisconnected, NodeIndexCache* aIndexCache) {
3081 if (aParent1 == aParent2) {
3082 return aOffset1 < aOffset2 ? -1 : aOffset1 > aOffset2 ? 1 : 0;
3083 }
3084
3085 AutoTArray<const nsINode*, 32> parents1, parents2;
3086 const nsINode* node1 = aParent1;
3087 const nsINode* node2 = aParent2;
3088 do {
3089 parents1.AppendElement(node1);
3090 node1 = node1->GetParentOrShadowHostNode();
3091 } while (node1);
3092 do {
3093 parents2.AppendElement(node2);
3094 node2 = node2->GetParentOrShadowHostNode();
3095 } while (node2);
3096
3097 uint32_t pos1 = parents1.Length() - 1;
3098 uint32_t pos2 = parents2.Length() - 1;
3099
3100 bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
3101 if (aDisconnected) {
3102 *aDisconnected = disconnected;
3103 }
3104 if (disconnected) {
3105 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"
, 3105); MOZ_PretendNoReturn(); } } while (0)
;
3106 return 1;
3107 }
3108
3109 // Find where the parent chains differ
3110 const nsINode* parent = parents1.ElementAt(pos1);
3111 uint32_t len;
3112 for (len = std::min(pos1, pos2); len > 0; --len) {
3113 const nsINode* child1 = parents1.ElementAt(--pos1);
3114 const nsINode* child2 = parents2.ElementAt(--pos2);
3115 if (child1 != child2) {
3116 if (MOZ_UNLIKELY(child1->IsShadowRoot())(__builtin_expect(!!(child1->IsShadowRoot()), 0))) {
3117 // Shadow roots come before light DOM per
3118 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3119 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"
, 3119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { *((volatile int*)__null
) = 3119; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3120 return -1;
3121 }
3122 if (MOZ_UNLIKELY(child2->IsShadowRoot())(__builtin_expect(!!(child2->IsShadowRoot()), 0))) {
3123 return 1;
3124 }
3125 Maybe<uint32_t> child1Index;
3126 Maybe<uint32_t> child2Index;
3127 if (aIndexCache) {
3128 aIndexCache->ComputeIndicesOf(parent, child1, child2, child1Index,
3129 child2Index);
3130 } else {
3131 child1Index = parent->ComputeIndexOf(child1);
3132 child2Index = parent->ComputeIndexOf(child2);
3133 }
3134 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3135 return *child1Index < *child2Index ? -1 : 1;
3136 }
3137 // XXX Keep the odd traditional behavior for now.
3138 return child1Index.isNothing() && child2Index.isSome() ? -1 : 1;
3139 }
3140 parent = child1;
3141 }
3142
3143 // The parent chains never differed, so one of the nodes is an ancestor of
3144 // the other
3145
3146 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"
, 3147); MOZ_PretendNoReturn(); } } while (0)
3147 "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"
, 3147); MOZ_PretendNoReturn(); } } while (0)
;
3148
3149 if (!pos1) {
3150 const nsINode* child2 = parents2.ElementAt(--pos2);
3151 const Maybe<uint32_t> child2Index =
3152 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child2)
3153 : parent->ComputeIndexOf(child2);
3154 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"
, 3154)), 0))
) {
3155 return 1;
3156 }
3157 return aOffset1 <= *child2Index ? -1 : 1;
3158 }
3159
3160 const nsINode* child1 = parents1.ElementAt(--pos1);
3161 const Maybe<uint32_t> child1Index =
3162 aIndexCache ? aIndexCache->ComputeIndexOf(parent, child1)
3163 : parent->ComputeIndexOf(child1);
3164 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"
, 3164)), 0))
) {
3165 return -1;
3166 }
3167 return *child1Index < aOffset2 ? -1 : 1;
3168}
3169
3170/* static */
3171BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
3172 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
3173 return GetCommonAncestorInternal(
3174 aBrowserParent1, aBrowserParent2, [](BrowserParent* aBrowserParent) {
3175 return aBrowserParent->GetBrowserBridgeParent()
3176 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
3177 : nullptr;
3178 });
3179}
3180
3181/* static */
3182Element* nsContentUtils::GetTargetElement(Document* aDocument,
3183 const nsAString& aAnchorName) {
3184 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"
, 3184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 3184; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3185
3186 if (aAnchorName.IsEmpty()) {
3187 return nullptr;
3188 }
3189 // 1. If there is an element in the document tree that has an ID equal to
3190 // fragment, then return the first such element in tree order.
3191 if (Element* el = aDocument->GetElementById(aAnchorName)) {
3192 return el;
3193 }
3194
3195 // 2. If there is an a element in the document tree that has a name
3196 // attribute whose value is equal to fragment, then return the first such
3197 // element in tree order.
3198 //
3199 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
3200 if (aDocument->IsHTMLDocument()) {
3201 nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName);
3202 // Loop through the named nodes looking for the first anchor
3203 uint32_t length = list->Length();
3204 for (uint32_t i = 0; i < length; i++) {
3205 nsIContent* node = list->Item(i);
3206 if (node->IsHTMLElement(nsGkAtoms::a)) {
3207 return node->AsElement();
3208 }
3209 }
3210 } else {
3211 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
3212 // Get the list of anchor elements
3213 nsCOMPtr<nsINodeList> list =
3214 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
3215 // Loop through the anchors looking for the first one with the given name.
3216 for (uint32_t i = 0; true; i++) {
3217 nsIContent* node = list->Item(i);
3218 if (!node) { // End of list
3219 break;
3220 }
3221
3222 // Compare the name attribute
3223 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
3224 aAnchorName, eCaseMatters)) {
3225 return node->AsElement();
3226 }
3227 }
3228 }
3229
3230 // 3. Return null.
3231 return nullptr;
3232}
3233
3234/* static */
3235template <typename FPT, typename FRT, typename SPT, typename SRT>
3236Maybe<int32_t> nsContentUtils::ComparePoints(
3237 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3238 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary) {
3239 if (!aFirstBoundary.IsSet() || !aSecondBoundary.IsSet()) {
3240 return Nothing{};
3241 }
3242
3243 bool disconnected{false};
3244 const int32_t order =
3245 ComparePoints_Deprecated(aFirstBoundary, aSecondBoundary, &disconnected);
3246
3247 if (disconnected) {
3248 return Nothing{};
3249 }
3250
3251 return Some(order);
3252}
3253
3254/* static */
3255template <typename FPT, typename FRT, typename SPT, typename SRT>
3256int32_t nsContentUtils::ComparePoints_Deprecated(
3257 const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
3258 const RangeBoundaryBase<SPT, SRT>& aSecondBoundary, bool* aDisconnected) {
3259 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"
, 3259)
||
3260 NS_WARN_IF(!aSecondBoundary.IsSet())NS_warn_if_impl(!aSecondBoundary.IsSet(), "!aSecondBoundary.IsSet()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 3260)
) {
3261 return -1;
3262 }
3263 // XXX Re-implement this without calling `Offset()` as far as possible,
3264 // and the other overload should be an alias of this.
3265 return ComparePoints_Deprecated(
3266 aFirstBoundary.Container(),
3267 *aFirstBoundary.Offset(
3268 RangeBoundaryBase<FPT, FRT>::OffsetFilter::kValidOrInvalidOffsets),
3269 aSecondBoundary.Container(),
3270 *aSecondBoundary.Offset(
3271 RangeBoundaryBase<SPT, SRT>::OffsetFilter::kValidOrInvalidOffsets),
3272 aDisconnected);
3273}
3274
3275inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
3276 char16_t ch;
3277 while ((ch = *aSet)) {
3278 if (aChar == char16_t(ch)) {
3279 return true;
3280 }
3281 ++aSet;
3282 }
3283 return false;
3284}
3285
3286/**
3287 * This method strips leading/trailing chars, in given set, from string.
3288 */
3289
3290// static
3291const nsDependentSubstring nsContentUtils::TrimCharsInSet(
3292 const char* aSet, const nsAString& aValue) {
3293 nsAString::const_iterator valueCurrent, valueEnd;
3294
3295 aValue.BeginReading(valueCurrent);
3296 aValue.EndReading(valueEnd);
3297
3298 // Skip characters in the beginning
3299 while (valueCurrent != valueEnd) {
3300 if (!IsCharInSet(aSet, *valueCurrent)) {
3301 break;
3302 }
3303 ++valueCurrent;
3304 }
3305
3306 if (valueCurrent != valueEnd) {
3307 for (;;) {
3308 --valueEnd;
3309 if (!IsCharInSet(aSet, *valueEnd)) {
3310 break;
3311 }
3312 }
3313 ++valueEnd; // Step beyond the last character we want in the value.
3314 }
3315
3316 // valueEnd should point to the char after the last to copy
3317 return Substring(valueCurrent, valueEnd);
3318}
3319
3320/**
3321 * This method strips leading and trailing whitespace from a string.
3322 */
3323
3324// static
3325template <bool IsWhitespace(char16_t)>
3326const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
3327 bool aTrimTrailing) {
3328 nsAString::const_iterator start, end;
3329
3330 aStr.BeginReading(start);
3331 aStr.EndReading(end);
3332
3333 // Skip whitespace characters in the beginning
3334 while (start != end && IsWhitespace(*start)) {
3335 ++start;
3336 }
3337
3338 if (aTrimTrailing) {
3339 // Skip whitespace characters in the end.
3340 while (end != start) {
3341 --end;
3342
3343 if (!IsWhitespace(*end)) {
3344 // Step back to the last non-whitespace character.
3345 ++end;
3346
3347 break;
3348 }
3349 }
3350 }
3351
3352 // Return a substring for the string w/o leading and/or trailing
3353 // whitespace
3354
3355 return Substring(start, end);
3356}
3357
3358// Declaring the templates we are going to use avoid linking issues without
3359// inlining the method. Considering there is not so much spaces checking
3360// methods we can consider this to be better than inlining.
3361template const nsDependentSubstring
3362nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
3363template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3364 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
3365template const nsDependentSubstring nsContentUtils::TrimWhitespace<
3366 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
3367
3368static inline void KeyAppendSep(nsACString& aKey) {
3369 if (!aKey.IsEmpty()) {
3370 aKey.Append('>');
3371 }
3372}
3373
3374static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
3375 KeyAppendSep(aKey);
3376
3377 // Could escape separator here if collisions happen. > is not a legal char
3378 // for a name or type attribute, so we should be safe avoiding that extra
3379 // work.
3380
3381 AppendUTF16toUTF8(aString, aKey);
3382}
3383
3384static inline void KeyAppendString(const nsACString& aString,
3385 nsACString& aKey) {
3386 KeyAppendSep(aKey);
3387
3388 // Could escape separator here if collisions happen. > is not a legal char
3389 // for a name or type attribute, so we should be safe avoiding that extra
3390 // work.
3391
3392 aKey.Append(aString);
3393}
3394
3395static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
3396 KeyAppendSep(aKey);
3397
3398 aKey.AppendInt(aInt);
3399}
3400
3401static inline bool IsAutocompleteOff(const nsIContent* aContent) {
3402 return aContent->IsElement() &&
3403 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
3404 nsGkAtoms::autocomplete, u"off"_ns,
3405 eIgnoreCase);
3406}
3407
3408/*static*/
3409void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
3410 nsACString& aKey) {
3411 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"
, 3411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 3411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3412
3413 aKey.Truncate();
3414
3415 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
3416
3417 // Don't capture state for anonymous content
3418 if (aContent->IsInNativeAnonymousSubtree()) {
3419 return;
3420 }
3421
3422 if (IsAutocompleteOff(aContent)) {
3423 return;
3424 }
3425
3426 RefPtr<Document> doc = aContent->GetUncomposedDoc();
3427
3428 KeyAppendInt(partID, aKey); // first append a partID
3429 bool generatedUniqueKey = false;
3430
3431 if (doc && doc->IsHTMLOrXHTML()) {
3432 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
3433
3434 // If we have a form control and can calculate form information, use that
3435 // as the key - it is more reliable than just recording position in the
3436 // DOM.
3437 // XXXbz Is it, really? We have bugs on this, I think...
3438 // Important to have a unique key, and tag/type/name may not be.
3439 //
3440 // The format of the key depends on whether the control has a form,
3441 // and whether the element was parser inserted:
3442 //
3443 // [Has Form, Parser Inserted]:
3444 // fp>type>FormNum>IndOfControlInForm>FormName>name
3445 //
3446 // [No Form, Parser Inserted]:
3447 // dp>type>ControlNum>name
3448 //
3449 // [Has Form, Not Parser Inserted]:
3450 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
3451 //
3452 // [No Form, Not Parser Inserted]:
3453 // dn>type>IndOfControlInDoc>name
3454 //
3455 // XXX We don't need to use index if name is there
3456 // XXXbz We don't? Why not? I don't follow.
3457 //
3458 nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
3459 if (control) {
3460 // Get the control number if this was a parser inserted element from the
3461 // network.
3462 int32_t controlNumber =
3463 control->GetParserInsertedControlNumberForStateKey();
3464 bool parserInserted = controlNumber != -1;
3465
3466 RefPtr<nsContentList> htmlForms;
3467 RefPtr<nsContentList> htmlFormControls;
3468 if (!parserInserted) {
3469 // Getting these lists is expensive, as we need to keep them up to date
3470 // as the document loads, so we avoid it if we don't need them.
3471 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
3472 getter_AddRefs(htmlFormControls));
3473 }
3474
3475 // Append the control type
3476 KeyAppendInt(int32_t(control->ControlType()), aKey);
3477
3478 // If in a form, add form name / index of form / index in form
3479 HTMLFormElement* formElement = control->GetForm();
3480 if (formElement) {
3481 if (IsAutocompleteOff(formElement)) {
3482 aKey.Truncate();
3483 return;
3484 }
3485
3486 // Append the form number, if this is a parser inserted control, or
3487 // the index of the form in the document otherwise.
3488 bool appendedForm = false;
3489 if (parserInserted) {
3490 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"
, 3492); 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) = 3492; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3491 "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"
, 3492); 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) = 3492; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3492 "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"
, 3492); 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) = 3492; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3493 KeyAppendString("fp"_ns, aKey);
3494 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
3495 appendedForm = true;
3496 } else {
3497 KeyAppendString("fn"_ns, aKey);
3498 int32_t index = htmlForms->IndexOf(formElement, false);
3499 if (index <= -1) {
3500 //
3501 // XXX HACK this uses some state that was dumped into the document
3502 // specifically to fix bug 138892. What we are trying to do is
3503 // *guess* which form this control's state is found in, with the
3504 // highly likely guess that the highest form parsed so far is the
3505 // one. This code should not be on trunk, only branch.
3506 //
3507 index = htmlDoc->GetNumFormsSynchronous() - 1;
3508 }
3509 if (index > -1) {
3510 KeyAppendInt(index, aKey);
3511 appendedForm = true;
3512 }
3513 }
3514
3515 if (appendedForm) {
3516 // Append the index of the control in the form
3517 int32_t index = formElement->IndexOfContent(aContent);
3518
3519 if (index > -1) {
3520 KeyAppendInt(index, aKey);
3521 generatedUniqueKey = true;
3522 }
3523 }
3524
3525 // Append the form name
3526 nsAutoString formName;
3527 formElement->GetAttr(nsGkAtoms::name, formName);
3528 KeyAppendString(formName, aKey);
3529 } else {
3530 // Not in a form. Append the control number, if this is a parser
3531 // inserted control, or the index of the control in the document
3532 // otherwise.
3533 if (parserInserted) {
3534 KeyAppendString("dp"_ns, aKey);
3535 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
3536 aKey);
3537 generatedUniqueKey = true;
3538 } else {
3539 KeyAppendString("dn"_ns, aKey);
3540 int32_t index = htmlFormControls->IndexOf(aContent, true);
3541 if (index > -1) {
3542 KeyAppendInt(index, aKey);
3543 generatedUniqueKey = true;
3544 }
3545 }
3546
3547 // Append the control name
3548 nsAutoString name;
3549 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
3550 KeyAppendString(name, aKey);
3551 }
3552 }
3553 }
3554
3555 if (!generatedUniqueKey) {
3556 // Either we didn't have a form control or we aren't in an HTML document so
3557 // we can't figure out form info. Append the tag name if it's an element
3558 // to avoid restoring state for one type of element on another type.
3559 if (aContent->IsElement()) {
3560 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
3561 aKey);
3562 } else {
3563 // Append a character that is not "d" or "f" to disambiguate from
3564 // the case when we were a form control in an HTML document.
3565 KeyAppendString("o"_ns, aKey);
3566 }
3567
3568 // Now start at aContent and append the indices of it and all its ancestors
3569 // in their containers. That should at least pin down its position in the
3570 // DOM...
3571 nsINode* parent = aContent->GetParentNode();
3572 nsINode* content = aContent;
3573 while (parent) {
3574 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
3575 content = parent;
3576 parent = content->GetParentNode();
3577 }
3578 }
3579}
3580
3581// static
3582nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
3583 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"
, 3583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3583; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3584
3585 // As opposed to SubjectPrincipal(), we do in fact assume that
3586 // we're in a realm here; anyone who calls this function in
3587 // situations where that's not the case is doing it wrong.
3588 JS::Realm* realm = js::GetContextRealm(aCx);
3589 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"
, 3589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { *((volatile int*)__null) = 3589; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3590
3591 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3592 return nsJSPrincipals::get(principals);
3593}
3594
3595// static
3596nsIPrincipal* nsContentUtils::SubjectPrincipal() {
3597 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"
, 3597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()"
")"); do { *((volatile int*)__null) = 3597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3598 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"
, 3598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3599 JSContext* cx = GetCurrentJSContext();
3600 if (!cx) {
3601 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"
, 3603); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3603; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3602 "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"
, 3603); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3603; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
3603 "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"
, 3603); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { *((volatile int*)__null) = 3603; __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
3604 }
3605
3606 JS::Realm* realm = js::GetContextRealm(cx);
3607
3608 // When an AutoJSAPI is instantiated, we are in a null realm until the
3609 // first JSAutoRealm, which is kind of a purgatory as far as permissions
3610 // go. It would be nice to just hard-abort if somebody does a security check
3611 // in this purgatory zone, but that would be too fragile, since it could be
3612 // triggered by random IsCallerChrome() checks 20-levels deep.
3613 //
3614 // So we want to return _something_ here - and definitely not the System
3615 // Principal, since that would make an AutoJSAPI a very dangerous thing to
3616 // instantiate.
3617 //
3618 // The natural thing to return is a null principal. Ideally, we'd return a
3619 // different null principal each time, to avoid any unexpected interactions
3620 // when the principal accidentally gets inherited somewhere. But
3621 // SubjectPrincipal doesn't return strong references, so there's no way to
3622 // sanely manage the lifetime of multiple null principals.
3623 //
3624 // So we use a singleton null principal. To avoid it being accidentally
3625 // inherited and becoming a "real" subject or object principal, we do a
3626 // release-mode assert during realm creation against using this principal on
3627 // an actual global.
3628 if (!realm) {
3629 return sNullSubjectPrincipal;
3630 }
3631
3632 return SubjectPrincipal(cx);
3633}
3634
3635// static
3636nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
3637#ifdef DEBUG1
3638 JS::AssertObjectBelongsToCurrentThread(aObj);
3639#endif
3640
3641 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"
, 3641); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { *((volatile int*)__null) = 3641; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3642
3643 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
3644 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
3645 return nsJSPrincipals::get(principals);
3646}
3647
3648// static
3649nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
3650 const nsAString& aSpec,
3651 Document* aDocument,
3652 nsIURI* aBaseURI) {
3653 if (aDocument) {
3654 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
3655 aBaseURI);
3656 }
3657 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
3658}
3659
3660// static
3661bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
3662 // A valid custom element name is a sequence of characters name which
3663 // must match the PotentialCustomElementName production:
3664 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
3665 const char16_t* name = aName->GetUTF16String();
3666 uint32_t len = aName->GetLength();
3667 bool hasDash = false;
3668
3669 if (!len || name[0] < 'a' || name[0] > 'z') {
3670 return false;
3671 }
3672
3673 uint32_t i = 1;
3674 while (i < len) {
3675 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))
) {
3676 // Merged two 16-bit surrogate pairs into code point.
3677 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))
;
3678
3679 if (code < 0x10000 || code > 0xEFFFF) {
3680 return false;
3681 }
3682
3683 i += 2;
3684 } else {
3685 if (name[i] == '-') {
3686 hasDash = true;
3687 }
3688
3689 if (name[i] != '-' && name[i] != '.' && name[i] != '_' &&
3690 name[i] != 0xB7 && (name[i] < '0' || name[i] > '9') &&
3691 (name[i] < 'a' || name[i] > 'z') &&
3692 (name[i] < 0xC0 || name[i] > 0xD6) &&
3693 (name[i] < 0xF8 || name[i] > 0x37D) &&
3694 (name[i] < 0x37F || name[i] > 0x1FFF) &&
3695 (name[i] < 0x200C || name[i] > 0x200D) &&
3696 (name[i] < 0x203F || name[i] > 0x2040) &&
3697 (name[i] < 0x2070 || name[i] > 0x218F) &&
3698 (name[i] < 0x2C00 || name[i] > 0x2FEF) &&
3699 (name[i] < 0x3001 || name[i] > 0xD7FF) &&
3700 (name[i] < 0xF900 || name[i] > 0xFDCF) &&
3701 (name[i] < 0xFDF0 || name[i] > 0xFFFD)) {
3702 return false;
3703 }
3704
3705 i++;
3706 }
3707 }
3708
3709 return hasDash;
3710}
3711
3712// static
3713bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
3714 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
3715 if (aNameSpaceID == kNameSpaceID_XUL8) {
3716 return true;
3717 }
3718
3719 bool hasDash = IsNameWithDash(aName);
3720 if (!hasDash) {
3721 return false;
3722 }
3723
3724 // The custom element name must not be one of the following values:
3725 // annotation-xml
3726 // color-profile
3727 // font-face
3728 // font-face-src
3729 // font-face-uri
3730 // font-face-format
3731 // font-face-name
3732 // missing-glyph
3733 return aName != nsGkAtoms::annotation_xml_ &&
3734 aName != nsGkAtoms::colorProfile && aName != nsGkAtoms::font_face &&
3735 aName != nsGkAtoms::font_face_src &&
3736 aName != nsGkAtoms::font_face_uri &&
3737 aName != nsGkAtoms::font_face_format &&
3738 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
3739}
3740
3741// static
3742nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
3743 bool aNamespaceAware,
3744 const char16_t** aColon) {
3745 const char* colon = nullptr;
3746 const char16_t* begin = aQualifiedName.BeginReading();
3747 const char16_t* end = aQualifiedName.EndReading();
3748
3749 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
3750 reinterpret_cast<const char*>(end),
3751 aNamespaceAware, &colon);
3752
3753 if (!result) {
3754 if (aColon) {
3755 *aColon = reinterpret_cast<const char16_t*>(colon);
3756 }
3757
3758 return NS_OK;
3759 }
3760
3761 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
3762}
3763
3764// static
3765nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
3766 const nsString& aQName, int32_t* aNamespace,
3767 nsAtom** aLocalName) {
3768 const char16_t* colon;
3769 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
3770 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"
, 3770); return rv; } } while (false)
;
3771
3772 if (colon) {
3773 const char16_t* end;
3774 aQName.EndReading(end);
3775 nsAutoString nameSpace;
3776 rv = aNamespaceResolver->LookupNamespaceURIInternal(
3777 Substring(aQName.get(), colon), nameSpace);
3778 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"
, 3778); return rv; } } while (false)
;
3779
3780 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
3781 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
3782 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
3783
3784 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
3785 } else {
3786 *aNamespace = kNameSpaceID_None;
3787 *aLocalName = NS_AtomizeMainThread(aQName).take();
3788 }
3789 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"
, 3789); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3790 return NS_OK;
3791}
3792
3793// static
3794nsresult nsContentUtils::GetNodeInfoFromQName(
3795 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
3796 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
3797 mozilla::dom::NodeInfo** aNodeInfo) {
3798 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
3799 const char16_t* colon;
3800 nsresult rv = nsContentUtils::CheckQName(qName, true, &colon);
3801 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"
, 3801); return rv; } } while (false)
;
3802
3803 int32_t nsID;
3804 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
3805 if (colon) {
3806 const char16_t* end;
3807 qName.EndReading(end);
3808
3809 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
3810
3811 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix, nsID,
3812 aNodeType, aNodeInfo);
3813 } else {
3814 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
3815 aNodeInfo);
3816 }
3817 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"
, 3817); return rv; } } while (false)
;
3818
3819 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
3820 (*aNodeInfo)->GetPrefixAtom(),
3821 (*aNodeInfo)->NamespaceID())
3822 ? NS_OK
3823 : NS_ERROR_DOM_NAMESPACE_ERR;
3824}
3825
3826// static
3827void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
3828 nsAtom** aPrefix, nsAtom** aLocalName,
3829 int32_t* aNameSpaceID) {
3830 /**
3831 * Expat can send the following:
3832 * localName
3833 * namespaceURI<separator>localName
3834 * namespaceURI<separator>localName<separator>prefix
3835 *
3836 * and we use 0xFFFF for the <separator>.
3837 *
3838 */
3839
3840 const char16_t* uriEnd = nullptr;
3841 const char16_t* nameEnd = nullptr;
3842 const char16_t* pos;
3843 for (pos = aExpatName; *pos; ++pos) {
3844 if (*pos == 0xFFFF) {
3845 if (uriEnd) {
3846 nameEnd = pos;
3847 } else {
3848 uriEnd = pos;
3849 }
3850 }
3851 }
3852
3853 const char16_t* nameStart;
3854 if (uriEnd) {
3855 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
3856 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
3857
3858 nameStart = (uriEnd + 1);
3859 if (nameEnd) {
3860 const char16_t* prefixStart = nameEnd + 1;
3861 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
3862 } else {
3863 nameEnd = pos;
3864 *aPrefix = nullptr;
3865 }
3866 } else {
3867 *aNameSpaceID = kNameSpaceID_None;
3868 nameStart = aExpatName;
3869 nameEnd = pos;
3870 *aPrefix = nullptr;
3871 }
3872 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
3873}
3874
3875// static
3876PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
3877 Document* doc = aContent->GetComposedDoc();
3878 if (!doc) {
3879 return nullptr;
3880 }
3881 return doc->GetPresShell();
3882}
3883
3884// static
3885nsPresContext* nsContentUtils::GetContextForContent(
3886 const nsIContent* aContent) {
3887 PresShell* presShell = GetPresShellForContent(aContent);
3888 if (!presShell) {
3889 return nullptr;
3890 }
3891 return presShell->GetPresContext();
3892}
3893
3894// static
3895bool nsContentUtils::CanLoadImage(nsIURI* aURI, nsINode* aNode,
3896 Document* aLoadingDocument,
3897 nsIPrincipal* aLoadingPrincipal) {
3898 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"
, 3898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI" ")"); do { *((volatile int*)__null) = 3898
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3899 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"
, 3899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { *((volatile int*)__null
) = 3899; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3900 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"
, 3900); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a loading principal" ")"); do { *((volatile
int*)__null) = 3900; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3901
3902 nsresult rv;
3903
3904 auto appType = nsIDocShell::APP_TYPE_UNKNOWN;
3905
3906 {
3907 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
3908 aLoadingDocument->GetDocShell();
3909 if (docShellTreeItem) {
3910 nsCOMPtr<nsIDocShellTreeItem> root;
3911 docShellTreeItem->GetInProcessRootTreeItem(getter_AddRefs(root));
3912
3913 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
3914
3915 if (docShell) {
3916 appType = docShell->GetAppType();
3917 }
3918 }
3919 }
3920
3921 if (appType != nsIDocShell::APP_TYPE_EDITOR) {
3922 // Editor apps get special treatment here, editors can load images
3923 // from anywhere. This allows editor to insert images from file://
3924 // into documents that are being edited.
3925 rv = sSecurityManager->CheckLoadURIWithPrincipal(
3926 aLoadingPrincipal, aURI, nsIScriptSecurityManager::ALLOW_CHROME,
3927 aLoadingDocument->InnerWindowID());
3928 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3929 return false;
3930 }
3931 }
3932
3933 nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new mozilla::net::LoadInfo(
3934 aLoadingPrincipal,
3935 aLoadingPrincipal, // triggering principal
3936 aNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
3937 nsIContentPolicy::TYPE_INTERNAL_IMAGE);
3938
3939 int16_t decision = nsIContentPolicy::ACCEPT;
3940
3941 rv = NS_CheckContentLoadPolicy(aURI, secCheckLoadInfo, &decision,
3942 GetContentPolicy());
3943
3944 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && NS_CP_ACCEPTED(decision)((decision) == nsIContentPolicy::ACCEPT);
3945}
3946
3947// static
3948bool nsContentUtils::IsInPrivateBrowsing(const Document* aDoc) {
3949 if (!aDoc) {
3950 return false;
3951 }
3952
3953 nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
3954 // See duplicated code below in IsInPrivateBrowsing(nsILoadGroup*)
3955 // and Document::Reset/ResetToURI
3956 if (loadGroup) {
3957 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3958 loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3959 if (callbacks) {
3960 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
3961 if (loadContext) {
3962 return loadContext->UsePrivateBrowsing();
3963 }
3964 }
3965 }
3966
3967 nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
3968 return channel && NS_UsePrivateBrowsing(channel);
3969}
3970
3971// static
3972bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
3973 if (!aLoadGroup) {
3974 return false;
3975 }
3976 bool isPrivate = false;
3977 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3978 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3979 if (callbacks) {
3980 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
3981 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
3982 }
3983 return isPrivate;
3984}
3985
3986// FIXME(emilio): This is (effectively) almost but not quite the same as
3987// Document::ShouldLoadImages(), which one is right?
3988bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
3989 if (!aDocument) {
3990 return false;
3991 }
3992 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
3993 aDocument->IsStaticDocument()) {
3994 return false;
3995 }
3996 nsCOMPtr<nsPIDOMWindowInner> win =
3997 do_QueryInterface(aDocument->GetScopeObject());
3998 return !win || !win->GetDocShell();
3999}
4000
4001imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
4002 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"
, 4002); return nullptr; } } while (false)
;
4003
4004 if (!aDoc) {
4005 return imgLoader::NormalLoader();
4006 }
4007 bool isPrivate = IsInPrivateBrowsing(aDoc);
4008 return isPrivate ? imgLoader::PrivateBrowsingLoader()
4009 : imgLoader::NormalLoader();
4010}
4011
4012// static
4013imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
4014 Document* aContext) {
4015 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"
, 4015); return nullptr; } } while (false)
;
4016
4017 if (!aChannel) {
4018 return imgLoader::NormalLoader();
4019 }
4020 nsCOMPtr<nsILoadContext> context;
4021 NS_QueryNotificationCallbacks(aChannel, context);
4022 return context && context->UsePrivateBrowsing()
4023 ? imgLoader::PrivateBrowsingLoader()
4024 : imgLoader::NormalLoader();
4025}
4026
4027// static
4028int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
4029 switch (aMode) {
4030 case CORS_ANONYMOUS:
4031 return imgILoader::LOAD_CORS_ANONYMOUS;
4032 case CORS_USE_CREDENTIALS:
4033 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
4034 default:
4035 return 0;
4036 }
4037}
4038
4039// static
4040nsresult nsContentUtils::LoadImage(
4041 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
4042 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
4043 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
4044 int32_t aLoadFlags, const nsAString& initiatorType,
4045 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
4046 bool aUseUrgentStartForChannel, bool aLinkPreload,
4047 uint64_t aEarlyHintPreloaderId,
4048 mozilla::dom::FetchPriority aFetchPriority) {
4049 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"
, 4049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI" ")"); do { *((volatile int*)__null) = 4049
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4050 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"
, 4050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") ("
"Must have a context" ")"); do { *((volatile int*)__null) = 4050
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4051 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"
, 4051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { *((volatile int*)__null
) = 4051; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4052 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"
, 4052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { *((volatile int*)__null
) = 4052; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4053 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"
, 4053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") ("
"Null out param" ")"); do { *((volatile int*)__null) = 4053;
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
4054
4055 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
4056 if (!imgLoader) {
4057 // nothing we can do here
4058 return NS_ERROR_FAILURE;
4059 }
4060
4061 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
4062
4063 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
4064
4065 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"
, 4066); MOZ_PretendNoReturn(); } } while (0)
4066 "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"
, 4066); MOZ_PretendNoReturn(); } } while (0)
;
4067
4068 // XXXbz using "documentURI" for the initialDocumentURI is not quite
4069 // right, but the best we can do here...
4070 return imgLoader->LoadImage(aURI, /* uri to load */
4071 documentURI, /* initialDocumentURI */
4072 aReferrerInfo, /* referrerInfo */
4073 aLoadingPrincipal, /* loading principal */
4074 aRequestContextID, /* request context ID */
4075 loadGroup, /* loadgroup */
4076 aObserver, /* imgINotificationObserver */
4077 aContext, /* loading context */
4078 aLoadingDocument, /* uniquification key */
4079 aLoadFlags, /* load flags */
4080 nullptr, /* cache key */
4081 aContentPolicyType, /* content policy type */
4082 initiatorType, /* the load initiator */
4083 aUseUrgentStartForChannel, /* urgent-start flag */
4084 aLinkPreload, /* <link preload> initiator */
4085 aEarlyHintPreloaderId, aFetchPriority, aRequest);
4086}
4087
4088// static
4089already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
4090 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
4091 if (aRequest) {
4092 *aRequest = nullptr;
4093 }
4094
4095 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"
, 4095); return nullptr; } } while (false)
;
4096
4097 nsCOMPtr<imgIRequest> imgRequest;
4098 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4099 getter_AddRefs(imgRequest));
4100 if (!imgRequest) {
4101 return nullptr;
4102 }
4103
4104 nsCOMPtr<imgIContainer> imgContainer;
4105 imgRequest->GetImage(getter_AddRefs(imgContainer));
4106
4107 if (!imgContainer) {
4108 return nullptr;
4109 }
4110
4111 if (aRequest) {
4112 // If the consumer wants the request, verify it has actually loaded
4113 // successfully.
4114 uint32_t imgStatus;
4115 imgRequest->GetImageStatus(&imgStatus);
4116 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
4117 !(imgStatus & imgIRequest::STATUS_ERROR)) {
4118 imgRequest.swap(*aRequest);
4119 }
4120 }
4121
4122 return imgContainer.forget();
4123}
4124
4125static bool IsLinkWithURI(const nsIContent& aContent) {
4126 const auto* element = Element::FromNode(aContent);
4127 if (!element || !element->IsLink()) {
4128 return false;
4129 }
4130 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
4131 return !!absURI;
4132}
4133
4134static bool HasImageRequest(nsIContent& aContent) {
4135 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
4136 if (!imageContent) {
4137 return false;
4138 }
4139
4140 nsCOMPtr<imgIRequest> imgRequest;
4141 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
4142 getter_AddRefs(imgRequest));
4143
4144 // XXXbz It may be draggable even if the request resulted in an error. Why?
4145 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
4146 return !!imgRequest;
4147}
4148
4149static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
4150 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
4151 if (el->Draggable()) {
4152 return Some(true);
4153 }
4154
4155 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
4156 nsGkAtoms::_false, eIgnoreCase)) {
4157 return Some(false);
4158 }
4159 }
4160 if (aContent.IsSVGElement()) {
4161 return Some(false);
4162 }
4163 return Nothing();
4164}
4165
4166// static
4167bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
4168 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"
, 4168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4169
4170 if (auto draggable = DraggableOverride(*aContent)) {
4171 return *draggable;
4172 }
4173
4174 // special handling for content area image and link dragging
4175 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
4176}
4177
4178// static
4179bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
4180 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"
, 4180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4180; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4181 return HasImageRequest(*aContent) &&
4182 DraggableOverride(*aContent).valueOr(true);
4183}
4184
4185// static
4186bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
4187 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"
, 4187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 4187; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4188 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
4189}
4190
4191// static
4192nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
4193 nsAtom* aName,
4194 mozilla::dom::NodeInfo** aResult) {
4195 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
4196
4197 *aResult = niMgr
4198 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
4199 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
4200 .take();
4201 return NS_OK;
4202}
4203
4204static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
4205 uint32_t aPerm, bool aExactHostMatch) {
4206 if (!aPrincipal) {
4207 // We always deny (i.e. don't allow) the permission if we don't have a
4208 // principal.
4209 return aPerm != nsIPermissionManager::ALLOW_ACTION;
4210 }
4211
4212 nsCOMPtr<nsIPermissionManager> permMgr =
4213 components::PermissionManager::Service();
4214 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"
, 4214); return false; } } while (false)
;
4215
4216 uint32_t perm;
4217 nsresult rv;
4218 if (aExactHostMatch) {
4219 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
4220 } else {
4221 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4222 }
4223 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"
, 4223); return false; } } while (false)
;
4224
4225 return perm == aPerm;
4226}
4227
4228bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
4229 const nsACString& aType) {
4230 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4231 false);
4232}
4233
4234bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
4235 const nsACString& aType) {
4236 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4237 false);
4238}
4239
4240bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
4241 const nsACString& aType) {
4242 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
4243 true);
4244}
4245
4246bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
4247 const nsACString& aType) {
4248 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
4249 true);
4250}
4251
4252bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
4253 const nsACString& aType) {
4254 if (!aPrincipal) {
4255 return false;
4256 }
4257
4258 nsCOMPtr<nsIPermissionManager> permMgr =
4259 components::PermissionManager::Service();
4260 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"
, 4260); return false; } } while (false)
;
4261
4262 uint32_t perm;
4263 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
4264 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"
, 4264); return false; } } while (false)
;
4265
4266 return perm != nsIPermissionManager::UNKNOWN_ACTION;
4267}
4268
4269static const char* gEventNames[] = {"event"};
4270static const char* gSVGEventNames[] = {"evt"};
4271// for b/w compat, the first name to onerror is still 'event', even though it
4272// is actually the error message
4273static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
4274 "error"};
4275
4276// static
4277void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
4278 bool aIsForWindow, uint32_t* aArgCount,
4279 const char*** aArgArray) {
4280#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
4281 *aArgCount = sizeof(names) / sizeof(names[0]); \
4282 *aArgArray = names;
4283
4284 // JSEventHandler is what does the arg magic for onerror, and it does
4285 // not seem to take the namespace into account. So we let onerror in all
4286 // namespaces get the 3 arg names.
4287 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
4288 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
4289 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
4290 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
4291 } else {
4292 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
4293 }
4294}
4295
4296// Note: The list of content bundles in nsStringBundle.cpp should be updated
4297// whenever entries are added or removed from this list.
4298static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = {
4299 // Must line up with the enum values in |PropertiesFile| enum.
4300 "chrome://global/locale/css.properties",
4301 "chrome://global/locale/xul.properties",
4302 "chrome://global/locale/layout_errors.properties",
4303 "chrome://global/locale/layout/HtmlForm.properties",
4304 "chrome://global/locale/printing.properties",
4305 "chrome://global/locale/dom/dom.properties",
4306 "chrome://global/locale/layout/htmlparser.properties",
4307 "chrome://global/locale/svg/svg.properties",
4308 "chrome://branding/locale/brand.properties",
4309 "chrome://global/locale/commonDialogs.properties",
4310 "chrome://global/locale/mathml/mathml.properties",
4311 "chrome://global/locale/security/security.properties",
4312 "chrome://necko/locale/necko.properties",
4313 "resource://gre/res/locale/layout/HtmlForm.properties",
4314 "resource://gre/res/locale/dom/dom.properties"};
4315
4316/* static */
4317nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
4318 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"
, 4319); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4319; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4319 "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"
, 4319); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
*((volatile int*)__null) = 4319; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4320 if (!sStringBundles[aFile]) {
4321 if (!sStringBundleService) {
4322 nsresult rv =
4323 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
4324 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"
, 4324); return rv; } } while (false)
;
4325 }
4326 RefPtr<nsIStringBundle> bundle;
4327 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)
4328 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)
;
4329 sStringBundles[aFile] = bundle.forget();
4330 }
4331 return NS_OK;
4332}
4333
4334/* static */
4335void nsContentUtils::AsyncPrecreateStringBundles() {
4336 // We only ever want to pre-create bundles in the parent process.
4337 //
4338 // All nsContentUtils bundles are shared between the parent and child
4339 // precesses, and the shared memory regions that back them *must* be created
4340 // in the parent, and then sent to all children.
4341 //
4342 // If we attempt to create a bundle in the child before its memory region is
4343 // available, we need to create a temporary non-shared bundle, and later
4344 // replace that with the shared memory copy. So attempting to pre-load in the
4345 // child is wasteful and unnecessary.
4346 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"
, 4346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4346; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4347
4348 for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT;
4349 ++bundleIndex) {
4350 nsresult rv = NS_DispatchToCurrentThreadQueue(
4351 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
4352 [bundleIndex]() {
4353 PropertiesFile file =
4354 static_cast<PropertiesFile>(bundleIndex);
4355 EnsureStringBundle(file);
4356 nsIStringBundle* bundle = sStringBundles[file];
4357 bundle->AsyncPreload();
4358 }),
4359 EventQueuePriority::Idle);
4360 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"
, 4360)
;
4361 }
4362}
4363
4364/* static */
4365bool nsContentUtils::SpoofLocaleEnglish() {
4366 // 0 - will prompt
4367 // 1 - don't spoof
4368 // 2 - spoof
4369 return StaticPrefs::privacy_spoof_english() == 2;
4370}
4371
4372static nsContentUtils::PropertiesFile GetMaybeSpoofedPropertiesFile(
4373 nsContentUtils::PropertiesFile aFile, const char* aKey,
4374 Document* aDocument) {
4375 // When we spoof English, use en-US properties in strings that are accessible
4376 // by content.
4377 bool spoofLocale = nsContentUtils::SpoofLocaleEnglish() &&
4378 (!aDocument || !aDocument->AllowsL10n());
4379 if (spoofLocale) {
4380 switch (aFile) {
4381 case nsContentUtils::eFORMS_PROPERTIES:
4382 return nsContentUtils::eFORMS_PROPERTIES_en_US;
4383 case nsContentUtils::eDOM_PROPERTIES:
4384 return nsContentUtils::eDOM_PROPERTIES_en_US;
4385 default:
4386 break;
4387 }
4388 }
4389 return aFile;
4390}
4391
4392/* static */
4393nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
4394 const char* aKey,
4395 Document* aDocument,
4396 nsAString& aResult) {
4397 return GetLocalizedString(
4398 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
4399}
4400
4401/* static */
4402nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
4403 const char* aKey,
4404 nsAString& aResult) {
4405 return FormatLocalizedString(aFile, aKey, {}, aResult);
4406}
4407
4408/* static */
4409nsresult nsContentUtils::FormatMaybeLocalizedString(
4410 PropertiesFile aFile, const char* aKey, Document* aDocument,
4411 const nsTArray<nsString>& aParams, nsAString& aResult) {
4412 return FormatLocalizedString(
4413 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
4414 aResult);
4415}
4416
4417class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
4418 public:
4419 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
4420 nsContentUtils::PropertiesFile aFile,
4421 const char* aKey,
4422 const nsTArray<nsString>& aParams,
4423 nsAString& aLocalizedString)
4424 : WorkerMainThreadRunnable(aWorkerPrivate,
4425 "FormatLocalizedStringRunnable"_ns),
4426 mFile(aFile),
4427 mKey(aKey),
4428 mParams(aParams),
4429 mLocalizedString(aLocalizedString) {
4430 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"
, 4430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWorkerPrivate"
")"); do { *((volatile int*)__null) = 4430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4431 aWorkerPrivate->AssertIsOnWorkerThread();
4432 }
4433
4434 bool MainThreadRun() override {
4435 AssertIsOnMainThread();
4436
4437 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
4438 mLocalizedString);
4439 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"
, 4439)
;
4440 return true;
4441 }
4442
4443 nsresult GetResult() const { return mResult; }
4444
4445 private:
4446 const nsContentUtils::PropertiesFile mFile;
4447 const char* mKey;
4448 const nsTArray<nsString>& mParams;
4449 nsresult mResult = NS_ERROR_FAILURE;
4450 nsAString& mLocalizedString;
4451};
4452
4453/* static */
4454nsresult nsContentUtils::FormatLocalizedString(
4455 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
4456 nsAString& aResult) {
4457 if (!NS_IsMainThread()) {
4458 // nsIStringBundle is thread-safe but its creation is not, and in particular
4459 // we don't create and store nsIStringBundle objects in a thread-safe way.
4460 //
4461 // TODO(emilio): Maybe if we already have the right bundle created we could
4462 // just call into it, but we should make sure that Shutdown() doesn't get
4463 // called on the main thread when that happens which is a bit tricky to
4464 // prove?
4465 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
4466 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4466)
) {
4467 return NS_ERROR_UNEXPECTED;
4468 }
4469
4470 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
4471 workerPrivate, aFile, aKey, aParams, aResult);
4472
4473 runnable->Dispatch(Canceling, IgnoreErrors());
4474 return runnable->GetResult();
4475 }
4476
4477 MOZ_TRY(EnsureStringBundle(aFile))do { auto mozTryTempResult_ = ::mozilla::ToResult(EnsureStringBundle
(aFile)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
;
4478 nsIStringBundle* bundle = sStringBundles[aFile];
4479 if (aParams.IsEmpty()) {
4480 return bundle->GetStringFromName(aKey, aResult);
4481 }
4482 return bundle->FormatStringFromName(aKey, aParams, aResult);
4483}
4484
4485/* static */
4486void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
4487 const nsACString& aCategory,
4488 bool aFromPrivateWindow,
4489 bool aFromChromeContext,
4490 uint32_t aErrorFlags) {
4491 nsCOMPtr<nsIScriptError> scriptError =
4492 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
4493 if (scriptError) {
4494 nsCOMPtr<nsIConsoleService> console =
4495 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
4496 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)))
4497 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)))
4498 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
4499 console->LogMessage(scriptError);
4500 }
4501 }
4502}
4503
4504/* static */
4505nsresult nsContentUtils::ReportToConsole(
4506 uint32_t aErrorFlags, const nsACString& aCategory,
4507 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
4508 const nsTArray<nsString>& aParams, nsIURI* aURI,
4509 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber) {
4510 nsresult rv;
4511 nsAutoString errorText;
4512 if (!aParams.IsEmpty()) {
4513 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
4514 } else {
4515 rv = GetLocalizedString(aFile, aMessageName, errorText);
4516 }
4517 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"
, 4517); return rv; } } while (false)
;
4518
4519 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
4520 aDocument, aURI, aSourceLine, aLineNumber,
4521 aColumnNumber);
4522}
4523
4524/* static */
4525void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
4526 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
4527 nsContentUtils::eDOM_PROPERTIES, "EmptyGetElementByIdParam");
4528}
4529
4530/* static */
4531nsresult nsContentUtils::ReportToConsoleNonLocalized(
4532 const nsAString& aErrorText, uint32_t aErrorFlags,
4533 const nsACString& aCategory, const Document* aDocument, nsIURI* aURI,
4534 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber,
4535 MissingErrorLocationMode aLocationMode) {
4536 uint64_t innerWindowID = 0;
4537 if (aDocument) {
4538 if (!aURI) {
4539 aURI = aDocument->GetDocumentURI();
4540 }
4541 innerWindowID = aDocument->InnerWindowID();
4542 }
4543
4544 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
4545 innerWindowID, aURI, aSourceLine,
4546 aLineNumber, aColumnNumber, aLocationMode);
4547}
4548
4549/* static */
4550nsresult nsContentUtils::ReportToConsoleByWindowID(
4551 const nsAString& aErrorText, uint32_t aErrorFlags,
4552 const nsACString& aCategory, uint64_t aInnerWindowID, nsIURI* aURI,
4553 const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber,
4554 MissingErrorLocationMode aLocationMode) {
4555 nsresult rv;
4556 if (!sConsoleService) { // only need to bother null-checking here
4557 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4558 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"
, 4558); return rv; } } while (false)
;
4559 }
4560
4561 nsAutoString spec;
4562 if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
4563 JSContext* cx = GetCurrentJSContext();
4564 if (cx) {
4565 nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
4566 }
4567 }
4568
4569 nsCOMPtr<nsIScriptError> errorObject =
4570 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
4571 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"
, 4571); return rv; } } while (false)
;
4572
4573 if (!spec.IsEmpty()) {
4574 rv = errorObject->InitWithWindowID(aErrorText,
4575 spec, // file name
4576 aSourceLine, aLineNumber, aColumnNumber,
4577 aErrorFlags, aCategory, aInnerWindowID);
4578 } else {
4579 rv = errorObject->InitWithSourceURI(aErrorText, aURI, aSourceLine,
4580 aLineNumber, aColumnNumber, aErrorFlags,
4581 aCategory, aInnerWindowID);
4582 }
4583 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"
, 4583); return rv; } } while (false)
;
4584
4585 return sConsoleService->LogMessage(errorObject);
4586}
4587
4588void nsContentUtils::LogMessageToConsole(const char* aMsg) {
4589 if (!sConsoleService) { // only need to bother null-checking here
4590 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
4591 if (!sConsoleService) {
4592 return;
4593 }
4594 }
4595 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
4596}
4597
4598bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
4599 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
4600}
4601
4602bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
4603 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
4604 return bc->GetParent();
4605 }
4606 return false;
4607}
4608
4609bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
4610 // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
4611 // define in nsContentDLF.h as well.
4612 return aContentType.EqualsLiteral(TEXT_PLAIN"text/plain") ||
4613 aContentType.EqualsLiteral(TEXT_CSS"text/css") ||
4614 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
4615 aContentType.EqualsLiteral(TEXT_VTT"text/vtt") ||
4616 aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT"application/javascript") ||
4617 aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT"application/x-javascript") ||
4618 aContentType.EqualsLiteral(TEXT_ECMASCRIPT"text/ecmascript") ||
4619 aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT"application/ecmascript") ||
4620 aContentType.EqualsLiteral(TEXT_JAVASCRIPT"text/javascript") ||
4621 aContentType.EqualsLiteral(APPLICATION_JSON"application/json") ||
4622 aContentType.EqualsLiteral(TEXT_JSON"text/json");
4623}
4624
4625bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
4626 // NOTE: This must be a subset of the list in IsPlainTextType().
4627 return aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
4628 aContentType.EqualsLiteral(APPLICATION_JSON"application/json") ||
4629 aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
4630 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
4631}
4632
4633bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
4634 return aDocument && aDocument->IsInChromeDocShell();
4635}
4636
4637// static
4638nsIContentPolicy* nsContentUtils::GetContentPolicy() {
4639 if (!sTriedToGetContentPolicy) {
4640 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
4641 // It's OK to not have a content policy service
4642 sTriedToGetContentPolicy = true;
4643 }
4644
4645 return sContentPolicyService;
4646}
4647
4648// static
4649bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
4650 const char16_t* name = aName->GetUTF16String();
4651 if (name[0] != 'o' || name[1] != 'n') {
4652 return false;
4653 }
4654
4655 EventNameMapping mapping;
4656 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
4657}
4658
4659// static
4660EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
4661 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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { *((volatile
int*)__null) = 4661; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4662 if (aName) {
4663 EventNameMapping mapping;
4664 if (sAtomEventTable->Get(aName, &mapping)) {
4665 return mapping.mMessage;
4666 }
4667 }
4668
4669 return eUnidentifiedEvent;
4670}
4671
4672// static
4673mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
4674 EventNameMapping mapping;
4675 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
4676
4677 return eBasicEventClass;
4678}
4679
4680nsAtom* nsContentUtils::GetEventMessageAndAtom(
4681 const nsAString& aName, mozilla::EventClassID aEventClassID,
4682 EventMessage* aEventMessage) {
4683 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"
, 4683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4683; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4684 EventNameMapping mapping;
4685 if (sStringEventTable->Get(aName, &mapping)) {
4686 *aEventMessage = mapping.mEventClassID == aEventClassID
4687 ? mapping.mMessage
4688 : eUnidentifiedEvent;
4689 return mapping.mAtom;
4690 }
4691
4692 // If we have cached lots of user defined event names, clear some of them.
4693 if (sUserDefinedEvents->Length() > 127) {
4694 while (sUserDefinedEvents->Length() > 64) {
4695 nsAtom* first = sUserDefinedEvents->ElementAt(0);
4696 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
4697 sUserDefinedEvents->RemoveElementAt(0);
4698 }
4699 }
4700
4701 *aEventMessage = eUnidentifiedEvent;
4702 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
4703 sUserDefinedEvents->AppendElement(atom);
4704 mapping.mAtom = atom;
4705 mapping.mMessage = eUnidentifiedEvent;
4706 mapping.mType = EventNameType_None;
4707 mapping.mEventClassID = eBasicEventClass;
4708 sStringEventTable->InsertOrUpdate(aName, mapping);
4709 return mapping.mAtom;
4710}
4711
4712// static
4713EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
4714 const nsAString& aName, nsAtom** aOnName) {
4715 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"
, 4715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { *((volatile
int*)__null) = 4715; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4716
4717 // Check sStringEventTable for a matching entry. This will only fail for
4718 // user-defined event types.
4719 EventNameMapping mapping;
4720 if (sStringEventTable->Get(aName, &mapping)) {
4721 RefPtr<nsAtom> atom = mapping.mAtom;
4722 atom.forget(aOnName);
4723 return mapping.mMessage;
4724 }
4725
4726 // sStringEventTable did not contain an entry for this event type string.
4727 // Call GetEventMessageAndAtom, which will create an event type atom and
4728 // cache it in sStringEventTable for future calls.
4729 EventMessage msg = eUnidentifiedEvent;
4730 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
4731 atom.forget(aOnName);
4732 return msg;
4733}
4734
4735static already_AddRefed<Event> GetEventWithTarget(
4736 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4737 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4738 Trusted aTrusted, ErrorResult& aErrorResult) {
4739 RefPtr<Event> event =
4740 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
4741 if (aErrorResult.Failed()) {
4742 return nullptr;
4743 }
4744
4745 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
4746 event->SetTrusted(aTrusted == Trusted::eYes);
4747
4748 event->SetTarget(aTarget);
4749
4750 return event.forget();
4751}
4752
4753// static
4754nsresult nsContentUtils::DispatchTrustedEvent(
4755 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4756 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
4757 bool* aDefaultAction) {
4758 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"
, 4760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4760; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4759 !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"
, 4760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4760; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4760 "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"
, 4760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile
int*)__null) = 4760; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4761 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4762 aComposed, Trusted::eYes, aDefaultAction);
4763}
4764
4765// static
4766nsresult nsContentUtils::DispatchUntrustedEvent(
4767 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
4768 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
4769 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4770 Composed::eDefault, Trusted::eNo, aDefaultAction);
4771}
4772
4773// static
4774nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4775 const nsAString& aEventName,
4776 CanBubble aCanBubble,
4777 Cancelable aCancelable,
4778 Composed aComposed, Trusted aTrusted,
4779 bool* aDefaultAction,
4780 ChromeOnlyDispatch aOnlyChromeDispatch) {
4781 if (!aDoc || !aTarget) {
4782 return NS_ERROR_INVALID_ARG;
4783 }
4784
4785 ErrorResult err;
4786 RefPtr<Event> event =
4787 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4788 aComposed, aTrusted, err);
4789 if (err.Failed()) {
4790 return err.StealNSResult();
4791 }
4792 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
4793 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4794
4795 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
4796 if (aDefaultAction) {
4797 *aDefaultAction = doDefault;
4798 }
4799 return err.StealNSResult();
4800}
4801
4802// static
4803nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget,
4804 WidgetEvent& aEvent,
4805 EventMessage aEventMessage,
4806 CanBubble aCanBubble,
4807 Cancelable aCancelable, Trusted aTrusted,
4808 bool* aDefaultAction,
4809 ChromeOnlyDispatch aOnlyChromeDispatch) {
4810 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"
, 4811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4811 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"
, 4811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes"
")"); do { *((volatile int*)__null) = 4811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4812
4813 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
4814 aEvent.SetDefaultComposed();
4815 aEvent.SetDefaultComposedInNativeAnonymousContent();
4816
4817 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
4818 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
4819 aEvent.mFlags.mOnlyChromeDispatch =
4820 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
4821
4822 aEvent.mTarget = aTarget;
4823
4824 nsEventStatus status = nsEventStatus_eIgnore;
4825 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
4826 nullptr, &status);
4827 if (aDefaultAction) {
4828 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
4829 }
4830 return rv;
4831}
4832
4833// static
4834nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
4835 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
4836 mozilla::EditorInputType::eUnknown, nullptr,
4837 InputEventOptions());
4838}
4839
4840// static
4841nsresult nsContentUtils::DispatchInputEvent(
4842 Element* aEventTargetElement, EventMessage aEventMessage,
4843 EditorInputType aEditorInputType, EditorBase* aEditorBase,
4844 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
4845 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"
, 4846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4846 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"
, 4846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { *((volatile int*)__null) = 4846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4847
4848 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4848)
) {
4849 return NS_ERROR_INVALID_ARG;
4850 }
4851
4852 // If this is called from editor, the instance should be set to aEditorBase.
4853 // Otherwise, we need to look for an editor for aEventTargetElement.
4854 // However, we don't need to do it for HTMLEditor since nobody shouldn't
4855 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
4856 // itself.
4857 bool useInputEvent = false;
4858 if (aEditorBase) {
4859 useInputEvent = true;
4860 } else if (HTMLTextAreaElement* textAreaElement =
4861 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
4862 aEditorBase = textAreaElement->GetTextEditorWithoutCreation();
4863 useInputEvent = true;
4864 } else if (HTMLInputElement* inputElement =
4865 HTMLInputElement::FromNode(aEventTargetElement)) {
4866 if (inputElement->IsInputEventTarget()) {
4867 aEditorBase = inputElement->GetTextEditorWithoutCreation();
4868 useInputEvent = true;
4869 }
4870 }
4871#ifdef DEBUG1
4872 else {
4873 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"
, 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4874 "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"
, 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { *((volatile int*)__null) = 4874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4875 }
4876#endif // #ifdef DEBUG
4877
4878 if (!useInputEvent) {
4879 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"
, 4879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { *((volatile int*)__null) = 4879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4880 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"
, 4880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { *((volatile int*)__null) = 4880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4881 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"
, 4881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4882 // Dispatch "input" event with Event instance.
4883 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
4884 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
4885 widgetEvent.mFlags.mCancelable = false;
4886 widgetEvent.mFlags.mComposed = true;
4887 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
4888 widgetEvent, aEventStatus);
4889 }
4890
4891 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"
, 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4892 !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"
, 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable"
")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4893 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"
, 4895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4895; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4894 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"
, 4895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4895; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4895 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"
, 4895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { *((volatile int*)__null) = 4895; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4896
4897 nsCOMPtr<nsIWidget> widget;
4898 if (aEditorBase) {
4899 widget = aEditorBase->GetWidget();
4900 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4900)
) {
4901 return NS_ERROR_FAILURE;
4902 }
4903 } else {
4904 Document* document = aEventTargetElement->OwnerDoc();
4905 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4905)
) {
4906 return NS_ERROR_FAILURE;
4907 }
4908 // If we're running xpcshell tests, we fail to get presShell here.
4909 // Even in such case, we need to dispatch "input" event without widget.
4910 PresShell* presShell = document->GetPresShell();
4911 if (presShell) {
4912 nsPresContext* presContext = presShell->GetPresContext();
4913 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4913)
) {
4914 return NS_ERROR_FAILURE;
4915 }
4916 widget = presContext->GetRootWidget();
4917 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp"
, 4917)
) {
4918 return NS_ERROR_FAILURE;
4919 }
4920 }
4921 }
4922
4923 // Dispatch "input" event with InputEvent instance.
4924 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
4925
4926 inputEvent.mFlags.mCancelable =
4927 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
4928 IsCancelableBeforeInputEvent(aEditorInputType);
4929 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"
, 4929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { *((volatile int*)__null) = 4929; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4930
4931 // If there is an editor, set isComposing to true when it has composition.
4932 // Note that EditorBase::IsIMEComposing() may return false even when we
4933 // need to set it to true.
4934 // Otherwise, i.e., editor hasn't been created for the element yet,
4935 // we should set isComposing to false since the element can never has
4936 // composition without editor.
4937 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
4938
4939 if (!aEditorBase || aEditorBase->IsTextEditor()) {
4940 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
4941 inputEvent.mData = std::move(aOptions.mData);
4942 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"
, 4943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4943; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4943 "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"
, 4943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4943; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4944 }
4945#ifdef DEBUG1
4946 else {
4947 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"
, 4947); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 4947; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4948 }
4949#endif // #ifdef DEBUG
4950 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"
, 4952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4951 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"
, 4952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4952 "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"
, 4952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { *((volatile int*)__null) = 4952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4953 } else {
4954 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"
, 4954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4955 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
4956 inputEvent.mData = std::move(aOptions.mData);
4957 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"
, 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4958; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4958 "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"
, 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile
int*)__null) = 4958; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4959 } else {
4960 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"
, 4960); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { *((volatile
int*)__null) = 4960; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4961 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
4962 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
4963 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"
, 4964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 4964; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4964 "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"
, 4964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ *((volatile int*)__null) = 4964; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4965 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"
, 4966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 4966; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4966 "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"
, 4966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ *((volatile int*)__null) = 4966; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4967 }
4968#ifdef DEBUG1
4969 else {
4970 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"
, 4971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 4971; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4971 "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"
, 4971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
*((volatile int*)__null) = 4971; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4972 }
4973#endif // #ifdef DEBUG
4974 }
4975 if (aEventMessage == eEditorBeforeInput &&
4976 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
4977 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
4978 }
4979#ifdef DEBUG1
4980 else {
4981 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"
, 4982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 4982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4982 "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"
, 4982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { *((volatile int*)__null) = 4982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4983 }
4984#endif // #ifdef DEBUG
4985 }
4986
4987 inputEvent.mInputType = aEditorInputType;
4988
4989 // If we cannot dispatch an event right now, we cannot make it cancelable.
4990 if (!nsContentUtils::IsSafeToRunScript()) {
4991 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"
, 4993); MOZ_PretendNoReturn(); } } while (0)
4992 !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"
, 4993); MOZ_PretendNoReturn(); } } while (0)
4993 "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"
, 4993); MOZ_PretendNoReturn(); } } while (0)
;
4994 inputEvent.mFlags.mCancelable = false;
4995 }
4996 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
4997 inputEvent, aEventStatus);
4998}
4999
5000nsresult nsContentUtils::DispatchChromeEvent(
5001 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
5002 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
5003 if (!aDoc || !aTarget) {
5004 return NS_ERROR_INVALID_ARG;
5005 }
5006
5007 if (!aDoc->GetWindow()) {
5008 return NS_ERROR_INVALID_ARG;
5009 }
5010
5011 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
5012 if (!piTarget) {
5013 return NS_ERROR_INVALID_ARG;
5014 }
5015
5016 ErrorResult err;
5017 RefPtr<Event> event =
5018 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
5019 Composed::eDefault, Trusted::eYes, err);
5020 if (err.Failed()) {
5021 return err.StealNSResult();
5022 }
5023
5024 bool defaultActionEnabled =
5025 piTarget->DispatchEvent(*event, CallerType::System, err);
5026 if (aDefaultAction) {
5027 *aDefaultAction = defaultActionEnabled;
5028 }
5029 return err.StealNSResult();
5030}
5031
5032void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
5033 CallerType aCallerType) {
5034 RefPtr<Element> target = &aFrameElement;
5035 bool defaultAction = true;
5036 if (aCanRaise) {
5037 DispatchEventOnlyToChrome(target->OwnerDoc(), target,
5038 u"framefocusrequested"_ns, CanBubble::eYes,
5039 Cancelable::eYes, &defaultAction);
5040 }
5041 if (!defaultAction) {
5042 return;
5043 }
5044
5045 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
5046 if (!fm) {
5047 return;
5048 }
5049
5050 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
5051 if (aCanRaise) {
5052 flags |= nsIFocusManager::FLAG_RAISE;
5053 }
5054
5055 if (aCallerType == CallerType::NonSystem) {
5056 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
5057 }
5058
5059 fm->SetFocus(target, flags);
5060}
5061
5062nsresult nsContentUtils::DispatchEventOnlyToChrome(
5063 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
5064 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
5065 bool* aDefaultAction) {
5066 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
5067 aComposed, Trusted::eYes, aDefaultAction,
5068 ChromeOnlyDispatch::eYes);
5069}
5070
5071/* static */
5072Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5073 const nsAtom* aId) {
5074 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
5075 if (aId == cur->GetID()) {
5076 return cur->AsElement();
5077 }
5078 }
5079
5080 return nullptr;
5081}
5082
5083/* static */
5084Element* nsContentUtils::MatchElementId(nsIContent* aContent,
5085 const nsAString& aId) {
5086 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"
, 5086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { *((volatile int
*)__null) = 5086; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5087
5088 // ID attrs are generally stored as atoms, so just atomize this up front
5089 RefPtr<nsAtom> id(NS_Atomize(aId));
5090 if (!id) {
5091 // OOM, so just bail
5092 return nullptr;
5093 }
5094
5095 return MatchElementId(aContent, id);
5096}
5097
5098/* static */
5099void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
5100 nsCOMPtr<nsIObserverService> observerService =
5101 mozilla::services::GetObserverService();
5102 if (observerService) {
5103 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
5104 false);
5105 }
5106}
5107
5108/* static */
5109void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
5110 nsCOMPtr<nsIObserverService> observerService =
5111 mozilla::services::GetObserverService();
5112 if (observerService) {
5113 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
5114 }
5115}
5116
5117/* static */
5118bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
5119 int32_t aNameSpaceID, nsAtom* aName) {
5120 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
5121 return aContent->IsElement() &&
5122 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
5123 eCaseMatters) ==
5124 AttrArray::ATTR_VALUE_NO_MATCH;
5125}
5126
5127/* static */
5128bool nsContentUtils::HasMutationListeners(nsINode* aNode, uint32_t aType,
5129 nsINode* aTargetForSubtreeModified) {
5130 Document* doc = aNode->OwnerDoc();
5131
5132 // global object will be null for documents that don't have windows.
5133 nsPIDOMWindowInner* window = doc->GetInnerWindow();
5134 // This relies on EventListenerManager::AddEventListener, which sets
5135 // all mutation bits when there is a listener for DOMSubtreeModified event.
5136 if (window && !window->HasMutationListeners(aType)) {
5137 return false;
5138 }
5139
5140 if (aNode->ChromeOnlyAccess() || aNode->IsInShadowTree()) {
5141 return false;
5142 }
5143
5144 doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
5145
5146 // If we have a window, we can check it for mutation listeners now.
5147 if (aNode->IsInUncomposedDoc()) {
5148 nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
5149 if (piTarget) {
5150 EventListenerManager* manager = piTarget->GetExistingListenerManager();
5151 if (manager && manager->HasMutationListeners()) {
5152 return true;
5153 }
5154 }
5155 }
5156
5157 // If we have a window, we know a mutation listener is registered, but it
5158 // might not be in our chain. If we don't have a window, we might have a
5159 // mutation listener. Check quickly to see.
5160 while (aNode) {
5161 EventListenerManager* manager = aNode->GetExistingListenerManager();
5162 if (manager && manager->HasMutationListeners()) {
5163 return true;
5164 }
5165
5166 aNode = aNode->GetParentNode();
5167 }
5168
5169 return false;
5170}
5171
5172/* static */
5173bool nsContentUtils::HasMutationListeners(Document* aDocument, uint32_t aType) {
5174 nsPIDOMWindowInner* window =
5175 aDocument ? aDocument->GetInnerWindow() : nullptr;
5176
5177 // This relies on EventListenerManager::AddEventListener, which sets
5178 // all mutation bits when there is a listener for DOMSubtreeModified event.
5179 return !window || window->HasMutationListeners(aType);
5180}
5181
5182void nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent) {
5183 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"
, 5183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") ("
"Missing child" ")"); do { *((volatile int*)__null) = 5183; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5184 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"
, 5184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode() == aParent"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5184
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5185 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"
, 5185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->OwnerDoc() == aParent->OwnerDoc()"
") (" "Wrong owner-doc" ")"); do { *((volatile int*)__null) =
5185; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5186
5187 // Having an explicit check here since it's an easy mistake to fall into,
5188 // and there might be existing code with problems. We'd rather be safe
5189 // than fire DOMNodeRemoved in all corner cases. We also rely on it for
5190 // nsAutoScriptBlockerSuppressNodeRemoved.
5191 if (!IsSafeToRunScript()) {
5192 // This checks that IsSafeToRunScript is true since we don't want to fire
5193 // events when that is false. We can't rely on EventDispatcher to assert
5194 // this in this situation since most of the time there are no mutation
5195 // event listeners, in which case we won't even attempt to dispatch events.
5196 // However this also allows for two exceptions. First off, we don't assert
5197 // if the mutation happens to native anonymous content since we never fire
5198 // mutation events on such content anyway.
5199 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
5200 // that is a know case when we'd normally fire a mutation event, but can't
5201 // make that safe and so we suppress it at this time. Ideally this should
5202 // go away eventually.
5203 if (!aChild->IsInNativeAnonymousSubtree() &&
5204 !sDOMNodeRemovedSuppressCount) {
5205 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"
, 5205); MOZ_PretendNoReturn(); } while (0)
;
5206 WarnScriptWasIgnored(aChild->OwnerDoc());
5207 }
5208 return;
5209 }
5210
5211 {
5212 Document* doc = aParent->OwnerDoc();
5213 if (MOZ_UNLIKELY(doc->DevToolsWatchingDOMMutations())(__builtin_expect(!!(doc->DevToolsWatchingDOMMutations()),
0))
&&
5214 aChild->IsInComposedDoc() && !aChild->ChromeOnlyAccess()) {
5215 DispatchChromeEvent(doc, aChild, u"devtoolschildremoved"_ns,
5216 CanBubble::eNo, Cancelable::eNo);
5217 }
5218 }
5219
5220 if (HasMutationListeners(aChild, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04,
5221 aParent)) {
5222 InternalMutationEvent mutation(true, eLegacyNodeRemoved);
5223 mutation.mRelatedNode = aParent;
5224
5225 mozAutoSubtreeModified subtree(aParent->OwnerDoc(), aParent);
5226 EventDispatcher::Dispatch(aChild, nullptr, &mutation);
5227 }
5228}
5229
5230void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() {
5231 if (!sEventListenerManagersHash) {
5232 return;
5233 }
5234
5235 for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
5236 auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
5237 nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
5238 if (n && n->IsInComposedDoc() &&
5239 nsCCUncollectableMarker::InGeneration(
5240 n->OwnerDoc()->GetMarkedCCGeneration())) {
5241 entry->mListenerManager->MarkForCC();
5242 }
5243 }
5244}
5245
5246/* static */
5247void nsContentUtils::TraverseListenerManager(
5248 nsINode* aNode, nsCycleCollectionTraversalCallback& cb) {
5249 if (!sEventListenerManagersHash) {
5250 // We're already shut down, just return.
5251 return;
5252 }
5253
5254 auto entry = static_cast<EventListenerManagerMapEntry*>(
5255 sEventListenerManagersHash->Search(aNode));
5256 if (entry) {
5257 CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
5258 "[via hash] mListenerManager");
5259 }
5260}
5261
5262EventListenerManager* nsContentUtils::GetListenerManagerForNode(
5263 nsINode* aNode) {
5264 if (!sEventListenerManagersHash) {
5265 // We're already shut down, don't bother creating an event listener
5266 // manager.
5267
5268 return nullptr;
5269 }
5270
5271 auto entry = static_cast<EventListenerManagerMapEntry*>(
5272 sEventListenerManagersHash->Add(aNode, fallible));
5273
5274 if (!entry) {
5275 return nullptr;
5276 }
5277
5278 if (!entry->mListenerManager) {
5279 entry->mListenerManager = new EventListenerManager(aNode);
5280
5281 aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
5282 }
5283
5284 return entry->mListenerManager;
5285}
5286
5287EventListenerManager* nsContentUtils::GetExistingListenerManagerForNode(
5288 const nsINode* aNode) {
5289 if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
5290 return nullptr;
5291 }
5292
5293 if (!sEventListenerManagersHash) {
5294 // We're already shut down, don't bother creating an event listener
5295 // manager.
5296
5297 return nullptr;
5298 }
5299
5300 auto entry = static_cast<EventListenerManagerMapEntry*>(
5301 sEventListenerManagersHash->Search(aNode));
5302 if (entry) {
5303 return entry->mListenerManager;
5304 }
5305
5306 return nullptr;
5307}
5308
5309void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
5310 DOMArena* aDOMArena) {
5311 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"
, 5311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5311; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5312 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"
, 5312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5313 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"
, 5313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)"
")"); do { *((volatile int*)__null) = 5313; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5314 if (!sDOMArenaHashtable) {
5315 sDOMArenaHashtable =
5316 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
5317 }
5318 aNode->SetFlags(NODE_KEEPS_DOMARENA);
5319 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
5320}
5321
5322already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
5323 const nsINode* aNode) {
5324 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"
, 5324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)"
")"); do { *((volatile int*)__null) = 5324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5325 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"
, 5325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()"
")"); do { *((volatile int*)__null) = 5325; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5326 RefPtr<DOMArena> arena;
5327 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
5328 return arena.forget();
5329}
5330
5331/* static */
5332void nsContentUtils::RemoveListenerManager(nsINode* aNode) {
5333 if (sEventListenerManagersHash) {
5334 auto entry = static_cast<EventListenerManagerMapEntry*>(
5335 sEventListenerManagersHash->Search(aNode));
5336 if (entry) {
5337 RefPtr<EventListenerManager> listenerManager;
5338 listenerManager.swap(entry->mListenerManager);
5339 // Remove the entry and *then* do operations that could cause further
5340 // modification of sEventListenerManagersHash. See bug 334177.
5341 sEventListenerManagersHash->RawRemove(entry);
5342 if (listenerManager) {
5343 listenerManager->Disconnect();
5344 }
5345 }
5346 }
5347}
5348
5349/* static */
5350bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
5351 int32_t aNamespaceID) {
5352 if (aNamespaceID == kNameSpaceID_Unknown-1) {
5353 return false;
5354 }
5355
5356 if (!aPrefix) {
5357 // If the prefix is null, then either the QName must be xmlns or the
5358 // namespace must not be XMLNS.
5359 return (aLocalName == nsGkAtoms::xmlns) ==
5360 (aNamespaceID == kNameSpaceID_XMLNS1);
5361 }
5362
5363 // If the prefix is non-null then the namespace must not be null.
5364 if (aNamespaceID == kNameSpaceID_None) {
5365 return false;
5366 }
5367
5368 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
5369 // but the localname must not be xmlns.
5370 if (aNamespaceID == kNameSpaceID_XMLNS1) {
5371 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
5372 }
5373