Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 380 kB image not shown  

SSL nsContentUtils.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/* A namespace class for static layout utilities. */

#include "nsContentUtils.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <new>
#include <utility>
#include "BrowserChild.h"
#include "DecoderTraits.h"
#include "ErrorList.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "ImageOps.h"
#include "InProcessBrowserChildMessageManager.h"
#include "MainThreadUtils.h"
#include "PLDHashTable.h"
#include "ReferrerInfo.h"
#include "ScopedNSSTypes.h"
#include "ThirdPartyUtil.h"
#include "Units.h"
#include "chrome/common/ipc_message.h"
#include "gfxDrawable.h"
#include "harfbuzz/hb.h"
#include "imgICache.h"
#include "imgIContainer.h"
#include "imgILoader.h"
#include "imgIRequest.h"
#include "imgLoader.h"
#include "js/Array.h"
#include "js/ArrayBuffer.h"
#include "js/BuildId.h"
#include "js/GCAPI.h"
#include "js/Id.h"
#include "js/JSON.h"
#include "js/PropertyAndElement.h"  // JS_DefineElement, JS_GetProperty
#include "js/PropertyDescriptor.h"
#include "js/Realm.h"
#include "js/RegExp.h"
#include "js/RegExpFlags.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
#include "js/Value.h"
#include "js/Wrapper.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozAutoDocUpdate.h"
#include "mozIDOMWindow.h"
#include "nsIOService.h"
#include "nsObjectLoadingContent.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/ArrayIterator.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/AtomArray.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/Base64.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/BloomFilter.h"
#include "mozilla/CORSMode.h"
#include "mozilla/CallState.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Components.h"
#include "mozilla/ContentBlockingAllowList.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventQueue.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/FlushType.h"
#include "mozilla/FOGIPC.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/HangAnnotations.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/InputEventOptions.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/Latin1.h"
#include "mozilla/Likely.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/Logging.h"
#include "mozilla/MacroForEach.h"
#include "mozilla/ManualNAC.h"
#include "mozilla/Maybe.h"
#include "mozilla/MediaFeatureChange.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/NotNull.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/ProfilerRunnable.h"
#include "mozilla/RangeBoundary.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/ScrollbarPreferences.h"
#include "mozilla/ScrollContainerFrame.h"
#include "mozilla/ShutdownPhase.h"
#include "mozilla/Span.h"
#include "mozilla/StaticAnalysisFunctions.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_dom.h"
#ifdef FUZZING
#  include "mozilla/StaticPrefs_fuzzing.h"
#endif
#include "mozilla/StaticPrefs_nglayout.h"
#include "mozilla/StaticPrefs_privacy.h"
#include "mozilla/StaticPrefs_test.h"
#include "mozilla/StaticPrefs_ui.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/TextControlState.h"
#include "mozilla/TextEditor.h"
#include "mozilla/TextEvents.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/Variant.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/dom/AncestorIterator.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/AutocompleteInfoBinding.h"
#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/BorrowedAttrInfo.h"
#include "mozilla/dom/BrowserBridgeParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/CacheExpirationTime.h"
#include "mozilla/dom/CallbackFunction.h"
#include "mozilla/dom/CallbackObject.h"
#include "mozilla/dom/ChromeMessageBroadcaster.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentFrameMessageManager.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/CustomElementTypes.h"
#include "mozilla/dom/DOMArena.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/DOMSecurityMonitor.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/ElementInlines.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemSecurity.h"
#include "mozilla/dom/FilteredNodeIterator.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/FragmentOrElement.h"
#include "mozilla/dom/FromParser.h"
#include "mozilla/dom/HTMLElement.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/HTMLTextAreaElement.h"
#include "mozilla/dom/IPCBlob.h"
#include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/dom/MessageBroadcaster.h"
#include "mozilla/dom/MessageListenerManager.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/dom/NameSpaceConstants.h"
#include "mozilla/dom/NodeBinding.h"
#include "mozilla/dom/NodeInfo.h"
#include "mozilla/dom/PBrowser.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/PrototypeList.h"
#include "mozilla/dom/ReferrerPolicyBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/TrustedHTML.h"
#include "mozilla/dom/TrustedTypesConstants.h"
#include "mozilla/dom/TrustedTypeUtils.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/dom/ViewTransition.h"
#include "mozilla/dom/WindowContext.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/XULCommandEvent.h"
#include "mozilla/glean/GleanPings.h"
#include "mozilla/fallible.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/BaseMargin.h"
#include "mozilla/gfx/BasePoint.h"
#include "mozilla/gfx/BaseSize.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/net/UrlClassifierCommon.h"
#include "mozilla/Tokenizer.h"
#include "mozilla/widget/IMEData.h"
#include "nsAboutProtocolUtils.h"
#include "nsArrayUtils.h"
#include "nsAtomHashKeys.h"
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsBaseHashtable.h"
#include "nsCCUncollectableMarker.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsCRTGlue.h"
#include "nsCanvasFrame.h"
#include "nsCaseTreatment.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsCharTraits.h"
#include "nsCompatibility.h"
#include "nsComponentManagerUtils.h"
#include "nsContainerFrame.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentDLF.h"
#include "nsContentList.h"
#include "nsContentListDeclarations.h"
#include "nsContentPolicyUtils.h"
#include "nsCoord.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsDOMMutationObserver.h"
#include "nsDOMString.h"
#include "nsTHashMap.h"
#include "nsDebug.h"
#include "nsDocShell.h"
#include "nsDocShellCID.h"
#include "nsError.h"
#include "nsFocusManager.h"
#include "nsFrameList.h"
#include "nsFrameLoader.h"
#include "nsFrameLoaderOwner.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsGlobalWindowInner.h"
#include "nsGlobalWindowOuter.h"
#include "nsHTMLDocument.h"
#include "nsHTMLTags.h"
#include "nsHashKeys.h"
#include "nsHtml5StringParser.h"
#include "nsIAboutModule.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIAppShell.h"
#include "nsIArray.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIBidiKeyboard.h"
#include "nsIBrowser.h"
#include "nsICacheInfoChannel.h"
#include "nsICachingChannel.h"
#include "nsICategoryManager.h"
#include "nsIChannel.h"
#include "nsIChannelEventSink.h"
#include "nsIClassifiedChannel.h"
#include "nsIConsoleService.h"
#include "nsIContent.h"
#include "nsIContentInlines.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentSink.h"
#include "nsIDOMWindowUtils.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocumentEncoder.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsIDocumentViewer.h"
#include "nsIDragService.h"
#include "nsIDragSession.h"
#include "nsIFile.h"
#include "nsIFocusManager.h"
#include "nsIFormControl.h"
#include "nsIFragmentContentSink.h"
#include "nsIFrame.h"
#include "nsIGlobalObject.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIIOService.h"
#include "nsIImageLoadingContent.h"
#include "nsIInputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsILoadContext.h"
#include "nsILoadGroup.h"
#include "nsILoadInfo.h"
#include "nsIMIMEService.h"
#include "nsIMemoryReporter.h"
#include "nsINetUtil.h"
#include "nsINode.h"
#include "nsIObjectLoadingContent.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIParserUtils.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsIProperties.h"
#include "nsIProtocolHandler.h"
#include "nsIRequest.h"
#include "nsIRunnable.h"
#include "nsIScreen.h"
#include "nsIScriptError.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsISerialEventTarget.h"
#include "nsIStreamConverter.h"
#include "nsIStreamConverterService.h"
#include "nsIStringBundle.h"
#include "nsISupports.h"
#include "nsISupportsPrimitives.h"
#include "nsISupportsUtils.h"
#include "nsITransferable.h"
#include "nsIURI.h"
#include "nsIURIMutator.h"
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
#  include "nsIURIWithSpecialOrigin.h"
#endif
#include "nsIUserIdleServiceInternal.h"
#include "nsIWeakReferenceUtils.h"
#include "nsIWebNavigation.h"
#include "nsIWebNavigationInfo.h"
#include "nsIWidget.h"
#include "nsIWindowMediator.h"
#include "nsIXPConnect.h"
#include "nsJSPrincipals.h"
#include "nsJSUtils.h"
#include "nsLayoutUtils.h"
#include "nsLiteralString.h"
#include "nsMargin.h"
#include "nsMimeTypes.h"
#include "nsNameSpaceManager.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsNodeInfoManager.h"
#include "nsPIDOMWindow.h"
#include "nsPIDOMWindowInlines.h"
#include "nsParser.h"
#include "nsParserConstants.h"
#include "nsPoint.h"
#include "nsPointerHashKeys.h"
#include "nsPresContext.h"
#include "nsQueryFrame.h"
#include "nsQueryObject.h"
#include "nsRange.h"
#include "nsRefPtrHashtable.h"
#include "nsSandboxFlags.h"
#include "nsScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsStringBundle.h"
#include "nsStringFlags.h"
#include "nsStringFwd.h"
#include "nsStringIterator.h"
#include "nsStringStream.h"
#include "nsTArray.h"
#include "nsTLiteralString.h"
#include "nsTPromiseFlatString.h"
#include "nsTStringRepr.h"
#include "nsTextFragment.h"
#include "nsTextNode.h"
#include "nsThreadManager.h"
#include "nsThreadUtils.h"
#include "nsTreeSanitizer.h"
#include "nsUGenCategory.h"
#include "nsURLHelper.h"
#include "nsUnicodeProperties.h"
#include "nsVariant.h"
#include "nsWidgetsCID.h"
#include "nsView.h"
#include "nsViewManager.h"
#include "nsXPCOM.h"
#include "nsXPCOMCID.h"
#include "nsXULAppAPI.h"
#include "nsXULElement.h"
#include "nsXULPopupManager.h"
#include "nscore.h"
#include "prinrval.h"
#include "xpcprivate.h"
#include "xpcpublic.h"

#if defined(XP_WIN)
// Undefine LoadImage to prevent naming conflict with Windows.
#  undef LoadImage
#endif

extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                      const char** next, char16_t* result);
extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
                                 const char** colon);

using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla;

const char kLoadAsData[] = "loadAsData";

nsIXPConnect* nsContentUtils::sXPConnect;
nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
nsIPrincipal* nsContentUtils::sSystemPrincipal;
nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal;
nsIConsoleService* nsContentUtils::sConsoleService;

static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
nsIStringBundleService* nsContentUtils::sStringBundleService;

static StaticRefPtr<nsIStringBundle>
    sStringBundles[nsContentUtils::PropertiesFile_COUNT];

nsIContentPolicy* nsContentUtils::sContentPolicyService;
bool nsContentUtils::sTriedToGetContentPolicy = false;
StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
uint32_t nsContentUtils::sScriptBlockerCount = 0;
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
    nullptr;
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;

bool nsContentUtils::sIsHandlingKeyBoardEvent = false;

nsString* nsContentUtils::sShiftText = nullptr;
nsString* nsContentUtils::sControlText = nullptr;
nsString* nsContentUtils::sCommandOrWinText = nullptr;
nsString* nsContentUtils::sAltText = nullptr;
nsString* nsContentUtils::sModifierSeparator = nullptr;

bool nsContentUtils::sInitialized = false;
#ifndef RELEASE_OR_BETA
bool nsContentUtils::sBypassCSSOMOriginCheck = false;
#endif

nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;

nsContentUtils::UserInteractionObserver*
    nsContentUtils::sUserInteractionObserver = nullptr;

nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
bool nsContentUtils::sFragmentParsingActive = false;

bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false;
bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false;

mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
    "nsResistFingerprinting");
mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");

int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;

template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RawRangeBoundary& aFirstBoundary,
    const RangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RawRangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary);

template int32_t nsContentUtils::ComparePoints_Deprecated(
    const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary,
    bool* aDisconnected);
template int32_t nsContentUtils::ComparePoints_Deprecated(
    const RangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
template int32_t nsContentUtils::ComparePoints_Deprecated(
    const RawRangeBoundary& aFirstBoundary,
    const RangeBoundary& aSecondBoundary, bool* aDisconnected);
template int32_t nsContentUtils::ComparePoints_Deprecated(
    const RawRangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);

// Subset of
// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
enum AutocompleteUnsupportedFieldName : uint8_t {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
  eAutocompleteUnsupportedFieldName_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
};

enum AutocompleteNoPersistFieldName : uint8_t {
#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
  eAutocompleteNoPersistFieldName_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
};

enum AutocompleteUnsupportFieldContactHint : uint8_t {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
  eAutocompleteUnsupportedFieldContactHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
};

enum AutocompleteFieldName : uint8_t {
#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
  AUTOCOMPLETE_FIELD_NAME(name_, value_)
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_NAME
#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
};

enum AutocompleteFieldHint : uint8_t {
#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_HINT
};

enum AutocompleteFieldContactHint : uint8_t {
#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
  eAutocompleteFieldContactHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
};

enum AutocompleteCredentialType : uint8_t {
#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
  eAutocompleteCredentialType_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CREDENTIAL_TYPE
};

enum AutocompleteCategory {
#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CATEGORY
};

static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteUnsupportedFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
    {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = {
#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteNoPersistFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
    {nullptr, 0}};

static const nsAttrValue::EnumTable
    kAutocompleteUnsupportedContactFieldHintTable[] = {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
  {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
        {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_NAME
    {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
    {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
  {value_, eAutocompleteFieldHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_HINT
    {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
  {value_, eAutocompleteFieldContactHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
    {nullptr, 0}};

static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = {
#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
  {value_, eAutocompleteCredentialType_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CREDENTIAL_TYPE
    {nullptr, 0}};

namespace {

static PLDHashTable* sEventListenerManagersHash;

// A global hashtable to for keeping the arena alive for cross docGroup node
// adoption.
static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
    sDOMArenaHashtable;

class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter {
  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)

  ~DOMEventListenerManagersHashReporter() = default;

 public:
  NS_DECL_ISUPPORTS

  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize) override {
    // We don't measure the |EventListenerManager| objects pointed to by the
    // entries because those references are non-owning.
    int64_t amount =
        sEventListenerManagersHash
            ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
                  MallocSizeOf)
            : 0;

    MOZ_COLLECT_REPORT(
        "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
        amount, "Memory used by the event listener manager's hash table.");

    return NS_OK;
  }
};

NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)

class EventListenerManagerMapEntry : public PLDHashEntryHdr {
 public:
  explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {}

  ~EventListenerManagerMapEntry() {
    NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
  }

 protected:          // declared protected to silence clang warnings
  const void* mKey;  // must be first, to look like PLDHashEntryStub

 public:
  RefPtr<EventListenerManager> mListenerManager;
};

static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry,
                                              const void* key) {
  // Initialize the entry with placement new
  new (entry) EventListenerManagerMapEntry(key);
}

static void EventListenerManagerHashClearEntry(PLDHashTable* table,
                                               PLDHashEntryHdr* entry) {
  EventListenerManagerMapEntry* lm =
      static_cast<EventListenerManagerMapEntry*>(entry);

  // Let the EventListenerManagerMapEntry clean itself up...
  lm->~EventListenerManagerMapEntry();
}

class SameOriginCheckerImpl final : public nsIChannelEventSink,
                                    public nsIInterfaceRequestor {
  ~SameOriginCheckerImpl() = default;

  NS_DECL_ISUPPORTS
  NS_DECL_NSICHANNELEVENTSINK
  NS_DECL_NSIINTERFACEREQUESTOR
};

}  // namespace

void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
  // Note: Document::SuppressEventHandling will also automatically suppress
  // event handling for any in-process sub-documents. However, since we need
  // to deal with cases where remote BrowsingContexts may be interleaved
  // with in-process ones, we still need to walk the entire tree ourselves.
  // This may be slightly redundant in some cases, but since event handling
  // suppressions maintain a count of current blockers, it does not cause
  // any problems.
  aDoc->SuppressEventHandling();
}

void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
  aDoc->UnsuppressEventHandlingAndFireEvents(true);
}

AutoSuppressEventHandling::~AutoSuppressEventHandling() {
  UnsuppressDocuments();
}

void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
  AutoSuppressEventHandling::SuppressDocument(aDoc);
  if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
    win->Suspend();
    mWindows.AppendElement(win);
  }
}

AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
  for (const auto& win : mWindows) {
    win->Resume();
  }
}

/**
 * This class is used to determine whether or not the user is currently
 * interacting with the browser. It listens to observer events to toggle the
 * value of the sUserActive static.
 *
 * This class is an internal implementation detail.
 * nsContentUtils::GetUserIsInteracting() should be used to access current
 * user interaction status.
 */

class nsContentUtils::UserInteractionObserver final
    : public nsIObserver,
      public BackgroundHangAnnotator {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIOBSERVER

  void Init();
  void Shutdown();
  void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;

  static Atomic<bool> sUserActive;

 private:
  ~UserInteractionObserver() = default;
};

static constexpr nsLiteralCString kRfpPrefs[] = {
    "privacy.resistFingerprinting"_ns,
    "privacy.resistFingerprinting.pbmode"_ns,
    "privacy.fingerprintingProtection"_ns,
    "privacy.fingerprintingProtection.pbmode"_ns,
    "privacy.fingerprintingProtection.overrides"_ns,
};

static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
  AutoTArray<RefPtr<BrowsingContextGroup>, 5> bcGroups;
  BrowsingContextGroup::GetAllGroups(bcGroups);
  for (auto& bcGroup : bcGroups) {
    AutoTArray<DocGroup*, 5> docGroups;
    bcGroup->GetDocGroups(docGroups);
    for (auto* docGroup : docGroups) {
      for (Document* doc : *docGroup) {
        if (doc->RecomputeResistFingerprinting()) {
          if (auto* pc = doc->GetPresContext()) {
            pc->MediaFeatureValuesChanged(
                {MediaFeatureChangeReason::PreferenceChange},
                MediaFeatureChangePropagation::JustThisDocument);
          }
        }
      }
    }
  }
}

// static
nsresult nsContentUtils::Init() {
  if (sInitialized) {
    NS_WARNING("Init() called twice");

    return NS_OK;
  }

  nsHTMLTags::AddRefTable();

  sXPConnect = nsXPConnect::XPConnect();
  // We hold a strong ref to sXPConnect to ensure that it does not go away until
  // nsLayoutStatics::Shutdown is happening.  Otherwise ~nsXPConnect can be
  // triggered by xpcModuleDtor late in shutdown and cause crashes due to
  // various stuff already being torn down by then.  Note that this means that
  // we are effectively making sure that if we leak nsLayoutStatics then we also
  // leak nsXPConnect.
  NS_ADDREF(sXPConnect);

  sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
  if (!sSecurityManager) return NS_ERROR_FAILURE;
  NS_ADDREF(sSecurityManager);

  sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
  MOZ_ASSERT(sSystemPrincipal);

  RefPtr<NullPrincipal> nullPrincipal =
      NullPrincipal::CreateWithoutOriginAttributes();
  if (!nullPrincipal) {
    return NS_ERROR_FAILURE;
  }

  nullPrincipal.forget(&sNullSubjectPrincipal);

  RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal =
      BasePrincipal::CreateContentPrincipal(
          "about:fingerprintingprotection"_ns);
  if (!fingerprintingProtectionPrincipal) {
    return NS_ERROR_FAILURE;
  }

  fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal);

  if (!InitializeEventTable()) return NS_ERROR_FAILURE;

  if (!sEventListenerManagersHash) {
    static const PLDHashTableOps hash_table_ops = {
        PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub,
        PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry,
        EventListenerManagerHashInitEntry};

    sEventListenerManagersHash =
        new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));

    RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
  }

  sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;

#ifndef RELEASE_OR_BETA
  sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
#endif

  Element::InitCCCallbacks();

  RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
  MOZ_ASSERT(rfpService);

  if (XRE_IsParentProcess()) {
    AsyncPrecreateStringBundles();

#if defined(MOZ_WIDGET_ANDROID)
    // On Android, at-shutdown ping submission isn't reliable
    // (( because, on Android, we usually get killed, not shut down )).
    // To have a chance at submitting the ping, aim for idle after startup.
    nsresult rv = NS_DispatchToCurrentThreadQueue(
        NS_NewRunnableFunction(
            "AndroidUseCounterPingSubmitter",
            []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
        EventQueuePriority::Idle);
    // This is mostly best-effort, so if it goes awry, just log.
    Unused << NS_WARN_IF(NS_FAILED(rv));
#endif  // defined(MOZ_WIDGET_ANDROID)

    RunOnShutdown(
        [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
        ShutdownPhase::AppShutdownConfirmed);
  }

  RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
  uio->Init();
  uio.forget(&sUserInteractionObserver);

  for (const auto& pref : kRfpPrefs) {
    Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
  }

  sInitialized = true;

  return NS_OK;
}

bool nsContentUtils::InitJSBytecodeMimeType() {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(!sJSScriptBytecodeMimeType);
  MOZ_ASSERT(!sJSModuleBytecodeMimeType);

  JS::BuildIdCharVector jsBuildId;
  if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
    return false;
  }

  nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
  sJSScriptBytecodeMimeType =
      new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
  sJSModuleBytecodeMimeType =
      new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
  return true;
}

void nsContentUtils::GetShiftText(nsAString& text) {
  if (!sShiftText) InitializeModifierStrings();
  text.Assign(*sShiftText);
}

void nsContentUtils::GetControlText(nsAString& text) {
  if (!sControlText) InitializeModifierStrings();
  text.Assign(*sControlText);
}

void nsContentUtils::GetCommandOrWinText(nsAString& text) {
  if (!sCommandOrWinText) {
    InitializeModifierStrings();
  }
  text.Assign(*sCommandOrWinText);
}

void nsContentUtils::GetAltText(nsAString& text) {
  if (!sAltText) InitializeModifierStrings();
  text.Assign(*sAltText);
}

void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
  if (!sModifierSeparator) InitializeModifierStrings();
  text.Assign(*sModifierSeparator);
}

void nsContentUtils::InitializeModifierStrings() {
  // load the display strings for the keyboard accelerators
  nsCOMPtr<nsIStringBundleService> bundleService =
      mozilla::components::StringBundle::Service();
  nsCOMPtr<nsIStringBundle> bundle;
  DebugOnly<nsresult> rv = NS_OK;
  if (bundleService) {
    rv = bundleService->CreateBundle(
        "chrome://global-platform/locale/platformKeys.properties",
        getter_AddRefs(bundle));
  }

  NS_ASSERTION(
      NS_SUCCEEDED(rv) && bundle,
      "chrome://global/locale/platformKeys.properties could not be loaded");
  nsAutoString shiftModifier;
  nsAutoString commandOrWinModifier;
  nsAutoString altModifier;
  nsAutoString controlModifier;
  nsAutoString modifierSeparator;
  if (bundle) {
    // macs use symbols for each modifier key, so fetch each from the bundle,
    // which also covers i18n
    bundle->GetStringFromName("VK_SHIFT", shiftModifier);
    bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
    bundle->GetStringFromName("VK_ALT", altModifier);
    bundle->GetStringFromName("VK_CONTROL", controlModifier);
    bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
  }
  // if any of these don't exist, we get  an empty string
  sShiftText = new nsString(shiftModifier);
  sCommandOrWinText = new nsString(commandOrWinModifier);
  sAltText = new nsString(altModifier);
  sControlText = new nsString(controlModifier);
  sModifierSeparator = new nsString(modifierSeparator);
}

mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
    EventMessage aEventMessage) {
  switch (aEventMessage) {
#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
  case message_:                                          \
    return struct_;
#include "mozilla/EventNameList.h"
#undef MESSAGE_TO_EVENT
    default:
      MOZ_ASSERT_UNREACHABLE("Invalid event message?");
      return eBasicEventClass;
  }
}

bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
  bool doesNotReturnData = false;
  nsresult rv = NS_URIChainHasFlags(
      aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
  return NS_SUCCEEDED(rv) && doesNotReturnData;
}

/* static */
nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
  switch (aEventMessage) {
#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
  case message_:                                          \
    return nsGkAtoms::on##name_;
#include "mozilla/EventNameList.h"
#undef MESSAGE_TO_EVENT
    default:
      return nullptr;
  }
}

bool nsContentUtils::InitializeEventTable() {
  NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
  NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");

  static const EventNameMapping eventArray[] = {
#define EVENT(name_, _message, _type, _class) \
  {nsGkAtoms::on##name_, _type, _message, _class},
#define WINDOW_ONLY_EVENT EVENT
#define DOCUMENT_ONLY_EVENT EVENT
#define NON_IDL_EVENT EVENT
#include "mozilla/EventNameList.h"
#undef WINDOW_ONLY_EVENT
#undef NON_IDL_EVENT
#undef EVENT
      {nullptr}};

  sAtomEventTable =
      new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray));
  sStringEventTable =
      new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray));
  sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);

  // Subtract one from the length because of the trailing null
  for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) {
    MOZ_ASSERT(!sAtomEventTable->Contains(eventArray[i].mAtom),
               "Double-defining event name; fix your EventNameList.h");
    sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
    sStringEventTable->InsertOrUpdate(
        Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
        eventArray[i]);
  }

  return true;
}

void nsContentUtils::InitializeTouchEventTable() {
  static bool sEventTableInitialized = false;
  if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
    sEventTableInitialized = true;
    static const EventNameMapping touchEventArray[] = {
#define EVENT(name_, _message, _type, _class)
#define TOUCH_EVENT(name_, _message, _type, _class) \
  {nsGkAtoms::on##name_, _type, _message, _class},
#include "mozilla/EventNameList.h"
#undef TOUCH_EVENT
#undef EVENT
        {nullptr}};
    // Subtract one from the length because of the trailing null
    for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) {
      sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
                                      touchEventArray[i]);
      sStringEventTable->InsertOrUpdate(
          Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
          touchEventArray[i]);
    }
  }
}

static bool Is8bit(const nsAString& aString) {
  static const char16_t EIGHT_BIT = char16_t(~0x00FF);

  for (nsAString::const_char_iterator start = aString.BeginReading(),
                                      end = aString.EndReading();
       start != end; ++start) {
    if (*start & EIGHT_BIT) {
      return false;
    }
  }

  return true;
}

nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
                              nsAString& aAsciiBase64String) {
  if (!Is8bit(aBinaryData)) {
    aAsciiBase64String.Truncate();
    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
  }

  return Base64Encode(aBinaryData, aAsciiBase64String);
}

nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
                              nsAString& aBinaryData) {
  if (!Is8bit(aAsciiBase64String)) {
    aBinaryData.Truncate();
    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
  }

  const char16_t* start = aAsciiBase64String.BeginReading();
  const char16_t* cur = start;
  const char16_t* end = aAsciiBase64String.EndReading();
  bool hasWhitespace = false;

  while (cur < end) {
    if (nsContentUtils::IsHTMLWhitespace(*cur)) {
      hasWhitespace = true;
      break;
    }
    cur++;
  }

  nsresult rv;

  if (hasWhitespace) {
    nsString trimmedString;

    if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
      return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    }

    trimmedString.Append(start, cur - start);

    while (cur < end) {
      if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
        trimmedString.Append(*cur);
      }
      cur++;
    }
    rv = Base64Decode(trimmedString, aBinaryData);
  } else {
    rv = Base64Decode(aAsciiBase64String, aBinaryData);
  }

  if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
  }
  return rv;
}

bool nsContentUtils::IsAutocompleteEnabled(
    mozilla::dom::HTMLInputElement* aInput) {
  MOZ_ASSERT(aInput, "aInput should not be null!");

  nsAutoString autocomplete;
  aInput->GetAutocomplete(autocomplete);

  if (autocomplete.IsEmpty()) {
    auto* form = aInput->GetForm();
    if (!form) {
      return true;
    }

    form->GetAutocomplete(autocomplete);
  }

  return !autocomplete.EqualsLiteral("off");
}

nsContentUtils::AutocompleteAttrState
nsContentUtils::SerializeAutocompleteAttribute(
    const nsAttrValue* aAttr, nsAString& aResult,
    AutocompleteAttrState aCachedState) {
  if (!aAttr ||
      aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
    return aCachedState;
  }

  if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
    uint32_t atomCount = aAttr->GetAtomCount();
    for (uint32_t i = 0; i < atomCount; i++) {
      if (i != 0) {
        aResult.Append(' ');
      }
      aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
    }
    nsContentUtils::ASCIIToLower(aResult);
    return aCachedState;
  }

  aResult.Truncate();

  mozilla::dom::AutocompleteInfo info;
  AutocompleteAttrState state =
      InternalSerializeAutocompleteAttribute(aAttr, info);
  if (state == eAutocompleteAttrState_Valid) {
    // Concatenate the info fields.
    aResult = info.mSection;

    if (!info.mAddressType.IsEmpty()) {
      if (!aResult.IsEmpty()) {
        aResult += ' ';
      }
      aResult += info.mAddressType;
    }

    if (!info.mContactType.IsEmpty()) {
      if (!aResult.IsEmpty()) {
        aResult += ' ';
      }
      aResult += info.mContactType;
    }

    if (!info.mFieldName.IsEmpty()) {
      if (!aResult.IsEmpty()) {
        aResult += ' ';
      }
      aResult += info.mFieldName;
    }

    // The autocomplete attribute value "webauthn" is interpreted as both a
    // field name and a credential type. The corresponding IDL-exposed autofill
    // value is "webauthn", not "webauthn webauthn".
    if (!info.mCredentialType.IsEmpty() &&
        !(info.mCredentialType.Equals(u"webauthn"_ns) &&
          info.mCredentialType.Equals(aResult))) {
      if (!aResult.IsEmpty()) {
        aResult += ' ';
      }
      aResult += info.mCredentialType;
    }
  }

  return state;
}

nsContentUtils::AutocompleteAttrState
nsContentUtils::SerializeAutocompleteAttribute(
    const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
    AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
  if (!aAttr ||
      aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
    return aCachedState;
  }

  return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
                                                aGrantAllValidValue);
}

/**
 * Helper to validate the @autocomplete tokens.
 *
 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
 */

nsContentUtils::AutocompleteAttrState
nsContentUtils::InternalSerializeAutocompleteAttribute(
    const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
    bool aGrantAllValidValue) {
  // No autocomplete attribute so we are done
  if (!aAttrVal) {
    return eAutocompleteAttrState_Invalid;
  }

  uint32_t numTokens = aAttrVal->GetAtomCount();
  if (!numTokens || numTokens > INT32_MAX) {
    return eAutocompleteAttrState_Invalid;
  }

  uint32_t index = numTokens - 1;
  nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
  AutocompleteCategory category;
  nsAttrValue enumValue;
  nsAutoString credentialTypeStr;

  bool result = enumValue.ParseEnumValue(
      tokenString, kAutocompleteCredentialTypeTable, false);
  if (result) {
    if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
      return eAutocompleteAttrState_Invalid;
    }
    enumValue.ToString(credentialTypeStr);
    ASCIIToLower(credentialTypeStr);
    // category is Credential and the indexth token is "webauthn"
    if (index == 0) {
      aInfo.mFieldName.Assign(credentialTypeStr);
      aInfo.mCredentialType.Assign(credentialTypeStr);
      return eAutocompleteAttrState_Valid;
    }

    --index;
    tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));

    // Only the Normal and Contact categories are allowed with webauthn
    //  - disallow Credential
    if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
                                 false)) {
      return eAutocompleteAttrState_Invalid;
    }
    //  - disallow Off and Automatic
    if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
                                 false)) {
      if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
          enumValue.Equals(u"on"_ns, eIgnoreCase)) {
        return eAutocompleteAttrState_Invalid;
      }
    }

    // Proceed to process the remaining tokens as if "webauthn" was not present.
    // We need to decrement numTokens to enforce the correct per-category limits
    // on the maximum number of tokens.
    --numTokens;
  }

  bool unsupported = false;
  if (!aGrantAllValidValue) {
    unsupported = enumValue.ParseEnumValue(
        tokenString, kAutocompleteUnsupportedFieldNameTable, false);
    if (unsupported) {
      return eAutocompleteAttrState_Invalid;
    }
  }

  nsAutoString fieldNameStr;
  result =
      enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);

  if (result) {
    // Off/Automatic/Normal categories.
    if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
        enumValue.Equals(u"on"_ns, eIgnoreCase)) {
      if (numTokens > 1) {
        return eAutocompleteAttrState_Invalid;
      }
      enumValue.ToString(fieldNameStr);
      ASCIIToLower(fieldNameStr);
      aInfo.mFieldName.Assign(fieldNameStr);
      aInfo.mCredentialType.Assign(credentialTypeStr);
      aInfo.mCanAutomaticallyPersist =
          !enumValue.Equals(u"off"_ns, eIgnoreCase);
      return eAutocompleteAttrState_Valid;
    }

    // Only allow on/off if form autofill @autocomplete values aren't enabled
    // and it doesn't grant all valid values.
    if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
        !aGrantAllValidValue) {
      return eAutocompleteAttrState_Invalid;
    }

    // Normal category
    if (numTokens > 3) {
      return eAutocompleteAttrState_Invalid;
    }
    category = eAutocompleteCategory_NORMAL;
  } else {  // Check if the last token is of the contact category instead.
    // Only allow on/off if form autofill @autocomplete values aren't enabled
    // and it doesn't grant all valid values.
    if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
        !aGrantAllValidValue) {
      return eAutocompleteAttrState_Invalid;
    }

    result = enumValue.ParseEnumValue(
        tokenString, kAutocompleteContactFieldNameTable, false);
    if (!result || numTokens > 4) {
      return eAutocompleteAttrState_Invalid;
    }

    category = eAutocompleteCategory_CONTACT;
  }

  enumValue.ToString(fieldNameStr);
  ASCIIToLower(fieldNameStr);

  aInfo.mFieldName.Assign(fieldNameStr);
  aInfo.mCredentialType.Assign(credentialTypeStr);
  aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
      tokenString, kAutocompleteNoPersistFieldNameTable, false);

  // We are done if this was the only token.
  if (numTokens == 1) {
    return eAutocompleteAttrState_Valid;
  }

  --index;
  tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));

  if (category == eAutocompleteCategory_CONTACT) {
    if (!aGrantAllValidValue) {
      unsupported = enumValue.ParseEnumValue(
          tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
      if (unsupported) {
        return eAutocompleteAttrState_Invalid;
      }
    }

    nsAttrValue contactFieldHint;
    result = contactFieldHint.ParseEnumValue(
        tokenString, kAutocompleteContactFieldHintTable, false);
    if (result) {
      nsAutoString contactFieldHintString;
      contactFieldHint.ToString(contactFieldHintString);
      ASCIIToLower(contactFieldHintString);
      aInfo.mContactType.Assign(contactFieldHintString);
      if (index == 0) {
        return eAutocompleteAttrState_Valid;
      }
      --index;
      tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
    }
  }

  // Check for billing/shipping tokens
  nsAttrValue fieldHint;
  if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
                               false)) {
    nsString fieldHintString;
    fieldHint.ToString(fieldHintString);
    ASCIIToLower(fieldHintString);
    aInfo.mAddressType.Assign(fieldHintString);
    if (index == 0) {
      return eAutocompleteAttrState_Valid;
    }
    --index;
    tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
  }

  // Check for section-* token
  const nsDependentSubstring& section = Substring(tokenString, 0, 8);
  if (section.LowerCaseEqualsASCII("section-")) {
    ASCIIToLower(tokenString);
    aInfo.mSection.Assign(tokenString);
    if (index == 0) {
      return eAutocompleteAttrState_Valid;
    }
  }

  // Clear the fields as the autocomplete attribute is invalid.
  aInfo.mSection.Truncate();
  aInfo.mAddressType.Truncate();
  aInfo.mContactType.Truncate();
  aInfo.mFieldName.Truncate();
  aInfo.mCredentialType.Truncate();

  return eAutocompleteAttrState_Invalid;
}

// Parse an integer according to HTML spec
template <class CharT>
int32_t nsContentUtils::ParseHTMLIntegerImpl(
    const CharT* aStart, const CharT* aEnd,
    ParseHTMLIntegerResultFlags* aResult) {
  int result = eParseHTMLInteger_NoFlags;

  const CharT* iter = aStart;

  while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
    result |= eParseHTMLInteger_NonStandard;
    ++iter;
  }

  if (iter == aEnd) {
    result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
    *aResult = (ParseHTMLIntegerResultFlags)result;
    return 0;
  }

  int sign = 1;
  if (*iter == CharT('-')) {
    sign = -1;
    result |= eParseHTMLInteger_Negative;
    ++iter;
  } else if (*iter == CharT('+')) {
    result |= eParseHTMLInteger_NonStandard;
    ++iter;
  }

  bool foundValue = false;
  CheckedInt32 value = 0;

  // Check for leading zeros first.
  uint64_t leadingZeros = 0;
  while (iter != aEnd) {
    if (*iter != CharT('0')) {
      break;
    }

    ++leadingZeros;
    foundValue = true;
    ++iter;
  }

  while (iter != aEnd) {
    if (*iter >= CharT('0') && *iter <= CharT('9')) {
      value = (value * 10) + (*iter - CharT('0')) * sign;
      ++iter;
      if (!value.isValid()) {
        result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
        break;
      }
      foundValue = true;
    } else {
      break;
    }
  }

  if (!foundValue) {
    result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
  }

  if (value.isValid() &&
      ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
       (sign == -1 && value == 0))) {
    result |= eParseHTMLInteger_NonStandard;
  }

  if (iter != aEnd) {
    result |= eParseHTMLInteger_DidNotConsumeAllInput;
  }

  *aResult = (ParseHTMLIntegerResultFlags)result;
  return value.isValid() ? value.value() : 0;
}

// Parse an integer according to HTML spec
int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
                                         const char16_t* aEnd,
                                         ParseHTMLIntegerResultFlags* aResult) {
  return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
}

int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
                                         ParseHTMLIntegerResultFlags* aResult) {
  return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
}

#define SKIP_WHITESPACE(iter, end_iter, end_res)                 \
  while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
    ++(iter);                                                    \
  }                                                              \
  if ((iter) == (end_iter)) {                                    \
    return (end_res);                                            \
  }

#define SKIP_ATTR_NAME(iter, end_iter)                            \
  while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
         *(iter) != '=') {                                        \
    ++(iter);                                                     \
  }

bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
                                             nsAtom* aName, nsAString& aValue) {
  aValue.Truncate();

  const char16_t* start = aSource.get();
  const char16_t* end = start + aSource.Length();
  const char16_t* iter;

  while (start != end) {
    SKIP_WHITESPACE(start, end, false)
    iter = start;
    SKIP_ATTR_NAME(iter, end)

    if (start == iter) {
      return false;
    }

    // Remember the attr name.
    const nsDependentSubstring& attrName = Substring(start, iter);

    // Now check whether this is a valid name="value" pair.
    start = iter;
    SKIP_WHITESPACE(start, end, false)
    if (*start != '=') {
      // No '=', so this is not a name="value" pair.  We don't know
      // what it is, and we have no way to handle it.
      return false;
    }

    // Have to skip the value.
    ++start;
    SKIP_WHITESPACE(start, end, false)
    char16_t q = *start;
    if (q != kQuote && q != kApostrophe) {
      // Not a valid quoted value, so bail.
      return false;
    }

    ++start;  // Point to the first char of the value.
    iter = start;

    while (iter != end && *iter != q) {
      ++iter;
    }

    if (iter == end) {
      // Oops, unterminated quoted string.
      return false;
    }

    // At this point attrName holds the name of the "attribute" and
    // the value is between start and iter.

    if (aName->Equals(attrName)) {
      // We'll accumulate as many characters as possible (until we hit either
      // the end of the string or the beginning of an entity). Chunks will be
      // delimited by start and chunkEnd.
      const char16_t* chunkEnd = start;
      while (chunkEnd != iter) {
        if (*chunkEnd == kLessThan) {
          aValue.Truncate();

          return false;
        }

        if (*chunkEnd == kAmpersand) {
          aValue.Append(start, chunkEnd - start);

          const char16_t* afterEntity = nullptr;
          char16_t result[2];
          uint32_t count = MOZ_XMLTranslateEntity(
              reinterpret_cast<const char*>(chunkEnd),
              reinterpret_cast<const char*>(iter),
              reinterpret_cast<const char**>(&afterEntity), result);
          if (count == 0) {
            aValue.Truncate();

            return false;
          }

          aValue.Append(result, count);

          // Advance to after the entity and begin a new chunk.
          start = chunkEnd = afterEntity;
        } else {
          ++chunkEnd;
        }
      }

      // Append remainder.
      aValue.Append(start, iter - start);

      return true;
    }

    // Resume scanning after the end of the attribute value (past the quote
    // char).
    start = iter + 1;
  }

  return false;
}

bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
  // Create MIME type as "text/" + given input
  nsAutoString mimeType(u"text/");
  mimeType.Append(aName);

  return IsJavascriptMIMEType(mimeType);
}

void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
                                   nsString& aParams) {
  aType.Truncate();
  aParams.Truncate();
  int32_t semiIndex = aValue.FindChar(char16_t(';'));
  if (-1 != semiIndex) {
    aType = Substring(aValue, 0, semiIndex);
    aParams =
        Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
    aParams.StripWhitespace();
  } else {
    aType = aValue;
  }
  aType.StripWhitespace();
}

/**
 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
 * directive) and converts it to the set of flags used internally.
 *
 * @param aSandboxAttr  the sandbox attribute
 * @return              the set of flags (SANDBOXED_NONE if aSandboxAttr is
 *                      null)
 */

uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
    const nsAttrValue* aSandboxAttr) {
  if (!aSandboxAttr) {
    return SANDBOXED_NONE;
  }

  uint32_t out = SANDBOX_ALL_FLAGS;

#define SANDBOX_KEYWORD(string, atom, flags)                  \
  if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
    out &= ~(flags);                                          \
  }
#include "IframeSandboxKeywordList.h"
#undef SANDBOX_KEYWORD

  return out;
}

/**
 * A helper function that checks if a string matches a valid sandbox flag.
 *
 * @param aFlag   the potential sandbox flag.
 * @return        true if the flag is a sandbox flag.
 */

bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
#define SANDBOX_KEYWORD(string, atom, flags)                                  \
  if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
    return true;                                                              \
  }
#include "IframeSandboxKeywordList.h"
#undef SANDBOX_KEYWORD
  return false;
}

/**
 * A helper function that returns a string attribute corresponding to the
 * sandbox flags.
 *
 * @param aFlags    the sandbox flags
 * @param aString   the attribute corresponding to the flags (null if aFlags
 *                  is zero)
 */

void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
  if (!aFlags) {
    SetDOMStringToNull(aString);
    return;
  }

  aString.Truncate();

#define SANDBOX_KEYWORD(string, atom, flags)                \
  if (!(aFlags & (flags))) {                                \
    if (!aString.IsEmpty()) {                               \
      aString.AppendLiteral(u" ");                          \
    }                                                       \
    aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
  }
#include "IframeSandboxKeywordList.h"
#undef SANDBOX_KEYWORD
}

nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
  if (!sBidiKeyboard) {
    sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
  }
  return sBidiKeyboard;
}

/**
 * This is used to determine whether a character is in one of the classes
 * which CSS says should be part of the first-letter.  Currently, that is
 * all punctuation classes (P*).  Note that this is a change from CSS2
 * which excluded Pc and Pd.
 *
 * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
 * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
 *  general category [UAX44]) [...]"
 */


// static
bool nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar) {
  switch (mozilla::unicode::GetGeneralCategory(aChar)) {
    case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
    case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION:    /* Pd */
    case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION:   /* Pe */
    case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION:   /* Pf */
    case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
    case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION:   /* Po */
    case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION:    /* Ps */
      return true;
    default:
      return false;
  }
}

// static
bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
  nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);

  return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
}

// static
bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
  nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);

  return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
         cat == nsUGenCategory::kSymbol;
}

// static
bool nsContentUtils::IsHyphen(uint32_t aChar) {
  // Characters treated as hyphens for the purpose of "emergency" breaking
  // when the content would otherwise overflow.
  return aChar == uint32_t('-') ||  // HYPHEN-MINUS
         aChar == 0x2010 ||         // HYPHEN
         aChar == 0x2012 ||         // FIGURE DASH
         aChar == 0x2013 ||         // EN DASH
         aChar == 0x058A;           // ARMENIAN HYPHEN
}

/* static */
bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
  return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
         aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
         aChar == char16_t(0x0020);
}

/* static */
bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
  return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
}

/* static */
bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
  return aContent->IsAnyOfHTMLElements(
      nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
      nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
      nsGkAtoms::dl,  // XXX why not dt and dd?
      nsGkAtoms::fieldset,
      nsGkAtoms::figure,  // XXX shouldn't figcaption be on this list
      nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
      nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
      nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
      nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
      nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
      nsGkAtoms::ul, nsGkAtoms::xmp);
}

// static
int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
  nsAString::const_iterator iter, end;
  aValue.BeginReading(iter);
  aValue.EndReading(end);

  while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
    ++iter;
  }

  if (iter == end) {
    return 0;
  }

  bool relative = false;
  bool negate = false;
  if (*iter == char16_t('-')) {
    relative = true;
    negate = true;
    ++iter;
  } else if (*iter == char16_t('+')) {
    relative = true;
    ++iter;
  }

  if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
    return 0;
  }

  // We don't have to worry about overflow, since we can bail out as soon as
  // we're bigger than 7.
  int32_t value = 0;
  while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
    value = 10 * value + (*iter - char16_t('0'));
    if (value >= 7) {
      break;
    }
    ++iter;
  }

  if (relative) {
    if (negate) {
      value = 3 - value;
    } else {
      value = 3 + value;
    }
  }

  return std::clamp(value, 1, 7);
}

/* static */
void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aDocument);
  *aURI = nullptr;

  if (aDocument->GetController().isSome()) {
    return;
  }

  Element* docElement = aDocument->GetRootElement();
  if (!docElement) {
    return;
  }

  nsAutoString manifestSpec;
  docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);

  // Manifest URIs can't have fragment identifiers.
  if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
    return;
  }

  nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
                                            aDocument->GetDocBaseURI());
}

/* static */
bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }

/* static */
bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
  return false;
}
// Static
bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
  if (!aURI) {
    return false;
  }

  if (!aURI->SchemeIs("about")) {
    return false;
  }

  nsAutoCString name;
  nsresult rv = NS_GetAboutModuleName(aURI, name);
  NS_ENSURE_SUCCESS(rv, false);

  return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
         name.EqualsLiteral("blocked");
}

// static
void nsContentUtils::Shutdown() {
  sInitialized = false;

  nsHTMLTags::ReleaseTable();

  NS_IF_RELEASE(sContentPolicyService);
  sTriedToGetContentPolicy = false;
  for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
    bundle = nullptr;
  }

  NS_IF_RELEASE(sStringBundleService);
  NS_IF_RELEASE(sConsoleService);
  NS_IF_RELEASE(sXPConnect);
  NS_IF_RELEASE(sSecurityManager);
  NS_IF_RELEASE(sSystemPrincipal);
  NS_IF_RELEASE(sNullSubjectPrincipal);
  NS_IF_RELEASE(sFingerprintingProtectionPrincipal);

  sBidiKeyboard = nullptr;

  delete sAtomEventTable;
  sAtomEventTable = nullptr;
  delete sStringEventTable;
  sStringEventTable = nullptr;
  delete sUserDefinedEvents;
  sUserDefinedEvents = nullptr;

  if (sEventListenerManagersHash) {
    NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0,
                 "Event listener manager hash not empty at shutdown!");

    // See comment above.

    // However, we have to handle this table differently.  If it still
    // has entries, we want to leak it too, so that we can keep it alive
    // in case any elements are destroyed.  Because if they are, we need
    // their event listener managers to be destroyed too, or otherwise
    // it could leave dangling references in DOMClassInfo's preserved
    // wrapper table.

    if (sEventListenerManagersHash->EntryCount() == 0) {
      delete sEventListenerManagersHash;
      sEventListenerManagersHash = nullptr;
    }
  }

  if (sDOMArenaHashtable) {
    MOZ_ASSERT(sDOMArenaHashtable->Count() == 0);
    MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup());
    delete sDOMArenaHashtable;
    sDOMArenaHashtable = nullptr;
  }

  NS_ASSERTION(!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0,
               "How'd this happen?");
  delete sBlockedScriptRunners;
  sBlockedScriptRunners = nullptr;

  delete sShiftText;
  sShiftText = nullptr;
  delete sControlText;
  sControlText = nullptr;
  delete sCommandOrWinText;
  sCommandOrWinText = nullptr;
  delete sAltText;
  sAltText = nullptr;
  delete sModifierSeparator;
  sModifierSeparator = nullptr;

  delete sJSScriptBytecodeMimeType;
  sJSScriptBytecodeMimeType = nullptr;

  delete sJSModuleBytecodeMimeType;
  sJSModuleBytecodeMimeType = nullptr;

  NS_IF_RELEASE(sSameOriginChecker);

  if (sUserInteractionObserver) {
    sUserInteractionObserver->Shutdown();
    NS_RELEASE(sUserInteractionObserver);
  }

  for (const auto& pref : kRfpPrefs) {
    Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
  }

  TextControlState::Shutdown();
}

/**
 * Checks whether two nodes come from the same origin. aTrustedNode is
 * considered 'safe' in that a user can operate on it.
 */

// static
nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
                                         const nsINode* unTrustedNode) {
  MOZ_ASSERT(aTrustedNode);
  MOZ_ASSERT(unTrustedNode);

  /*
   * Get hold of each node's principal
   */


  nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
  nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();

  if (trustedPrincipal == unTrustedPrincipal) {
    return NS_OK;
  }

  bool equal;
  // XXXbz should we actually have a Subsumes() check here instead?  Or perhaps
  // a separate method for that, with callers using one or the other?
  if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal)) ||
      !equal) {
    return NS_ERROR_DOM_PROP_ACCESS_DENIED;
  }

  return NS_OK;
}

// static
--> --------------------

--> maximum size reached

--> --------------------

93%


¤ Dauer der Verarbeitung: 0.49 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.