LCOV - code coverage report
Current view: top level - dom/base - nsContentUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1375 4699 29.3 %
Date: 2017-07-14 16:53:18 Functions: 192 468 41.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <math.h>
      13             : 
      14             : #include "DecoderTraits.h"
      15             : #include "harfbuzz/hb.h"
      16             : #include "imgICache.h"
      17             : #include "imgIContainer.h"
      18             : #include "imgINotificationObserver.h"
      19             : #include "imgLoader.h"
      20             : #include "imgRequestProxy.h"
      21             : #include "jsapi.h"
      22             : #include "jsfriendapi.h"
      23             : #include "js/Value.h"
      24             : #include "Layers.h"
      25             : #include "MediaDecoder.h"
      26             : #include "nsAppRunner.h"
      27             : // nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
      28             : #include "nsNPAPIPluginInstance.h"
      29             : #include "gfxDrawable.h"
      30             : #include "gfxPrefs.h"
      31             : #include "ImageOps.h"
      32             : #include "mozAutoDocUpdate.h"
      33             : #include "mozilla/ArrayUtils.h"
      34             : #include "mozilla/Attributes.h"
      35             : #include "mozilla/AutoRestore.h"
      36             : #include "mozilla/AutoTimelineMarker.h"
      37             : #include "mozilla/Base64.h"
      38             : #include "mozilla/CheckedInt.h"
      39             : #include "mozilla/DebugOnly.h"
      40             : #include "mozilla/LoadInfo.h"
      41             : #include "mozilla/dom/ContentChild.h"
      42             : #include "mozilla/dom/CustomElementRegistry.h"
      43             : #include "mozilla/dom/DocumentFragment.h"
      44             : #include "mozilla/dom/DOMTypes.h"
      45             : #include "mozilla/dom/Element.h"
      46             : #include "mozilla/dom/FileSystemSecurity.h"
      47             : #include "mozilla/dom/FileBlobImpl.h"
      48             : #include "mozilla/dom/HTMLInputElement.h"
      49             : #include "mozilla/dom/HTMLMediaElement.h"
      50             : #include "mozilla/dom/HTMLTemplateElement.h"
      51             : #include "mozilla/dom/HTMLContentElement.h"
      52             : #include "mozilla/dom/HTMLShadowElement.h"
      53             : #include "mozilla/dom/IPCBlobUtils.h"
      54             : #include "mozilla/dom/Promise.h"
      55             : #include "mozilla/dom/ScriptSettings.h"
      56             : #include "mozilla/dom/TabParent.h"
      57             : #include "mozilla/dom/TouchEvent.h"
      58             : #include "mozilla/dom/ShadowRoot.h"
      59             : #include "mozilla/dom/XULCommandEvent.h"
      60             : #include "mozilla/dom/WorkerPrivate.h"
      61             : #include "mozilla/dom/workers/ServiceWorkerManager.h"
      62             : #include "mozilla/EventDispatcher.h"
      63             : #include "mozilla/EventListenerManager.h"
      64             : #include "mozilla/EventStateManager.h"
      65             : #include "mozilla/gfx/DataSurfaceHelpers.h"
      66             : #include "mozilla/IMEStateManager.h"
      67             : #include "mozilla/InternalMutationEvent.h"
      68             : #include "mozilla/Likely.h"
      69             : #include "mozilla/MouseEvents.h"
      70             : #include "mozilla/Preferences.h"
      71             : #include "mozilla/dom/Selection.h"
      72             : #include "mozilla/TextEvents.h"
      73             : #include "nsArrayUtils.h"
      74             : #include "nsAString.h"
      75             : #include "nsAttrName.h"
      76             : #include "nsAttrValue.h"
      77             : #include "nsAttrValueInlines.h"
      78             : #include "nsBindingManager.h"
      79             : #include "nsCanvasFrame.h"
      80             : #include "nsCaret.h"
      81             : #include "nsCCUncollectableMarker.h"
      82             : #include "nsCharSeparatedTokenizer.h"
      83             : #include "nsCOMPtr.h"
      84             : #include "nsContentCreatorFunctions.h"
      85             : #include "nsContentDLF.h"
      86             : #include "nsContentList.h"
      87             : #include "nsContentPolicyUtils.h"
      88             : #include "nsContentSecurityManager.h"
      89             : #include "nsCPrefetchService.h"
      90             : #include "nsCRT.h"
      91             : #include "nsCycleCollectionParticipant.h"
      92             : #include "nsCycleCollector.h"
      93             : #include "nsDataHashtable.h"
      94             : #include "nsDocShellCID.h"
      95             : #include "nsDocument.h"
      96             : #include "nsDOMCID.h"
      97             : #include "mozilla/dom/DataTransfer.h"
      98             : #include "nsDOMJSUtils.h"
      99             : #include "nsDOMMutationObserver.h"
     100             : #include "nsError.h"
     101             : #include "nsFocusManager.h"
     102             : #include "nsGenericHTMLElement.h"
     103             : #include "nsGenericHTMLFrameElement.h"
     104             : #include "nsGkAtoms.h"
     105             : #include "nsHostObjectProtocolHandler.h"
     106             : #include "nsHtml5Module.h"
     107             : #include "nsHtml5StringParser.h"
     108             : #include "nsIAddonPolicyService.h"
     109             : #include "nsIAnonymousContentCreator.h"
     110             : #include "nsIAsyncVerifyRedirectCallback.h"
     111             : #include "nsICategoryManager.h"
     112             : #include "nsIChannelEventSink.h"
     113             : #include "nsICharsetDetectionObserver.h"
     114             : #include "nsIChromeRegistry.h"
     115             : #include "nsIConsoleService.h"
     116             : #include "nsIContent.h"
     117             : #include "nsIContentInlines.h"
     118             : #include "nsIContentSecurityPolicy.h"
     119             : #include "nsIContentSink.h"
     120             : #include "nsIContentViewer.h"
     121             : #include "nsIDocShell.h"
     122             : #include "nsIDocShellTreeOwner.h"
     123             : #include "nsIDocument.h"
     124             : #include "nsIDocumentEncoder.h"
     125             : #include "nsIDOMChromeWindow.h"
     126             : #include "nsIDOMDocument.h"
     127             : #include "nsIDOMDocumentType.h"
     128             : #include "nsIDOMEvent.h"
     129             : #include "nsIDOMElement.h"
     130             : #include "nsIDOMHTMLElement.h"
     131             : #include "nsIDOMHTMLFormElement.h"
     132             : #include "nsIDOMHTMLInputElement.h"
     133             : #include "nsIDOMNode.h"
     134             : #include "nsIDOMNodeList.h"
     135             : #include "nsIDOMWindowUtils.h"
     136             : #include "nsIDragService.h"
     137             : #include "nsIEditor.h"
     138             : #include "nsIFormControl.h"
     139             : #include "nsIForm.h"
     140             : #include "nsIFragmentContentSink.h"
     141             : #include "nsContainerFrame.h"
     142             : #include "nsIHTMLDocument.h"
     143             : #include "nsIIdleService.h"
     144             : #include "nsIImageLoadingContent.h"
     145             : #include "nsIInterfaceRequestor.h"
     146             : #include "nsIInterfaceRequestorUtils.h"
     147             : #include "nsIIOService.h"
     148             : #include "nsILineBreaker.h"
     149             : #include "nsILoadContext.h"
     150             : #include "nsILoadGroup.h"
     151             : #include "nsIMemoryReporter.h"
     152             : #include "nsIMIMEHeaderParam.h"
     153             : #include "nsIMIMEService.h"
     154             : #include "nsINode.h"
     155             : #include "mozilla/dom/NodeInfo.h"
     156             : #include "nsIObjectLoadingContent.h"
     157             : #include "nsIObserver.h"
     158             : #include "nsIObserverService.h"
     159             : #include "nsIOfflineCacheUpdate.h"
     160             : #include "nsIParser.h"
     161             : #include "nsIParserService.h"
     162             : #include "nsIPermissionManager.h"
     163             : #include "nsIPluginHost.h"
     164             : #include "nsIRequest.h"
     165             : #include "nsIRunnable.h"
     166             : #include "nsIScriptContext.h"
     167             : #include "nsIScriptError.h"
     168             : #include "nsIScriptGlobalObject.h"
     169             : #include "nsIScriptObjectPrincipal.h"
     170             : #include "nsIScriptSecurityManager.h"
     171             : #include "nsIScrollable.h"
     172             : #include "nsIStreamConverterService.h"
     173             : #include "nsIStringBundle.h"
     174             : #include "nsIURI.h"
     175             : #include "nsIURIWithPrincipal.h"
     176             : #include "nsIURL.h"
     177             : #include "nsIWebNavigation.h"
     178             : #include "nsIWindowMediator.h"
     179             : #include "nsIWordBreaker.h"
     180             : #include "nsIXPConnect.h"
     181             : #include "nsJSUtils.h"
     182             : #include "nsLWBrkCIID.h"
     183             : #include "nsMappedAttributes.h"
     184             : #include "nsNetCID.h"
     185             : #include "nsNetUtil.h"
     186             : #include "nsNodeInfoManager.h"
     187             : #include "NullPrincipal.h"
     188             : #include "nsParserCIID.h"
     189             : #include "nsParserConstants.h"
     190             : #include "nsPIDOMWindow.h"
     191             : #include "nsPresContext.h"
     192             : #include "nsPrintfCString.h"
     193             : #include "nsReferencedElement.h"
     194             : #include "nsSandboxFlags.h"
     195             : #include "nsScriptSecurityManager.h"
     196             : #include "nsSerializationHelper.h"
     197             : #include "nsStreamUtils.h"
     198             : #include "nsTextEditorState.h"
     199             : #include "nsTextFragment.h"
     200             : #include "nsTextNode.h"
     201             : #include "nsThreadUtils.h"
     202             : #include "nsUnicodeProperties.h"
     203             : #include "nsViewManager.h"
     204             : #include "nsViewportInfo.h"
     205             : #include "nsWidgetsCID.h"
     206             : #include "nsIWindowProvider.h"
     207             : #include "nsWrapperCacheInlines.h"
     208             : #include "nsXULPopupManager.h"
     209             : #include "xpcprivate.h" // nsXPConnect
     210             : #include "HTMLSplitOnSpacesTokenizer.h"
     211             : #include "nsContentTypeParser.h"
     212             : #include "nsICookiePermission.h"
     213             : #include "mozIThirdPartyUtil.h"
     214             : #include "nsICookieService.h"
     215             : #include "mozilla/EnumSet.h"
     216             : #include "mozilla/BloomFilter.h"
     217             : #include "TabChild.h"
     218             : #include "mozilla/dom/DocGroup.h"
     219             : #include "mozilla/dom/TabGroup.h"
     220             : #include "nsIWebNavigationInfo.h"
     221             : #include "nsPluginHost.h"
     222             : #include "mozilla/HangAnnotations.h"
     223             : #include "mozilla/Encoding.h"
     224             : 
     225             : #include "nsIBidiKeyboard.h"
     226             : 
     227             : #if defined(XP_WIN)
     228             : // Undefine LoadImage to prevent naming conflict with Windows.
     229             : #undef LoadImage
     230             : #endif
     231             : 
     232             : extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
     233             :                                       const char** next, char16_t* result);
     234             : extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
     235             :                                  int ns_aware, const char** colon);
     236             : 
     237             : class imgLoader;
     238             : 
     239             : using namespace mozilla::dom;
     240             : using namespace mozilla::ipc;
     241             : using namespace mozilla::gfx;
     242             : using namespace mozilla::layers;
     243             : using namespace mozilla::widget;
     244             : using namespace mozilla;
     245             : 
     246             : const char kLoadAsData[] = "loadAsData";
     247             : 
     248             : nsIXPConnect *nsContentUtils::sXPConnect;
     249             : nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
     250             : nsIPrincipal *nsContentUtils::sSystemPrincipal;
     251             : nsIPrincipal *nsContentUtils::sNullSubjectPrincipal;
     252             : nsIParserService *nsContentUtils::sParserService = nullptr;
     253             : nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
     254             : nsIIOService *nsContentUtils::sIOService;
     255             : nsIUUIDGenerator *nsContentUtils::sUUIDGenerator;
     256             : nsIConsoleService *nsContentUtils::sConsoleService;
     257             : nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
     258             : nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
     259             : nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nullptr;
     260             : nsIStringBundleService *nsContentUtils::sStringBundleService;
     261             : nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
     262             : nsIContentPolicy *nsContentUtils::sContentPolicyService;
     263             : bool nsContentUtils::sTriedToGetContentPolicy = false;
     264             : nsILineBreaker *nsContentUtils::sLineBreaker;
     265             : nsIWordBreaker *nsContentUtils::sWordBreaker;
     266             : nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
     267             : uint32_t nsContentUtils::sScriptBlockerCount = 0;
     268             : uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
     269             : uint32_t nsContentUtils::sMicroTaskLevel = 0;
     270             : AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = nullptr;
     271             : uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
     272             : nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
     273             : 
     274             : bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
     275             : bool nsContentUtils::sAllowXULXBL_for_file = false;
     276             : 
     277             : nsString* nsContentUtils::sShiftText = nullptr;
     278             : nsString* nsContentUtils::sControlText = nullptr;
     279             : nsString* nsContentUtils::sMetaText = nullptr;
     280             : nsString* nsContentUtils::sOSText = nullptr;
     281             : nsString* nsContentUtils::sAltText = nullptr;
     282             : nsString* nsContentUtils::sModifierSeparator = nullptr;
     283             : 
     284             : bool nsContentUtils::sInitialized = false;
     285             : bool nsContentUtils::sIsFullScreenApiEnabled = false;
     286             : bool nsContentUtils::sIsUnprefixedFullscreenApiEnabled = false;
     287             : bool nsContentUtils::sTrustedFullScreenOnly = true;
     288             : bool nsContentUtils::sIsCutCopyAllowed = true;
     289             : bool nsContentUtils::sIsFrameTimingPrefEnabled = false;
     290             : bool nsContentUtils::sIsPerformanceTimingEnabled = false;
     291             : bool nsContentUtils::sIsResourceTimingEnabled = false;
     292             : bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
     293             : bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
     294             : bool nsContentUtils::sIsWebComponentsEnabled = false;
     295             : bool nsContentUtils::sIsCustomElementsEnabled = false;
     296             : bool nsContentUtils::sSendPerformanceTimingNotifications = false;
     297             : bool nsContentUtils::sUseActivityCursor = false;
     298             : bool nsContentUtils::sAnimationsAPICoreEnabled = false;
     299             : bool nsContentUtils::sAnimationsAPIElementAnimateEnabled = false;
     300             : bool nsContentUtils::sGetBoxQuadsEnabled = false;
     301             : bool nsContentUtils::sSkipCursorMoveForSameValueSet = false;
     302             : bool nsContentUtils::sRequestIdleCallbackEnabled = false;
     303             : bool nsContentUtils::sLowerNetworkPriority = false;
     304             : bool nsContentUtils::sShowInputPlaceholderOnFocus = true;
     305             : bool nsContentUtils::sAutoFocusEnabled = true;
     306             : #ifndef RELEASE_OR_BETA
     307             : bool nsContentUtils::sBypassCSSOMOriginCheck = false;
     308             : #endif
     309             : bool nsContentUtils::sIsScopedStyleEnabled = false;
     310             : 
     311             : bool nsContentUtils::sIsBytecodeCacheEnabled = false;
     312             : int32_t nsContentUtils::sBytecodeCacheStrategy = 0;
     313             : nsCString* nsContentUtils::sJSBytecodeMimeType = nullptr;
     314             : 
     315             : int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000;
     316             : int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000;
     317             : 
     318             : nsContentUtils::UserInteractionObserver*
     319             : nsContentUtils::sUserInteractionObserver = nullptr;
     320             : 
     321             : uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
     322             : 
     323             : uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
     324             : uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
     325             : 
     326             : nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
     327             : nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
     328             : nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
     329             : bool nsContentUtils::sFragmentParsingActive = false;
     330             : nsISerialEventTarget* nsContentUtils::sStableStateEventTarget = nullptr;
     331             : 
     332             : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
     333             : bool nsContentUtils::sDOMWindowDumpEnabled;
     334             : #endif
     335             : 
     336             : bool nsContentUtils::sDoNotTrackEnabled = false;
     337             : 
     338             : mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
     339             : 
     340             : // Subset of http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
     341             : enum AutocompleteUnsupportedFieldName : uint8_t
     342             : {
     343             :   #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
     344             :     eAutocompleteUnsupportedFieldName_##name_,
     345             :   #include "AutocompleteFieldList.h"
     346             :   #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
     347             : };
     348             : 
     349             : enum AutocompleteUnsupportFieldContactHint : uint8_t
     350             : {
     351             :   #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
     352             :     eAutocompleteUnsupportedFieldContactHint_##name_,
     353             :   #include "AutocompleteFieldList.h"
     354             :   #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
     355             : };
     356             : 
     357             : enum AutocompleteFieldName : uint8_t
     358             : {
     359             :   #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
     360             :     eAutocompleteFieldName_##name_,
     361             :   #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
     362             :     AUTOCOMPLETE_FIELD_NAME(name_, value_)
     363             :   #include "AutocompleteFieldList.h"
     364             :   #undef AUTOCOMPLETE_FIELD_NAME
     365             :   #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
     366             : };
     367             : 
     368             : enum AutocompleteFieldHint : uint8_t
     369             : {
     370             :   #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
     371             :     eAutocompleteFieldHint_##name_,
     372             :   #include "AutocompleteFieldList.h"
     373             :   #undef AUTOCOMPLETE_FIELD_HINT
     374             : };
     375             : 
     376             : enum AutocompleteFieldContactHint : uint8_t
     377             : {
     378             :   #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
     379             :     eAutocompleteFieldContactHint_##name_,
     380             :   #include "AutocompleteFieldList.h"
     381             :   #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
     382             : };
     383             : 
     384             : enum AutocompleteCategory
     385             : {
     386             :   #define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
     387             :   #include "AutocompleteFieldList.h"
     388             :   #undef AUTOCOMPLETE_CATEGORY
     389             : };
     390             : 
     391             : static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
     392             :   #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
     393             :     { value_, eAutocompleteUnsupportedFieldName_##name_ },
     394             :   #include "AutocompleteFieldList.h"
     395             :   #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
     396             :   { nullptr, 0 }
     397             : };
     398             : 
     399             : static const nsAttrValue::EnumTable kAutocompleteUnsupportedContactFieldHintTable[] = {
     400             :   #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
     401             :     { value_, eAutocompleteUnsupportedFieldContactHint_##name_ },
     402             :   #include "AutocompleteFieldList.h"
     403             :   #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
     404             :   { nullptr, 0 }
     405             : };
     406             : 
     407             : 
     408             : static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
     409             :   #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
     410             :     { value_, eAutocompleteFieldName_##name_ },
     411             :   #include "AutocompleteFieldList.h"
     412             :   #undef AUTOCOMPLETE_FIELD_NAME
     413             :   { nullptr, 0 }
     414             : };
     415             : 
     416             : static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
     417             :   #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
     418             :     { value_, eAutocompleteFieldName_##name_ },
     419             :   #include "AutocompleteFieldList.h"
     420             :   #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
     421             :   { nullptr, 0 }
     422             : };
     423             : 
     424             : static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
     425             :   #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
     426             :     { value_, eAutocompleteFieldHint_##name_ },
     427             :   #include "AutocompleteFieldList.h"
     428             :   #undef AUTOCOMPLETE_FIELD_HINT
     429             :   { nullptr, 0 }
     430             : };
     431             : 
     432             : static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
     433             :   #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
     434             :     { value_, eAutocompleteFieldContactHint_##name_ },
     435             :   #include "AutocompleteFieldList.h"
     436             :   #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
     437             :   { nullptr, 0 }
     438             : };
     439             : 
     440             : namespace {
     441             : 
     442             : static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
     443             : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
     444             : 
     445             : static PLDHashTable* sEventListenerManagersHash;
     446             : 
     447           3 : class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter
     448             : {
     449           0 :   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
     450             : 
     451             :   ~DOMEventListenerManagersHashReporter() = default;
     452             : 
     453             : public:
     454             :   NS_DECL_ISUPPORTS
     455             : 
     456           0 :   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
     457             :                             nsISupports* aData, bool aAnonymize) override
     458             :   {
     459             :     // We don't measure the |EventListenerManager| objects pointed to by the
     460             :     // entries because those references are non-owning.
     461             :     int64_t amount = sEventListenerManagersHash
     462           0 :                    ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
     463             :                        MallocSizeOf)
     464           0 :                    : 0;
     465             : 
     466           0 :     MOZ_COLLECT_REPORT(
     467             :       "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
     468             :       amount,
     469           0 :       "Memory used by the event listener manager's hash table.");
     470             : 
     471           0 :     return NS_OK;
     472             :   }
     473             : };
     474             : 
     475          39 : NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
     476             : 
     477             : class EventListenerManagerMapEntry : public PLDHashEntryHdr
     478             : {
     479             : public:
     480         556 :   explicit EventListenerManagerMapEntry(const void* aKey)
     481         556 :     : mKey(aKey)
     482             :   {
     483         556 :   }
     484             : 
     485           3 :   ~EventListenerManagerMapEntry()
     486           3 :   {
     487           3 :     NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
     488           3 :   }
     489             : 
     490             : protected:          // declared protected to silence clang warnings
     491             :   const void *mKey; // must be first, to look like PLDHashEntryStub
     492             : 
     493             : public:
     494             :   RefPtr<EventListenerManager> mListenerManager;
     495             : };
     496             : 
     497             : static void
     498         556 : EventListenerManagerHashInitEntry(PLDHashEntryHdr *entry, const void *key)
     499             : {
     500             :   // Initialize the entry with placement new
     501         556 :   new (entry) EventListenerManagerMapEntry(key);
     502         556 : }
     503             : 
     504             : static void
     505           3 : EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
     506             : {
     507             :   EventListenerManagerMapEntry *lm =
     508           3 :     static_cast<EventListenerManagerMapEntry *>(entry);
     509             : 
     510             :   // Let the EventListenerManagerMapEntry clean itself up...
     511           3 :   lm->~EventListenerManagerMapEntry();
     512           3 : }
     513             : 
     514           0 : class SameOriginCheckerImpl final : public nsIChannelEventSink,
     515             :                                     public nsIInterfaceRequestor
     516             : {
     517             :   ~SameOriginCheckerImpl() = default;
     518             : 
     519             :   NS_DECL_ISUPPORTS
     520             :   NS_DECL_NSICHANNELEVENTSINK
     521             :   NS_DECL_NSIINTERFACEREQUESTOR
     522             : };
     523             : 
     524           3 : class StableStateEventTarget final : public nsISerialEventTarget
     525             : {
     526             : public:
     527             :   NS_DECL_THREADSAFE_ISUPPORTS
     528             :   NS_DECL_NSIEVENTTARGET_FULL
     529             : private:
     530           0 :   ~StableStateEventTarget() {}
     531             : };
     532             : 
     533           3 : NS_IMPL_ISUPPORTS(StableStateEventTarget, nsISerialEventTarget);
     534             : 
     535             : bool
     536           0 : StableStateEventTarget::IsOnCurrentThreadInfallible()
     537             : {
     538           0 :   return true;
     539             : }
     540             : 
     541             : NS_IMETHODIMP
     542           0 : StableStateEventTarget::IsOnCurrentThread(bool* aResult)
     543             : {
     544           0 :   *aResult = true;
     545           0 :   return NS_OK;
     546             : }
     547             : 
     548             : NS_IMETHODIMP
     549           0 : StableStateEventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
     550             : {
     551           0 :   if (NS_WARN_IF(!CycleCollectedJSContext::Get())) {
     552           0 :     return NS_ERROR_UNEXPECTED;
     553             :   }
     554           0 :   nsContentUtils::RunInStableState(Move(aEvent));
     555           0 :   return NS_OK;
     556             : }
     557             : 
     558             : NS_IMETHODIMP
     559           0 : StableStateEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
     560             : {
     561           0 :   return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
     562             : }
     563             : 
     564             : NS_IMETHODIMP
     565           0 : StableStateEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aDelay)
     566             : {
     567           0 :   return NS_ERROR_NOT_IMPLEMENTED;
     568             : }
     569             : 
     570             : } // namespace
     571             : 
     572             : /**
     573             :  * This class is used to determine whether or not the user is currently
     574             :  * interacting with the browser. It listens to observer events to toggle the
     575             :  * value of the sUserActive static.
     576             :  *
     577             :  * This class is an internal implementation detail.
     578             :  * nsContentUtils::GetUserIsInteracting() should be used to access current
     579             :  * user interaction status.
     580             :  */
     581           3 : class nsContentUtils::UserInteractionObserver final : public nsIObserver
     582             :                                                     , public HangMonitor::Annotator
     583             : {
     584             : public:
     585             :   NS_DECL_ISUPPORTS
     586             :   NS_DECL_NSIOBSERVER
     587             : 
     588             :   void Init();
     589             :   void Shutdown();
     590             :   void AnnotateHang(HangMonitor::HangAnnotations& aAnnotations) override;
     591             : 
     592             :   static Atomic<bool> sUserActive;
     593             : 
     594             : private:
     595           0 :   ~UserInteractionObserver() {}
     596             : };
     597             : 
     598             : /* static */
     599             : TimeDuration
     600           0 : nsContentUtils::HandlingUserInputTimeout()
     601             : {
     602           0 :   return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
     603             : }
     604             : 
     605             : // static
     606             : nsresult
     607           3 : nsContentUtils::Init()
     608             : {
     609           3 :   if (sInitialized) {
     610           0 :     NS_WARNING("Init() called twice");
     611             : 
     612           0 :     return NS_OK;
     613             :   }
     614             : 
     615           3 :   sNameSpaceManager = nsNameSpaceManager::GetInstance();
     616           3 :   NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
     617             : 
     618           3 :   sXPConnect = nsXPConnect::XPConnect();
     619             : 
     620           3 :   sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
     621           3 :   if(!sSecurityManager)
     622           0 :     return NS_ERROR_FAILURE;
     623           3 :   NS_ADDREF(sSecurityManager);
     624             : 
     625           3 :   sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
     626           3 :   MOZ_ASSERT(sSystemPrincipal);
     627             : 
     628           6 :   RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create();
     629           3 :   if (!nullPrincipal) {
     630           0 :     return NS_ERROR_FAILURE;
     631             :   }
     632             : 
     633           3 :   nullPrincipal.forget(&sNullSubjectPrincipal);
     634             : 
     635           3 :   nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
     636           3 :   if (NS_FAILED(rv)) {
     637             :     // This makes life easier, but we can live without it.
     638             : 
     639           0 :     sIOService = nullptr;
     640             :   }
     641             : 
     642           3 :   rv = CallGetService(NS_LBRK_CONTRACTID, &sLineBreaker);
     643           3 :   NS_ENSURE_SUCCESS(rv, rv);
     644             : 
     645           3 :   rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
     646           3 :   NS_ENSURE_SUCCESS(rv, rv);
     647             : 
     648           3 :   if (!InitializeEventTable())
     649           0 :     return NS_ERROR_FAILURE;
     650             : 
     651           3 :   if (!sEventListenerManagersHash) {
     652             :     static const PLDHashTableOps hash_table_ops =
     653             :     {
     654             :       PLDHashTable::HashVoidPtrKeyStub,
     655             :       PLDHashTable::MatchEntryStub,
     656             :       PLDHashTable::MoveEntryStub,
     657             :       EventListenerManagerHashClearEntry,
     658             :       EventListenerManagerHashInitEntry
     659             :     };
     660             : 
     661           3 :     sEventListenerManagersHash =
     662           3 :       new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
     663             : 
     664           3 :     RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
     665             :   }
     666             : 
     667           3 :   sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
     668             : 
     669             :   Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
     670           3 :                                "dom.allow_XUL_XBL_for_file");
     671             : 
     672             :   Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
     673           3 :                                "full-screen-api.enabled");
     674             : 
     675             :   Preferences::AddBoolVarCache(&sIsUnprefixedFullscreenApiEnabled,
     676           3 :                                "full-screen-api.unprefix.enabled");
     677             : 
     678             :   Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
     679           3 :                                "full-screen-api.allow-trusted-requests-only");
     680             : 
     681             :   Preferences::AddBoolVarCache(&sIsCutCopyAllowed,
     682           3 :                                "dom.allow_cut_copy", true);
     683             : 
     684             :   Preferences::AddBoolVarCache(&sIsPerformanceTimingEnabled,
     685           3 :                                "dom.enable_performance", true);
     686             : 
     687             :   Preferences::AddBoolVarCache(&sIsResourceTimingEnabled,
     688           3 :                                "dom.enable_resource_timing", true);
     689             : 
     690             :   Preferences::AddBoolVarCache(&sIsUserTimingLoggingEnabled,
     691           3 :                                "dom.performance.enable_user_timing_logging", false);
     692             : 
     693             :   Preferences::AddBoolVarCache(&sIsFrameTimingPrefEnabled,
     694           3 :                                "dom.enable_frame_timing", false);
     695             : 
     696             :   Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
     697           3 :                                "dom.forms.autocomplete.experimental", false);
     698             : 
     699             :   Preferences::AddBoolVarCache(&sIsWebComponentsEnabled,
     700           3 :                                "dom.webcomponents.enabled", false);
     701             : 
     702             :   Preferences::AddBoolVarCache(&sIsCustomElementsEnabled,
     703           3 :                                "dom.webcomponents.customelements.enabled", false);
     704             : 
     705             :   Preferences::AddIntVarCache(&sPrivacyMaxInnerWidth,
     706             :                               "privacy.window.maxInnerWidth",
     707           3 :                               1000);
     708             : 
     709             :   Preferences::AddIntVarCache(&sPrivacyMaxInnerHeight,
     710             :                               "privacy.window.maxInnerHeight",
     711           3 :                               1000);
     712             : 
     713             :   Preferences::AddUintVarCache(&sHandlingInputTimeout,
     714             :                                "dom.event.handling-user-input-time-limit",
     715           3 :                                1000);
     716             : 
     717             :   Preferences::AddBoolVarCache(&sSendPerformanceTimingNotifications,
     718           3 :                                "dom.performance.enable_notify_performance_timing", false);
     719             : 
     720             :   Preferences::AddUintVarCache(&sCookiesLifetimePolicy,
     721             :                                "network.cookie.lifetimePolicy",
     722           3 :                                nsICookieService::ACCEPT_NORMALLY);
     723             : 
     724             :   Preferences::AddUintVarCache(&sCookiesBehavior,
     725             :                                "network.cookie.cookieBehavior",
     726           3 :                                nsICookieService::BEHAVIOR_ACCEPT);
     727             : 
     728             : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
     729             :   Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
     730             :                                "browser.dom.window.dump.enabled");
     731             : #endif
     732             : 
     733             :   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
     734           3 :                                "privacy.donottrackheader.enabled", false);
     735             : 
     736             :   Preferences::AddBoolVarCache(&sUseActivityCursor,
     737           3 :                                "ui.use_activity_cursor", false);
     738             : 
     739             :   Preferences::AddBoolVarCache(&sAnimationsAPICoreEnabled,
     740           3 :                                "dom.animations-api.core.enabled", false);
     741             : 
     742             :   Preferences::AddBoolVarCache(&sAnimationsAPIElementAnimateEnabled,
     743           3 :                                "dom.animations-api.element-animate.enabled", false);
     744             : 
     745             :   Preferences::AddBoolVarCache(&sGetBoxQuadsEnabled,
     746           3 :                                "layout.css.getBoxQuads.enabled", false);
     747             : 
     748             :   Preferences::AddBoolVarCache(&sSkipCursorMoveForSameValueSet,
     749             :                                "dom.input.skip_cursor_move_for_same_value_set",
     750           3 :                                true);
     751             : 
     752             :   Preferences::AddBoolVarCache(&sRequestIdleCallbackEnabled,
     753           3 :                                "dom.requestIdleCallback.enabled", false);
     754             : 
     755             : #ifndef RELEASE_OR_BETA
     756           3 :   sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
     757             : #endif
     758             : 
     759             :   Preferences::AddBoolVarCache(&sIsScopedStyleEnabled,
     760           3 :                                "layout.css.scoped-style.enabled", false);
     761             : 
     762             :   Preferences::AddBoolVarCache(&sLowerNetworkPriority,
     763           3 :                                "privacy.trackingprotection.lower_network_priority", false);
     764             : 
     765             :   Preferences::AddBoolVarCache(&sShowInputPlaceholderOnFocus,
     766           3 :                                "dom.placeholder.show_on_focus", true);
     767             : 
     768             :   Preferences::AddBoolVarCache(&sAutoFocusEnabled,
     769           3 :                                "browser.autofocus", true);
     770             : 
     771             :   Preferences::AddBoolVarCache(&sIsBytecodeCacheEnabled,
     772           3 :                                "dom.script_loader.bytecode_cache.enabled", false);
     773             : 
     774             :   Preferences::AddIntVarCache(&sBytecodeCacheStrategy,
     775           3 :                               "dom.script_loader.bytecode_cache.strategy", 0);
     776             : 
     777           6 :   nsDependentCString buildID(mozilla::PlatformBuildID());
     778           6 :   sJSBytecodeMimeType = new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
     779             : 
     780           3 :   Element::InitCCCallbacks();
     781             : 
     782           3 :   Unused << nsRFPService::GetOrCreate();
     783             : 
     784           6 :   RefPtr<StableStateEventTarget> stableStateEventTarget = new StableStateEventTarget();
     785           3 :   stableStateEventTarget.forget(&sStableStateEventTarget);
     786             : 
     787             :   nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
     788           6 :     do_GetService("@mozilla.org/uuid-generator;1", &rv);
     789           3 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     790           0 :     return rv;
     791             :   }
     792           3 :   uuidGenerator.forget(&sUUIDGenerator);
     793             : 
     794           6 :   RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
     795           3 :   uio->Init();
     796           3 :   uio.forget(&sUserInteractionObserver);
     797             : 
     798           3 :   sInitialized = true;
     799             : 
     800           3 :   return NS_OK;
     801             : }
     802             : 
     803             : void
     804           0 : nsContentUtils::GetShiftText(nsAString& text)
     805             : {
     806           0 :   if (!sShiftText)
     807           0 :     InitializeModifierStrings();
     808           0 :   text.Assign(*sShiftText);
     809           0 : }
     810             : 
     811             : void
     812           0 : nsContentUtils::GetControlText(nsAString& text)
     813             : {
     814           0 :   if (!sControlText)
     815           0 :     InitializeModifierStrings();
     816           0 :   text.Assign(*sControlText);
     817           0 : }
     818             : 
     819             : void
     820           0 : nsContentUtils::GetMetaText(nsAString& text)
     821             : {
     822           0 :   if (!sMetaText)
     823           0 :     InitializeModifierStrings();
     824           0 :   text.Assign(*sMetaText);
     825           0 : }
     826             : 
     827             : void
     828           0 : nsContentUtils::GetOSText(nsAString& text)
     829             : {
     830           0 :   if (!sOSText) {
     831           0 :     InitializeModifierStrings();
     832             :   }
     833           0 :   text.Assign(*sOSText);
     834           0 : }
     835             : 
     836             : void
     837           0 : nsContentUtils::GetAltText(nsAString& text)
     838             : {
     839           0 :   if (!sAltText)
     840           0 :     InitializeModifierStrings();
     841           0 :   text.Assign(*sAltText);
     842           0 : }
     843             : 
     844             : void
     845           0 : nsContentUtils::GetModifierSeparatorText(nsAString& text)
     846             : {
     847           0 :   if (!sModifierSeparator)
     848           0 :     InitializeModifierStrings();
     849           0 :   text.Assign(*sModifierSeparator);
     850           0 : }
     851             : 
     852             : void
     853           0 : nsContentUtils::InitializeModifierStrings()
     854             : {
     855             :   //load the display strings for the keyboard accelerators
     856             :   nsCOMPtr<nsIStringBundleService> bundleService =
     857           0 :     mozilla::services::GetStringBundleService();
     858           0 :   nsCOMPtr<nsIStringBundle> bundle;
     859           0 :   DebugOnly<nsresult> rv = NS_OK;
     860           0 :   if (bundleService) {
     861           0 :     rv = bundleService->CreateBundle( "chrome://global-platform/locale/platformKeys.properties",
     862           0 :                                       getter_AddRefs(bundle));
     863             :   }
     864             : 
     865           0 :   NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/platformKeys.properties could not be loaded");
     866           0 :   nsXPIDLString shiftModifier;
     867           0 :   nsXPIDLString metaModifier;
     868           0 :   nsXPIDLString osModifier;
     869           0 :   nsXPIDLString altModifier;
     870           0 :   nsXPIDLString controlModifier;
     871           0 :   nsXPIDLString modifierSeparator;
     872           0 :   if (bundle) {
     873             :     //macs use symbols for each modifier key, so fetch each from the bundle, which also covers i18n
     874           0 :     bundle->GetStringFromName(u"VK_SHIFT", getter_Copies(shiftModifier));
     875           0 :     bundle->GetStringFromName(u"VK_META", getter_Copies(metaModifier));
     876           0 :     bundle->GetStringFromName(u"VK_WIN", getter_Copies(osModifier));
     877           0 :     bundle->GetStringFromName(u"VK_ALT", getter_Copies(altModifier));
     878           0 :     bundle->GetStringFromName(u"VK_CONTROL", getter_Copies(controlModifier));
     879           0 :     bundle->GetStringFromName(u"MODIFIER_SEPARATOR", getter_Copies(modifierSeparator));
     880             :   }
     881             :   //if any of these don't exist, we get  an empty string
     882           0 :   sShiftText = new nsString(shiftModifier);
     883           0 :   sMetaText = new nsString(metaModifier);
     884           0 :   sOSText = new nsString(osModifier);
     885           0 :   sAltText = new nsString(altModifier);
     886           0 :   sControlText = new nsString(controlModifier);
     887           0 :   sModifierSeparator = new nsString(modifierSeparator);
     888           0 : }
     889             : 
     890             : mozilla::EventClassID
     891           4 : nsContentUtils::GetEventClassIDFromMessage(EventMessage aEventMessage)
     892             : {
     893           4 :   switch (aEventMessage) {
     894             : #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
     895             :   case message_: return struct_;
     896             : #include "mozilla/EventNameList.h"
     897             : #undef MESSAGE_TO_EVENT
     898             :   default:
     899           0 :     MOZ_ASSERT_UNREACHABLE("Invalid event message?");
     900             :     return eBasicEventClass;
     901             :   }
     902             : }
     903             : 
     904             : static nsIAtom*
     905         607 : GetEventTypeFromMessage(EventMessage aEventMessage)
     906             : {
     907         607 :   switch (aEventMessage) {
     908             : #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
     909             :   case message_: return nsGkAtoms::on##name_;
     910             : #include "mozilla/EventNameList.h"
     911             : #undef MESSAGE_TO_EVENT
     912             :   default:
     913           0 :     return nullptr;
     914             :   }
     915             : }
     916             : 
     917             : // Because of SVG/SMIL we have several atoms mapped to the same
     918             : // id, but we can rely on MESSAGE_TO_EVENT to map id to only one atom.
     919             : static bool
     920         603 : ShouldAddEventToStringEventTable(const EventNameMapping& aMapping)
     921             : {
     922         603 :   MOZ_ASSERT(aMapping.mAtom);
     923         603 :   return GetEventTypeFromMessage(aMapping.mMessage) == aMapping.mAtom;
     924             : }
     925             : 
     926             : bool
     927           3 : nsContentUtils::InitializeEventTable() {
     928           3 :   NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
     929           3 :   NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
     930             : 
     931             :   static const EventNameMapping eventArray[] = {
     932             : #define EVENT(name_,  _message, _type, _class)          \
     933             :     { nsGkAtoms::on##name_, _type, _message, _class, false },
     934             : #define WINDOW_ONLY_EVENT EVENT
     935             : #define DOCUMENT_ONLY_EVENT EVENT
     936             : #define NON_IDL_EVENT EVENT
     937             : #include "mozilla/EventNameList.h"
     938             : #undef WINDOW_ONLY_EVENT
     939             : #undef NON_IDL_EVENT
     940             : #undef EVENT
     941             :     { nullptr }
     942           3 :   };
     943             : 
     944           3 :   sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>(
     945           6 :       ArrayLength(eventArray));
     946           3 :   sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>(
     947           6 :       ArrayLength(eventArray));
     948           3 :   sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
     949             : 
     950             :   // Subtract one from the length because of the trailing null
     951         606 :   for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) {
     952         603 :     MOZ_ASSERT(!sAtomEventTable->Lookup(eventArray[i].mAtom),
     953             :                "Double-defining event name; fix your EventNameList.h");
     954         603 :     sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]);
     955         603 :     if (ShouldAddEventToStringEventTable(eventArray[i])) {
     956        1164 :       sStringEventTable->Put(
     957        1164 :         Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
     958         582 :         eventArray[i]);
     959             :     }
     960             :   }
     961             : 
     962           3 :   return true;
     963             : }
     964             : 
     965             : void
     966           0 : nsContentUtils::InitializeTouchEventTable()
     967             : {
     968             :   static bool sEventTableInitialized = false;
     969           0 :   if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
     970           0 :     sEventTableInitialized = true;
     971             :     static const EventNameMapping touchEventArray[] = {
     972             : #define EVENT(name_,  _message, _type, _class)
     973             : #define TOUCH_EVENT(name_,  _message, _type, _class)      \
     974             :       { nsGkAtoms::on##name_, _type, _message, _class },
     975             : #include "mozilla/EventNameList.h"
     976             : #undef TOUCH_EVENT
     977             : #undef EVENT
     978             :       { nullptr }
     979           0 :     };
     980             :     // Subtract one from the length because of the trailing null
     981           0 :     for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
     982           0 :       sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]);
     983           0 :       sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
     984           0 :                              touchEventArray[i]);
     985             :     }
     986             :   }
     987           0 : }
     988             : 
     989             : static bool
     990           0 : Is8bit(const nsAString& aString)
     991             : {
     992             :   static const char16_t EIGHT_BIT = char16_t(~0x00FF);
     993             : 
     994           0 :   for (nsAString::const_char_iterator start = aString.BeginReading(),
     995           0 :          end = aString.EndReading();
     996           0 :        start != end;
     997             :        ++start) {
     998           0 :     if (*start & EIGHT_BIT) {
     999           0 :       return false;
    1000             :     }
    1001             :   }
    1002             : 
    1003           0 :   return true;
    1004             : }
    1005             : 
    1006             : nsresult
    1007           0 : nsContentUtils::Btoa(const nsAString& aBinaryData,
    1008             :                      nsAString& aAsciiBase64String)
    1009             : {
    1010           0 :   if (!Is8bit(aBinaryData)) {
    1011           0 :     aAsciiBase64String.Truncate();
    1012           0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    1013             :   }
    1014             : 
    1015           0 :   return Base64Encode(aBinaryData, aAsciiBase64String);
    1016             : }
    1017             : 
    1018             : nsresult
    1019           0 : nsContentUtils::Atob(const nsAString& aAsciiBase64String,
    1020             :                      nsAString& aBinaryData)
    1021             : {
    1022           0 :   if (!Is8bit(aAsciiBase64String)) {
    1023           0 :     aBinaryData.Truncate();
    1024           0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    1025             :   }
    1026             : 
    1027           0 :   const char16_t* start = aAsciiBase64String.BeginReading();
    1028           0 :   const char16_t* end = aAsciiBase64String.EndReading();
    1029           0 :   nsString trimmedString;
    1030           0 :   if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
    1031           0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    1032             :   }
    1033           0 :   while (start < end) {
    1034           0 :     if (!nsContentUtils::IsHTMLWhitespace(*start)) {
    1035           0 :       trimmedString.Append(*start);
    1036             :     }
    1037           0 :     start++;
    1038             :   }
    1039           0 :   nsresult rv = Base64Decode(trimmedString, aBinaryData);
    1040           0 :   if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
    1041           0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    1042             :   }
    1043           0 :   return rv;
    1044             : }
    1045             : 
    1046             : bool
    1047           0 : nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
    1048             : {
    1049           0 :   NS_PRECONDITION(aInput, "aInput should not be null!");
    1050             : 
    1051           0 :   nsAutoString autocomplete;
    1052           0 :   aInput->GetAutocomplete(autocomplete);
    1053             : 
    1054           0 :   if (autocomplete.IsEmpty()) {
    1055           0 :     nsCOMPtr<nsIDOMHTMLFormElement> form;
    1056           0 :     aInput->GetForm(getter_AddRefs(form));
    1057           0 :     if (!form) {
    1058           0 :       return true;
    1059             :     }
    1060             : 
    1061           0 :     form->GetAutocomplete(autocomplete);
    1062             :   }
    1063             : 
    1064           0 :   return !autocomplete.EqualsLiteral("off");
    1065             : }
    1066             : 
    1067             : nsContentUtils::AutocompleteAttrState
    1068           0 : nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
    1069             :                                                nsAString& aResult,
    1070             :                                                AutocompleteAttrState aCachedState)
    1071             : {
    1072           0 :   if (!aAttr ||
    1073             :       aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
    1074           0 :     return aCachedState;
    1075             :   }
    1076             : 
    1077           0 :   if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
    1078           0 :     uint32_t atomCount = aAttr->GetAtomCount();
    1079           0 :     for (uint32_t i = 0; i < atomCount; i++) {
    1080           0 :       if (i != 0) {
    1081           0 :         aResult.Append(' ');
    1082             :       }
    1083           0 :       aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
    1084             :     }
    1085           0 :     nsContentUtils::ASCIIToLower(aResult);
    1086           0 :     return aCachedState;
    1087             :   }
    1088             : 
    1089           0 :   aResult.Truncate();
    1090             : 
    1091           0 :   mozilla::dom::AutocompleteInfo info;
    1092             :   AutocompleteAttrState state =
    1093           0 :     InternalSerializeAutocompleteAttribute(aAttr, info);
    1094           0 :   if (state == eAutocompleteAttrState_Valid) {
    1095             :     // Concatenate the info fields.
    1096           0 :     aResult = info.mSection;
    1097             : 
    1098           0 :     if (!info.mAddressType.IsEmpty()) {
    1099           0 :       if (!aResult.IsEmpty()) {
    1100           0 :         aResult += ' ';
    1101             :       }
    1102           0 :       aResult += info.mAddressType;
    1103             :     }
    1104             : 
    1105           0 :     if (!info.mContactType.IsEmpty()) {
    1106           0 :       if (!aResult.IsEmpty()) {
    1107           0 :         aResult += ' ';
    1108             :       }
    1109           0 :       aResult += info.mContactType;
    1110             :     }
    1111             : 
    1112           0 :     if (!info.mFieldName.IsEmpty()) {
    1113           0 :       if (!aResult.IsEmpty()) {
    1114           0 :         aResult += ' ';
    1115             :       }
    1116           0 :       aResult += info.mFieldName;
    1117             :     }
    1118             :   }
    1119             : 
    1120           0 :   return state;
    1121             : }
    1122             : 
    1123             : nsContentUtils::AutocompleteAttrState
    1124           0 : nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
    1125             :                                                mozilla::dom::AutocompleteInfo& aInfo,
    1126             :                                                AutocompleteAttrState aCachedState,
    1127             :                                                bool aGrantAllValidValue)
    1128             : {
    1129           0 :   if (!aAttr ||
    1130             :       aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
    1131           0 :     return aCachedState;
    1132             :   }
    1133             : 
    1134           0 :   return InternalSerializeAutocompleteAttribute(aAttr, aInfo, aGrantAllValidValue);
    1135             : }
    1136             : 
    1137             : /**
    1138             :  * Helper to validate the @autocomplete tokens.
    1139             :  *
    1140             :  * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
    1141             :  */
    1142             : nsContentUtils::AutocompleteAttrState
    1143           0 : nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
    1144             :                                                        mozilla::dom::AutocompleteInfo& aInfo,
    1145             :                                                        bool aGrantAllValidValue)
    1146             : {
    1147             :   // No sandbox attribute so we are done
    1148           0 :   if (!aAttrVal) {
    1149           0 :     return eAutocompleteAttrState_Invalid;
    1150             :   }
    1151             : 
    1152           0 :   uint32_t numTokens = aAttrVal->GetAtomCount();
    1153           0 :   if (!numTokens) {
    1154           0 :     return eAutocompleteAttrState_Invalid;
    1155             :   }
    1156             : 
    1157           0 :   uint32_t index = numTokens - 1;
    1158           0 :   nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
    1159             :   AutocompleteCategory category;
    1160           0 :   nsAttrValue enumValue;
    1161             : 
    1162           0 :   bool unsupported = false;
    1163           0 :   if (!aGrantAllValidValue) {
    1164             :     unsupported = enumValue.ParseEnumValue(tokenString,
    1165             :                                            kAutocompleteUnsupportedFieldNameTable,
    1166           0 :                                            false);
    1167           0 :     if (unsupported) {
    1168           0 :       return eAutocompleteAttrState_Invalid;
    1169             :     }
    1170             :   }
    1171             : 
    1172           0 :   nsAutoString str;
    1173           0 :   bool result = enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
    1174           0 :   if (result) {
    1175             :     // Off/Automatic/Normal categories.
    1176           0 :     if (enumValue.Equals(NS_LITERAL_STRING("off"), eIgnoreCase) ||
    1177           0 :         enumValue.Equals(NS_LITERAL_STRING("on"), eIgnoreCase)) {
    1178           0 :       if (numTokens > 1) {
    1179           0 :         return eAutocompleteAttrState_Invalid;
    1180             :       }
    1181           0 :       enumValue.ToString(str);
    1182           0 :       ASCIIToLower(str);
    1183           0 :       aInfo.mFieldName.Assign(str);
    1184           0 :       return eAutocompleteAttrState_Valid;
    1185             :     }
    1186             : 
    1187             :     // Only allow on/off if experimental @autocomplete values aren't enabled
    1188             :     // and it doesn't grant all valid values.
    1189           0 :     if (!sIsExperimentalAutocompleteEnabled && !aGrantAllValidValue) {
    1190           0 :       return eAutocompleteAttrState_Invalid;
    1191             :     }
    1192             : 
    1193             :     // Normal category
    1194           0 :     if (numTokens > 3) {
    1195           0 :       return eAutocompleteAttrState_Invalid;
    1196             :     }
    1197           0 :     category = eAutocompleteCategory_NORMAL;
    1198             :   } else { // Check if the last token is of the contact category instead.
    1199             :     // Only allow on/off if experimental @autocomplete values aren't enabled
    1200             :     // and it doesn't grant all valid values.
    1201           0 :     if (!sIsExperimentalAutocompleteEnabled && !aGrantAllValidValue) {
    1202           0 :       return eAutocompleteAttrState_Invalid;
    1203             :     }
    1204             : 
    1205           0 :     result = enumValue.ParseEnumValue(tokenString, kAutocompleteContactFieldNameTable, false);
    1206           0 :     if (!result || numTokens > 4) {
    1207           0 :       return eAutocompleteAttrState_Invalid;
    1208             :     }
    1209             : 
    1210           0 :     category = eAutocompleteCategory_CONTACT;
    1211             :   }
    1212             : 
    1213           0 :   enumValue.ToString(str);
    1214           0 :   ASCIIToLower(str);
    1215           0 :   aInfo.mFieldName.Assign(str);
    1216             : 
    1217             :   // We are done if this was the only token.
    1218           0 :   if (numTokens == 1) {
    1219           0 :     return eAutocompleteAttrState_Valid;
    1220             :   }
    1221             : 
    1222           0 :   --index;
    1223           0 :   tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
    1224             : 
    1225           0 :   if (category == eAutocompleteCategory_CONTACT) {
    1226           0 :     if (!aGrantAllValidValue) {
    1227             :       unsupported = enumValue.ParseEnumValue(tokenString,
    1228             :                                              kAutocompleteUnsupportedContactFieldHintTable,
    1229           0 :                                              false);
    1230           0 :       if (unsupported) {
    1231           0 :         return eAutocompleteAttrState_Invalid;
    1232             :       }
    1233             :     }
    1234             : 
    1235             : 
    1236           0 :     nsAttrValue contactFieldHint;
    1237           0 :     result = contactFieldHint.ParseEnumValue(tokenString, kAutocompleteContactFieldHintTable, false);
    1238           0 :     if (result) {
    1239           0 :       nsAutoString contactFieldHintString;
    1240           0 :       contactFieldHint.ToString(contactFieldHintString);
    1241           0 :       ASCIIToLower(contactFieldHintString);
    1242           0 :       aInfo.mContactType.Assign(contactFieldHintString);
    1243           0 :       if (index == 0) {
    1244           0 :         return eAutocompleteAttrState_Valid;
    1245             :       }
    1246           0 :       --index;
    1247           0 :       tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
    1248             :     }
    1249             :   }
    1250             : 
    1251             :   // Check for billing/shipping tokens
    1252           0 :   nsAttrValue fieldHint;
    1253           0 :   if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, false)) {
    1254           0 :     nsString fieldHintString;
    1255           0 :     fieldHint.ToString(fieldHintString);
    1256           0 :     ASCIIToLower(fieldHintString);
    1257           0 :     aInfo.mAddressType.Assign(fieldHintString);
    1258           0 :     if (index == 0) {
    1259           0 :       return eAutocompleteAttrState_Valid;
    1260             :     }
    1261           0 :     --index;
    1262           0 :     tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
    1263             :   }
    1264             : 
    1265             :   // Check for section-* token
    1266           0 :   const nsDependentSubstring& section = Substring(tokenString, 0, 8);
    1267           0 :   if (section.LowerCaseEqualsASCII("section-")) {
    1268           0 :     ASCIIToLower(tokenString);
    1269           0 :     aInfo.mSection.Assign(tokenString);
    1270           0 :     if (index == 0) {
    1271           0 :       return eAutocompleteAttrState_Valid;
    1272             :     }
    1273             :   }
    1274             : 
    1275             :   // Clear the fields as the autocomplete attribute is invalid.
    1276           0 :   aInfo.mSection.Truncate();
    1277           0 :   aInfo.mAddressType.Truncate();
    1278           0 :   aInfo.mContactType.Truncate();
    1279           0 :   aInfo.mFieldName.Truncate();
    1280             : 
    1281           0 :   return eAutocompleteAttrState_Invalid;
    1282             : }
    1283             : 
    1284             : // Parse an integer according to HTML spec
    1285             : int32_t
    1286           0 : nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
    1287             :                                  ParseHTMLIntegerResultFlags *aResult)
    1288             : {
    1289           0 :   int result = eParseHTMLInteger_NoFlags;
    1290             : 
    1291           0 :   nsAString::const_iterator iter, end;
    1292           0 :   aValue.BeginReading(iter);
    1293           0 :   aValue.EndReading(end);
    1294             : 
    1295           0 :   while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
    1296           0 :     result |= eParseHTMLInteger_NonStandard;
    1297           0 :     ++iter;
    1298             :   }
    1299             : 
    1300           0 :   if (iter == end) {
    1301           0 :     result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
    1302           0 :     *aResult = (ParseHTMLIntegerResultFlags)result;
    1303           0 :     return 0;
    1304             :   }
    1305             : 
    1306           0 :   int sign = 1;
    1307           0 :   if (*iter == char16_t('-')) {
    1308           0 :     sign = -1;
    1309           0 :     result |= eParseHTMLInteger_Negative;
    1310           0 :     ++iter;
    1311           0 :   } else if (*iter == char16_t('+')) {
    1312           0 :     result |= eParseHTMLInteger_NonStandard;
    1313           0 :     ++iter;
    1314             :   }
    1315             : 
    1316           0 :   bool foundValue = false;
    1317           0 :   CheckedInt32 value = 0;
    1318             : 
    1319             :   // Check for leading zeros first.
    1320           0 :   uint64_t leadingZeros = 0;
    1321           0 :   while (iter != end) {
    1322           0 :     if (*iter != char16_t('0')) {
    1323           0 :       break;
    1324             :     }
    1325             : 
    1326           0 :     ++leadingZeros;
    1327           0 :     foundValue = true;
    1328           0 :     ++iter;
    1329             :   }
    1330             : 
    1331           0 :   while (iter != end) {
    1332           0 :     if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
    1333           0 :       value = (value * 10) + (*iter - char16_t('0')) * sign;
    1334           0 :       ++iter;
    1335           0 :       if (!value.isValid()) {
    1336           0 :         result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
    1337           0 :         break;
    1338             :       }
    1339           0 :       foundValue = true;
    1340           0 :     } else if (*iter == char16_t('%')) {
    1341           0 :       ++iter;
    1342           0 :       result |= eParseHTMLInteger_IsPercent;
    1343           0 :       break;
    1344             :     } else {
    1345           0 :       break;
    1346             :     }
    1347             :   }
    1348             : 
    1349           0 :   if (!foundValue) {
    1350           0 :     result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
    1351             :   }
    1352             : 
    1353           0 :   if (value.isValid() &&
    1354           0 :        ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
    1355           0 :        (sign == -1 && value == 0))) {
    1356           0 :     result |= eParseHTMLInteger_NonStandard;
    1357             :   }
    1358             : 
    1359           0 :   if (iter != end) {
    1360           0 :     result |= eParseHTMLInteger_DidNotConsumeAllInput;
    1361             :   }
    1362             : 
    1363           0 :   *aResult = (ParseHTMLIntegerResultFlags)result;
    1364           0 :   return value.isValid() ? value.value() : 0;
    1365             : }
    1366             : 
    1367             : #define SKIP_WHITESPACE(iter, end_iter, end_res)                 \
    1368             :   while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
    1369             :     ++(iter);                                                    \
    1370             :   }                                                              \
    1371             :   if ((iter) == (end_iter)) {                                    \
    1372             :     return (end_res);                                            \
    1373             :   }
    1374             : 
    1375             : #define SKIP_ATTR_NAME(iter, end_iter)                            \
    1376             :   while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
    1377             :          *(iter) != '=') {                                        \
    1378             :     ++(iter);                                                     \
    1379             :   }
    1380             : 
    1381             : bool
    1382          33 : nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
    1383             :                                         nsAString& aValue)
    1384             : {
    1385          33 :   aValue.Truncate();
    1386             : 
    1387          33 :   const char16_t *start = aSource.get();
    1388          33 :   const char16_t *end = start + aSource.Length();
    1389             :   const char16_t *iter;
    1390             : 
    1391         117 :   while (start != end) {
    1392          81 :     SKIP_WHITESPACE(start, end, false)
    1393          57 :     iter = start;
    1394         285 :     SKIP_ATTR_NAME(iter, end)
    1395             : 
    1396          57 :     if (start == iter) {
    1397           0 :       return false;
    1398             :     }
    1399             : 
    1400             :     // Remember the attr name.
    1401          99 :     const nsDependentSubstring & attrName = Substring(start, iter);
    1402             : 
    1403             :     // Now check whether this is a valid name="value" pair.
    1404          57 :     start = iter;
    1405          57 :     SKIP_WHITESPACE(start, end, false)
    1406          57 :     if (*start != '=') {
    1407             :       // No '=', so this is not a name="value" pair.  We don't know
    1408             :       // what it is, and we have no way to handle it.
    1409           0 :       return false;
    1410             :     }
    1411             : 
    1412             :     // Have to skip the value.
    1413          57 :     ++start;
    1414          57 :     SKIP_WHITESPACE(start, end, false)
    1415          57 :     char16_t q = *start;
    1416          57 :     if (q != kQuote && q != kApostrophe) {
    1417             :       // Not a valid quoted value, so bail.
    1418           0 :       return false;
    1419             :     }
    1420             : 
    1421          57 :     ++start;  // Point to the first char of the value.
    1422          57 :     iter = start;
    1423             : 
    1424        3163 :     while (iter != end && *iter != q) {
    1425        1553 :       ++iter;
    1426             :     }
    1427             : 
    1428          57 :     if (iter == end) {
    1429             :       // Oops, unterminated quoted string.
    1430           0 :       return false;
    1431             :     }
    1432             : 
    1433             :     // At this point attrName holds the name of the "attribute" and
    1434             :     // the value is between start and iter.
    1435             : 
    1436          57 :     if (aName->Equals(attrName)) {
    1437             :       // We'll accumulate as many characters as possible (until we hit either
    1438             :       // the end of the string or the beginning of an entity). Chunks will be
    1439             :       // delimited by start and chunkEnd.
    1440          15 :       const char16_t *chunkEnd = start;
    1441         873 :       while (chunkEnd != iter) {
    1442         429 :         if (*chunkEnd == kLessThan) {
    1443           0 :           aValue.Truncate();
    1444             : 
    1445           0 :           return false;
    1446             :         }
    1447             : 
    1448         429 :         if (*chunkEnd == kAmpersand) {
    1449           0 :           aValue.Append(start, chunkEnd - start);
    1450             : 
    1451           0 :           const char16_t *afterEntity = nullptr;
    1452             :           char16_t result[2];
    1453             :           uint32_t count =
    1454           0 :             MOZ_XMLTranslateEntity(reinterpret_cast<const char*>(chunkEnd),
    1455             :                                    reinterpret_cast<const char*>(iter),
    1456             :                                    reinterpret_cast<const char**>(&afterEntity),
    1457           0 :                                    result);
    1458           0 :           if (count == 0) {
    1459           0 :             aValue.Truncate();
    1460             : 
    1461           0 :             return false;
    1462             :           }
    1463             : 
    1464           0 :           aValue.Append(result, count);
    1465             : 
    1466             :           // Advance to after the entity and begin a new chunk.
    1467           0 :           start = chunkEnd = afterEntity;
    1468             :         }
    1469             :         else {
    1470         429 :           ++chunkEnd;
    1471             :         }
    1472             :       }
    1473             : 
    1474             :       // Append remainder.
    1475          15 :       aValue.Append(start, iter - start);
    1476             : 
    1477          15 :       return true;
    1478             :     }
    1479             : 
    1480             :     // Resume scanning after the end of the attribute value (past the quote
    1481             :     // char).
    1482          42 :     start = iter + 1;
    1483             :   }
    1484             : 
    1485          18 :   return false;
    1486             : }
    1487             : 
    1488             : bool
    1489           0 : nsContentUtils::IsJavaScriptLanguage(const nsString& aName)
    1490             : {
    1491           0 :   return aName.LowerCaseEqualsLiteral("javascript") ||
    1492           0 :          aName.LowerCaseEqualsLiteral("livescript") ||
    1493           0 :          aName.LowerCaseEqualsLiteral("mocha") ||
    1494           0 :          aName.LowerCaseEqualsLiteral("javascript1.0") ||
    1495           0 :          aName.LowerCaseEqualsLiteral("javascript1.1") ||
    1496           0 :          aName.LowerCaseEqualsLiteral("javascript1.2") ||
    1497           0 :          aName.LowerCaseEqualsLiteral("javascript1.3") ||
    1498           0 :          aName.LowerCaseEqualsLiteral("javascript1.4") ||
    1499           0 :          aName.LowerCaseEqualsLiteral("javascript1.5");
    1500             : }
    1501             : 
    1502             : JSVersion
    1503           0 : nsContentUtils::ParseJavascriptVersion(const nsAString& aVersionStr)
    1504             : {
    1505           0 :   if (aVersionStr.Length() != 3 || aVersionStr[0] != '1' ||
    1506           0 :       aVersionStr[1] != '.') {
    1507           0 :     return JSVERSION_UNKNOWN;
    1508             :   }
    1509             : 
    1510           0 :   switch (aVersionStr[2]) {
    1511             :   case '0': /* fall through */
    1512             :   case '1': /* fall through */
    1513             :   case '2': /* fall through */
    1514             :   case '3': /* fall through */
    1515             :   case '4': /* fall through */
    1516           0 :   case '5': return JSVERSION_DEFAULT;
    1517           0 :   case '6': return JSVERSION_1_6;
    1518           0 :   case '7': return JSVERSION_1_7;
    1519           0 :   case '8': return JSVERSION_1_8;
    1520           0 :   default:  return JSVERSION_UNKNOWN;
    1521             :   }
    1522             : }
    1523             : 
    1524             : void
    1525           6 : nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
    1526             :                               nsString& aParams)
    1527             : {
    1528           6 :   aType.Truncate();
    1529           6 :   aParams.Truncate();
    1530           6 :   int32_t semiIndex = aValue.FindChar(char16_t(';'));
    1531           6 :   if (-1 != semiIndex) {
    1532           0 :     aType = Substring(aValue, 0, semiIndex);
    1533           0 :     aParams = Substring(aValue, semiIndex + 1,
    1534           0 :                        aValue.Length() - (semiIndex + 1));
    1535           0 :     aParams.StripWhitespace();
    1536             :   }
    1537             :   else {
    1538           6 :     aType = aValue;
    1539             :   }
    1540           6 :   aType.StripWhitespace();
    1541           6 : }
    1542             : 
    1543             : nsresult
    1544           0 : nsContentUtils::IsUserIdle(uint32_t aRequestedIdleTimeInMS, bool* aUserIsIdle)
    1545             : {
    1546             :   nsresult rv;
    1547             :   nsCOMPtr<nsIIdleService> idleService =
    1548           0 :     do_GetService("@mozilla.org/widget/idleservice;1", &rv);
    1549           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1550             : 
    1551             :   uint32_t idleTimeInMS;
    1552           0 :   rv = idleService->GetIdleTime(&idleTimeInMS);
    1553           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1554             : 
    1555           0 :   *aUserIsIdle = idleTimeInMS >= aRequestedIdleTimeInMS;
    1556           0 :   return NS_OK;
    1557             : }
    1558             : 
    1559             : /**
    1560             :  * Access a cached parser service. Don't addref. We need only one
    1561             :  * reference to it and this class has that one.
    1562             :  */
    1563             : /* static */
    1564             : nsIParserService*
    1565          74 : nsContentUtils::GetParserService()
    1566             : {
    1567             :   // XXX: This isn't accessed from several threads, is it?
    1568          74 :   if (!sParserService) {
    1569             :     // Lock, recheck sCachedParserService and aquire if this should be
    1570             :     // safe for multiple threads.
    1571           2 :     nsresult rv = CallGetService(kParserServiceCID, &sParserService);
    1572           2 :     if (NS_FAILED(rv)) {
    1573           0 :       sParserService = nullptr;
    1574             :     }
    1575             :   }
    1576             : 
    1577          74 :   return sParserService;
    1578             : }
    1579             : 
    1580             : /**
    1581             : * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
    1582             : * directive) and converts it to the set of flags used internally.
    1583             : *
    1584             : * @param aSandboxAttr  the sandbox attribute
    1585             : * @return              the set of flags (SANDBOXED_NONE if aSandboxAttr is
    1586             : *                      null)
    1587             : */
    1588             : uint32_t
    1589           0 : nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr)
    1590             : {
    1591           0 :   if (!aSandboxAttr) {
    1592           0 :     return SANDBOXED_NONE;
    1593             :   }
    1594             : 
    1595           0 :   uint32_t out = SANDBOX_ALL_FLAGS;
    1596             : 
    1597             : #define SANDBOX_KEYWORD(string, atom, flags)                  \
    1598             :   if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
    1599             :     out &= ~(flags);                                          \
    1600             :   }
    1601             : #include "IframeSandboxKeywordList.h"
    1602             : #undef SANDBOX_KEYWORD
    1603             : 
    1604           0 :   return out;
    1605             : }
    1606             : 
    1607             : /**
    1608             : * A helper function that checks if a string matches a valid sandbox flag.
    1609             : *
    1610             : * @param aFlag   the potential sandbox flag.
    1611             : * @return        true if the flag is a sandbox flag.
    1612             : */
    1613             : bool
    1614           0 : nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag)
    1615             : {
    1616             : #define SANDBOX_KEYWORD(string, atom, flags)                                  \
    1617             :   if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
    1618             :     return true;                                                              \
    1619             :   }
    1620             : #include "IframeSandboxKeywordList.h"
    1621             : #undef SANDBOX_KEYWORD
    1622           0 :   return false;
    1623             : }
    1624             : 
    1625             : /**
    1626             :  * A helper function that returns a string attribute corresponding to the
    1627             :  * sandbox flags.
    1628             :  *
    1629             :  * @param aFlags    the sandbox flags
    1630             :  * @param aString   the attribute corresponding to the flags (null if aFlags
    1631             :  *                  is zero)
    1632             :  */
    1633             : void
    1634           0 : nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString)
    1635             : {
    1636           0 :   if (!aFlags) {
    1637           0 :     SetDOMStringToNull(aString);
    1638           0 :     return;
    1639             :   }
    1640             : 
    1641           0 :   aString.Truncate();
    1642             : 
    1643             : #define SANDBOX_KEYWORD(string, atom, flags)                \
    1644             :   if (!(aFlags & (flags))) {                                \
    1645             :     if (!aString.IsEmpty()) {                               \
    1646             :       aString.Append(NS_LITERAL_STRING(" "));               \
    1647             :     }                                                       \
    1648             :     aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
    1649             :   }
    1650             : #include "IframeSandboxKeywordList.h"
    1651             : #undef SANDBOX_KEYWORD
    1652             : }
    1653             : 
    1654             : nsIBidiKeyboard*
    1655           4 : nsContentUtils::GetBidiKeyboard()
    1656             : {
    1657           4 :   if (!sBidiKeyboard) {
    1658           3 :     nsresult rv = CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
    1659           3 :     if (NS_FAILED(rv)) {
    1660           0 :       sBidiKeyboard = nullptr;
    1661             :     }
    1662             :   }
    1663           4 :   return sBidiKeyboard;
    1664             : }
    1665             : 
    1666             : template <class OutputIterator>
    1667             : struct NormalizeNewlinesCharTraits {
    1668             :   public:
    1669             :     typedef typename OutputIterator::value_type value_type;
    1670             : 
    1671             :   public:
    1672           0 :     explicit NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { }
    1673           0 :     void writechar(typename OutputIterator::value_type aChar) {
    1674           0 :       *mIterator++ = aChar;
    1675           0 :     }
    1676             : 
    1677             :   private:
    1678             :     OutputIterator mIterator;
    1679             : };
    1680             : 
    1681             : template <class CharT>
    1682             : struct NormalizeNewlinesCharTraits<CharT*> {
    1683             :   public:
    1684             :     typedef CharT value_type;
    1685             : 
    1686             :   public:
    1687           0 :     explicit NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { }
    1688           0 :     void writechar(CharT aChar) {
    1689           0 :       *mCharPtr++ = aChar;
    1690           0 :     }
    1691             : 
    1692             :   private:
    1693             :     CharT* mCharPtr;
    1694             : };
    1695             : 
    1696             : template <class OutputIterator>
    1697             : class CopyNormalizeNewlines
    1698             : {
    1699             :   public:
    1700             :     typedef typename OutputIterator::value_type value_type;
    1701             : 
    1702             :   public:
    1703           0 :     explicit CopyNormalizeNewlines(OutputIterator* aDestination,
    1704             :                                    bool aLastCharCR = false) :
    1705             :       mLastCharCR(aLastCharCR),
    1706             :       mDestination(aDestination),
    1707           0 :       mWritten(0)
    1708           0 :     { }
    1709             : 
    1710           0 :     uint32_t GetCharsWritten() {
    1711           0 :       return mWritten;
    1712             :     }
    1713             : 
    1714           0 :     bool IsLastCharCR() {
    1715           0 :       return mLastCharCR;
    1716             :     }
    1717             : 
    1718           0 :     void write(const typename OutputIterator::value_type* aSource, uint32_t aSourceLength) {
    1719             : 
    1720           0 :       const typename OutputIterator::value_type* done_writing = aSource + aSourceLength;
    1721             : 
    1722             :       // If the last source buffer ended with a CR...
    1723           0 :       if (mLastCharCR) {
    1724             :         // ..and if the next one is a LF, then skip it since
    1725             :         // we've already written out a newline
    1726           0 :         if (aSourceLength && (*aSource == value_type('\n'))) {
    1727           0 :           ++aSource;
    1728             :         }
    1729           0 :         mLastCharCR = false;
    1730             :       }
    1731             : 
    1732           0 :       uint32_t num_written = 0;
    1733           0 :       while ( aSource < done_writing ) {
    1734           0 :         if (*aSource == value_type('\r')) {
    1735           0 :           mDestination->writechar('\n');
    1736           0 :           ++aSource;
    1737             :           // If we've reached the end of the buffer, record
    1738             :           // that we wrote out a CR
    1739           0 :           if (aSource == done_writing) {
    1740           0 :             mLastCharCR = true;
    1741             :           }
    1742             :           // If the next character is a LF, skip it
    1743           0 :           else if (*aSource == value_type('\n')) {
    1744           0 :             ++aSource;
    1745             :           }
    1746             :         }
    1747             :         else {
    1748           0 :           mDestination->writechar(*aSource++);
    1749             :         }
    1750           0 :         ++num_written;
    1751             :       }
    1752             : 
    1753           0 :       mWritten += num_written;
    1754           0 :     }
    1755             : 
    1756             :   private:
    1757             :     bool mLastCharCR;
    1758             :     OutputIterator* mDestination;
    1759             :     uint32_t mWritten;
    1760             : };
    1761             : 
    1762             : // static
    1763             : uint32_t
    1764           0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString& aSource,
    1765             :                                                uint32_t aSrcOffset,
    1766             :                                                char16_t* aDest,
    1767             :                                                uint32_t aLength,
    1768             :                                                bool& aLastCharCR)
    1769             : {
    1770             :   typedef NormalizeNewlinesCharTraits<char16_t*> sink_traits;
    1771             : 
    1772           0 :   sink_traits dest_traits(aDest);
    1773           0 :   CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits,aLastCharCR);
    1774           0 :   nsReadingIterator<char16_t> fromBegin, fromEnd;
    1775           0 :   copy_string(aSource.BeginReading(fromBegin).advance( int32_t(aSrcOffset) ),
    1776           0 :               aSource.BeginReading(fromEnd).advance( int32_t(aSrcOffset+aLength) ),
    1777           0 :               normalizer);
    1778           0 :   aLastCharCR = normalizer.IsLastCharCR();
    1779           0 :   return normalizer.GetCharsWritten();
    1780             : }
    1781             : 
    1782             : // static
    1783             : uint32_t
    1784           0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator<char16_t>& aSrcStart, const nsReadingIterator<char16_t>& aSrcEnd, nsAString& aDest)
    1785             : {
    1786             :   typedef nsWritingIterator<char16_t> WritingIterator;
    1787             :   typedef NormalizeNewlinesCharTraits<WritingIterator> sink_traits;
    1788             : 
    1789           0 :   WritingIterator iter;
    1790           0 :   aDest.BeginWriting(iter);
    1791           0 :   sink_traits dest_traits(iter);
    1792           0 :   CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits);
    1793           0 :   copy_string(aSrcStart, aSrcEnd, normalizer);
    1794           0 :   return normalizer.GetCharsWritten();
    1795             : }
    1796             : 
    1797             : /**
    1798             :  * This is used to determine whether a character is in one of the classes
    1799             :  * which CSS says should be part of the first-letter.  Currently, that is
    1800             :  * all punctuation classes (P*).  Note that this is a change from CSS2
    1801             :  * which excluded Pc and Pd.
    1802             :  *
    1803             :  * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
    1804             :  * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
    1805             :  *  general category [UAX44]) [...]"
    1806             :  */
    1807             : 
    1808             : // static
    1809             : bool
    1810           0 : nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar)
    1811             : {
    1812           0 :   switch (mozilla::unicode::GetGeneralCategory(aChar)) {
    1813             :     case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
    1814             :     case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION:    /* Pd */
    1815             :     case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION:   /* Pe */
    1816             :     case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION:   /* Pf */
    1817             :     case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
    1818             :     case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION:   /* Po */
    1819             :     case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION:    /* Ps */
    1820           0 :       return true;
    1821             :     default:
    1822           0 :       return false;
    1823             :   }
    1824             : }
    1825             : 
    1826             : // static
    1827             : bool
    1828           0 : nsContentUtils::IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, uint32_t aOffset)
    1829             : {
    1830           0 :   char16_t h = aFrag->CharAt(aOffset);
    1831           0 :   if (!IS_SURROGATE(h)) {
    1832           0 :     return IsFirstLetterPunctuation(h);
    1833             :   }
    1834           0 :   if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
    1835           0 :     char16_t l = aFrag->CharAt(aOffset + 1);
    1836           0 :     if (NS_IS_LOW_SURROGATE(l)) {
    1837           0 :       return IsFirstLetterPunctuation(SURROGATE_TO_UCS4(h, l));
    1838             :     }
    1839             :   }
    1840           0 :   return false;
    1841             : }
    1842             : 
    1843             : // static
    1844           0 : bool nsContentUtils::IsAlphanumeric(uint32_t aChar)
    1845             : {
    1846           0 :   nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
    1847             : 
    1848           0 :   return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
    1849             : }
    1850             : 
    1851             : // static
    1852           0 : bool nsContentUtils::IsAlphanumericAt(const nsTextFragment* aFrag, uint32_t aOffset)
    1853             : {
    1854           0 :   char16_t h = aFrag->CharAt(aOffset);
    1855           0 :   if (!IS_SURROGATE(h)) {
    1856           0 :     return IsAlphanumeric(h);
    1857             :   }
    1858           0 :   if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
    1859           0 :     char16_t l = aFrag->CharAt(aOffset + 1);
    1860           0 :     if (NS_IS_LOW_SURROGATE(l)) {
    1861           0 :       return IsAlphanumeric(SURROGATE_TO_UCS4(h, l));
    1862             :     }
    1863             :   }
    1864           0 :   return false;
    1865             : }
    1866             : 
    1867             : /* static */
    1868             : bool
    1869       18101 : nsContentUtils::IsHTMLWhitespace(char16_t aChar)
    1870             : {
    1871       18101 :   return aChar == char16_t(0x0009) ||
    1872       18101 :          aChar == char16_t(0x000A) ||
    1873       18101 :          aChar == char16_t(0x000C) ||
    1874       36202 :          aChar == char16_t(0x000D) ||
    1875       18101 :          aChar == char16_t(0x0020);
    1876             : }
    1877             : 
    1878             : /* static */
    1879             : bool
    1880           0 : nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar)
    1881             : {
    1882           0 :   return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
    1883             : }
    1884             : 
    1885             : /* static */
    1886             : bool
    1887           0 : nsContentUtils::IsHTMLBlock(nsIContent* aContent)
    1888             : {
    1889           0 :   return aContent->IsAnyOfHTMLElements(nsGkAtoms::address,
    1890             :                                        nsGkAtoms::article,
    1891             :                                        nsGkAtoms::aside,
    1892             :                                        nsGkAtoms::blockquote,
    1893             :                                        nsGkAtoms::center,
    1894             :                                        nsGkAtoms::dir,
    1895             :                                        nsGkAtoms::div,
    1896             :                                        nsGkAtoms::dl, // XXX why not dt and dd?
    1897             :                                        nsGkAtoms::fieldset,
    1898             :                                        nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
    1899             :                                        nsGkAtoms::footer,
    1900             :                                        nsGkAtoms::form,
    1901             :                                        nsGkAtoms::h1,
    1902             :                                        nsGkAtoms::h2,
    1903             :                                        nsGkAtoms::h3,
    1904             :                                        nsGkAtoms::h4,
    1905             :                                        nsGkAtoms::h5,
    1906             :                                        nsGkAtoms::h6,
    1907             :                                        nsGkAtoms::header,
    1908             :                                        nsGkAtoms::hgroup,
    1909             :                                        nsGkAtoms::hr,
    1910             :                                        nsGkAtoms::li,
    1911             :                                        nsGkAtoms::listing,
    1912             :                                        nsGkAtoms::menu,
    1913             :                                        nsGkAtoms::multicol, // XXX get rid of this one?
    1914             :                                        nsGkAtoms::nav,
    1915             :                                        nsGkAtoms::ol,
    1916             :                                        nsGkAtoms::p,
    1917             :                                        nsGkAtoms::pre,
    1918             :                                        nsGkAtoms::section,
    1919             :                                        nsGkAtoms::table,
    1920             :                                        nsGkAtoms::ul,
    1921           0 :                                        nsGkAtoms::xmp);
    1922             : }
    1923             : 
    1924             : /* static */
    1925             : bool
    1926           2 : nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result)
    1927             : {
    1928           4 :   nsAutoString marginStr(aString);
    1929           2 :   marginStr.CompressWhitespace(true, true);
    1930           2 :   if (marginStr.IsEmpty()) {
    1931           2 :     return false;
    1932             :   }
    1933             : 
    1934           0 :   int32_t start = 0, end = 0;
    1935           0 :   for (int count = 0; count < 4; count++) {
    1936           0 :     if ((uint32_t)end >= marginStr.Length())
    1937           0 :       return false;
    1938             : 
    1939             :     // top, right, bottom, left
    1940           0 :     if (count < 3)
    1941           0 :       end = Substring(marginStr, start).FindChar(',');
    1942             :     else
    1943           0 :       end = Substring(marginStr, start).Length();
    1944             : 
    1945           0 :     if (end <= 0)
    1946           0 :       return false;
    1947             : 
    1948             :     nsresult ec;
    1949           0 :     int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec);
    1950           0 :     if (NS_FAILED(ec))
    1951           0 :       return false;
    1952             : 
    1953           0 :     switch(count) {
    1954             :       case 0:
    1955           0 :         result.top = val;
    1956           0 :       break;
    1957             :       case 1:
    1958           0 :         result.right = val;
    1959           0 :       break;
    1960             :       case 2:
    1961           0 :         result.bottom = val;
    1962           0 :       break;
    1963             :       case 3:
    1964           0 :         result.left = val;
    1965           0 :       break;
    1966             :     }
    1967           0 :     start += end + 1;
    1968             :   }
    1969           0 :   return true;
    1970             : }
    1971             : 
    1972             : // static
    1973             : int32_t
    1974           0 : nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
    1975             : {
    1976           0 :   nsAString::const_iterator iter, end;
    1977           0 :   aValue.BeginReading(iter);
    1978           0 :   aValue.EndReading(end);
    1979             : 
    1980           0 :   while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
    1981           0 :     ++iter;
    1982             :   }
    1983             : 
    1984           0 :   if (iter == end) {
    1985           0 :     return 0;
    1986             :   }
    1987             : 
    1988           0 :   bool relative = false;
    1989           0 :   bool negate = false;
    1990           0 :   if (*iter == char16_t('-')) {
    1991           0 :     relative = true;
    1992           0 :     negate = true;
    1993           0 :     ++iter;
    1994           0 :   } else if (*iter == char16_t('+')) {
    1995           0 :     relative = true;
    1996           0 :     ++iter;
    1997             :   }
    1998             : 
    1999           0 :   if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
    2000           0 :     return 0;
    2001             :   }
    2002             : 
    2003             :   // We don't have to worry about overflow, since we can bail out as soon as
    2004             :   // we're bigger than 7.
    2005           0 :   int32_t value = 0;
    2006           0 :   while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
    2007           0 :     value = 10*value + (*iter - char16_t('0'));
    2008           0 :     if (value >= 7) {
    2009           0 :       break;
    2010             :     }
    2011           0 :     ++iter;
    2012             :   }
    2013             : 
    2014           0 :   if (relative) {
    2015           0 :     if (negate) {
    2016           0 :       value = 3 - value;
    2017             :     } else {
    2018           0 :       value = 3 + value;
    2019             :     }
    2020             :   }
    2021             : 
    2022           0 :   return clamped(value, 1, 7);
    2023             : }
    2024             : 
    2025             : /* static */
    2026             : bool
    2027           3 : nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument)
    2028             : {
    2029           3 :   if (nsContentUtils::IsInPrivateBrowsing(aDocument)) {
    2030           0 :     return false;
    2031             :   }
    2032             : 
    2033             :   RefPtr<workers::ServiceWorkerManager> swm =
    2034           6 :     workers::ServiceWorkerManager::GetInstance();
    2035           3 :   MOZ_ASSERT(swm);
    2036             : 
    2037           6 :   ErrorResult rv;
    2038           3 :   bool controlled = swm->IsControlled(aDocument, rv);
    2039           3 :   if (NS_WARN_IF(rv.Failed())) {
    2040           0 :     rv.SuppressException();
    2041           0 :     return false;
    2042             :   }
    2043             : 
    2044           3 :   return controlled;
    2045             : }
    2046             : 
    2047             : /* static */
    2048             : void
    2049           0 : nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
    2050             : {
    2051           0 :   MOZ_ASSERT(NS_IsMainThread());
    2052           0 :   MOZ_ASSERT(aDocument);
    2053           0 :   *aURI = nullptr;
    2054             : 
    2055           0 :   if (IsControlledByServiceWorker(aDocument)) {
    2056           0 :     return;
    2057             :   }
    2058             : 
    2059           0 :   Element* docElement = aDocument->GetRootElement();
    2060           0 :   if (!docElement) {
    2061           0 :     return;
    2062             :   }
    2063             : 
    2064           0 :   nsAutoString manifestSpec;
    2065           0 :   docElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
    2066             : 
    2067             :   // Manifest URIs can't have fragment identifiers.
    2068           0 :   if (manifestSpec.IsEmpty() ||
    2069           0 :       manifestSpec.Contains('#')) {
    2070           0 :     return;
    2071             :   }
    2072             : 
    2073           0 :   nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
    2074             :                                             aDocument,
    2075           0 :                                             aDocument->GetDocBaseURI());
    2076             : }
    2077             : 
    2078             : /* static */
    2079             : bool
    2080           0 : nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
    2081             : {
    2082             :   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    2083           0 :     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    2084           0 :   if (!updateService) {
    2085           0 :     return false;
    2086             :   }
    2087             : 
    2088             :   bool allowed;
    2089             :   nsresult rv =
    2090           0 :     updateService->OfflineAppAllowedForURI(aURI,
    2091             :                                            Preferences::GetRootBranch(),
    2092           0 :                                            &allowed);
    2093           0 :   return NS_SUCCEEDED(rv) && allowed;
    2094             : }
    2095             : 
    2096             : /* static */
    2097             : bool
    2098           0 : nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
    2099             : {
    2100             :   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    2101           0 :     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    2102           0 :   if (!updateService) {
    2103           0 :     return false;
    2104             :   }
    2105             : 
    2106             :   bool allowed;
    2107           0 :   nsresult rv = updateService->OfflineAppAllowed(aPrincipal,
    2108             :                                                  Preferences::GetRootBranch(),
    2109           0 :                                                  &allowed);
    2110           0 :   return NS_SUCCEEDED(rv) && allowed;
    2111             : }
    2112             : 
    2113             : bool
    2114           0 : nsContentUtils::MaybeAllowOfflineAppByDefault(nsIPrincipal *aPrincipal)
    2115             : {
    2116           0 :   if (!Preferences::GetRootBranch())
    2117           0 :     return false;
    2118             : 
    2119             :   nsresult rv;
    2120             : 
    2121             :   bool allowedByDefault;
    2122           0 :   rv = Preferences::GetRootBranch()->GetBoolPref(
    2123           0 :     "offline-apps.allow_by_default", &allowedByDefault);
    2124           0 :   if (NS_FAILED(rv))
    2125           0 :     return false;
    2126             : 
    2127           0 :   if (!allowedByDefault)
    2128           0 :     return false;
    2129             : 
    2130             :   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    2131           0 :     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    2132           0 :   if (!updateService) {
    2133           0 :     return false;
    2134             :   }
    2135             : 
    2136           0 :   rv = updateService->AllowOfflineApp(aPrincipal);
    2137           0 :   return NS_SUCCEEDED(rv);
    2138             : }
    2139             : 
    2140             : // static
    2141             : void
    2142           0 : nsContentUtils::Shutdown()
    2143             : {
    2144           0 :   sInitialized = false;
    2145             : 
    2146           0 :   NS_IF_RELEASE(sContentPolicyService);
    2147           0 :   sTriedToGetContentPolicy = false;
    2148             :   uint32_t i;
    2149           0 :   for (i = 0; i < PropertiesFile_COUNT; ++i)
    2150           0 :     NS_IF_RELEASE(sStringBundles[i]);
    2151             : 
    2152           0 :   NS_IF_RELEASE(sStringBundleService);
    2153           0 :   NS_IF_RELEASE(sConsoleService);
    2154           0 :   sXPConnect = nullptr;
    2155           0 :   NS_IF_RELEASE(sSecurityManager);
    2156           0 :   NS_IF_RELEASE(sSystemPrincipal);
    2157           0 :   NS_IF_RELEASE(sNullSubjectPrincipal);
    2158           0 :   NS_IF_RELEASE(sParserService);
    2159           0 :   NS_IF_RELEASE(sIOService);
    2160           0 :   NS_IF_RELEASE(sUUIDGenerator);
    2161           0 :   NS_IF_RELEASE(sLineBreaker);
    2162           0 :   NS_IF_RELEASE(sWordBreaker);
    2163           0 :   NS_IF_RELEASE(sBidiKeyboard);
    2164             : 
    2165           0 :   delete sAtomEventTable;
    2166           0 :   sAtomEventTable = nullptr;
    2167           0 :   delete sStringEventTable;
    2168           0 :   sStringEventTable = nullptr;
    2169           0 :   delete sUserDefinedEvents;
    2170           0 :   sUserDefinedEvents = nullptr;
    2171             : 
    2172           0 :   if (sEventListenerManagersHash) {
    2173           0 :     NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0,
    2174             :                  "Event listener manager hash not empty at shutdown!");
    2175             : 
    2176             :     // See comment above.
    2177             : 
    2178             :     // However, we have to handle this table differently.  If it still
    2179             :     // has entries, we want to leak it too, so that we can keep it alive
    2180             :     // in case any elements are destroyed.  Because if they are, we need
    2181             :     // their event listener managers to be destroyed too, or otherwise
    2182             :     // it could leave dangling references in DOMClassInfo's preserved
    2183             :     // wrapper table.
    2184             : 
    2185           0 :     if (sEventListenerManagersHash->EntryCount() == 0) {
    2186           0 :       delete sEventListenerManagersHash;
    2187           0 :       sEventListenerManagersHash = nullptr;
    2188             :     }
    2189             :   }
    2190             : 
    2191           0 :   NS_ASSERTION(!sBlockedScriptRunners ||
    2192             :                sBlockedScriptRunners->Length() == 0,
    2193             :                "How'd this happen?");
    2194           0 :   delete sBlockedScriptRunners;
    2195           0 :   sBlockedScriptRunners = nullptr;
    2196             : 
    2197           0 :   delete sShiftText;
    2198           0 :   sShiftText = nullptr;
    2199           0 :   delete sControlText;
    2200           0 :   sControlText = nullptr;
    2201           0 :   delete sMetaText;
    2202           0 :   sMetaText = nullptr;
    2203           0 :   delete sOSText;
    2204           0 :   sOSText = nullptr;
    2205           0 :   delete sAltText;
    2206           0 :   sAltText = nullptr;
    2207           0 :   delete sModifierSeparator;
    2208           0 :   sModifierSeparator = nullptr;
    2209             : 
    2210           0 :   delete sJSBytecodeMimeType;
    2211           0 :   sJSBytecodeMimeType = nullptr;
    2212             : 
    2213           0 :   NS_IF_RELEASE(sSameOriginChecker);
    2214             : 
    2215           0 :   NS_IF_RELEASE(sStableStateEventTarget);
    2216             : 
    2217           0 :   if (sUserInteractionObserver) {
    2218           0 :     sUserInteractionObserver->Shutdown();
    2219           0 :     NS_RELEASE(sUserInteractionObserver);
    2220             :   }
    2221             : 
    2222           0 :   HTMLInputElement::Shutdown();
    2223           0 :   nsMappedAttributes::Shutdown();
    2224           0 : }
    2225             : 
    2226             : /**
    2227             :  * Checks whether two nodes come from the same origin. aTrustedNode is
    2228             :  * considered 'safe' in that a user can operate on it and that it isn't
    2229             :  * a js-object that implements nsIDOMNode.
    2230             :  * Never call this function with the first node provided by script, it
    2231             :  * must always be known to be a 'real' node!
    2232             :  */
    2233             : // static
    2234             : nsresult
    2235           4 : nsContentUtils::CheckSameOrigin(const nsINode *aTrustedNode,
    2236             :                                 nsIDOMNode *aUnTrustedNode)
    2237             : {
    2238           4 :   MOZ_ASSERT(aTrustedNode);
    2239             : 
    2240             :   // Make sure it's a real node.
    2241           8 :   nsCOMPtr<nsINode> unTrustedNode = do_QueryInterface(aUnTrustedNode);
    2242           4 :   NS_ENSURE_TRUE(unTrustedNode, NS_ERROR_UNEXPECTED);
    2243           4 :   return CheckSameOrigin(aTrustedNode, unTrustedNode);
    2244             : }
    2245             : 
    2246             : nsresult
    2247         288 : nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
    2248             :                                 const nsINode* unTrustedNode)
    2249             : {
    2250         288 :   MOZ_ASSERT(aTrustedNode);
    2251         288 :   MOZ_ASSERT(unTrustedNode);
    2252             : 
    2253             :   /*
    2254             :    * Get hold of each node's principal
    2255             :    */
    2256             : 
    2257         288 :   nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
    2258         288 :   nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
    2259             : 
    2260         288 :   if (trustedPrincipal == unTrustedPrincipal) {
    2261         288 :     return NS_OK;
    2262             :   }
    2263             : 
    2264             :   bool equal;
    2265             :   // XXXbz should we actually have a Subsumes() check here instead?  Or perhaps
    2266             :   // a separate method for that, with callers using one or the other?
    2267           0 :   if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal)) ||
    2268           0 :       !equal) {
    2269           0 :     return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    2270             :   }
    2271             : 
    2272           0 :   return NS_OK;
    2273             : }
    2274             : 
    2275             : // static
    2276             : bool
    2277           4 : nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
    2278             :                                 nsIPrincipal* aPrincipal)
    2279             : {
    2280             :   bool subsumes;
    2281           4 :   nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
    2282           4 :   NS_ENSURE_SUCCESS(rv, false);
    2283             : 
    2284           4 :   if (subsumes) {
    2285           4 :     return true;
    2286             :   }
    2287             : 
    2288             :   // The subject doesn't subsume aPrincipal. Allow access only if the subject
    2289             :   // is chrome.
    2290           0 :   return IsCallerChrome();
    2291             : }
    2292             : 
    2293             : // static
    2294             : bool
    2295           0 : nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
    2296             : {
    2297           0 :   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
    2298           0 :   NS_ENSURE_TRUE(node, false);
    2299           0 :   return CanCallerAccess(node);
    2300             : }
    2301             : 
    2302             : // static
    2303             : bool
    2304           4 : nsContentUtils::CanCallerAccess(nsINode* aNode)
    2305             : {
    2306           4 :   return CanCallerAccess(SubjectPrincipal(), aNode->NodePrincipal());
    2307             : }
    2308             : 
    2309             : // static
    2310             : bool
    2311           0 : nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow)
    2312             : {
    2313           0 :   nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
    2314           0 :   NS_ENSURE_TRUE(scriptObject, false);
    2315             : 
    2316           0 :   return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
    2317             : }
    2318             : 
    2319             : // static
    2320             : bool
    2321           0 : nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm)
    2322             : {
    2323             :   // Chrome gets access by default.
    2324           0 :   if (IsSystemPrincipal(aPrincipal)) {
    2325           0 :     return true;
    2326             :   }
    2327             : 
    2328             :   // Otherwise, only allow if caller is an addon with the permission.
    2329           0 :   return BasePrincipal::Cast(aPrincipal)->AddonHasPermission(aPerm);
    2330             : }
    2331             : 
    2332             : // static
    2333             : bool
    2334           0 : nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
    2335             : {
    2336           0 :   return PrincipalHasPermission(SubjectPrincipal(aCx), aPerm);
    2337             : }
    2338             : 
    2339             : //static
    2340             : bool
    2341           9 : nsContentUtils::InProlog(nsINode *aNode)
    2342             : {
    2343           9 :   NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
    2344             : 
    2345           9 :   nsINode* parent = aNode->GetParentNode();
    2346           9 :   if (!parent || !parent->IsNodeOfType(nsINode::eDOCUMENT)) {
    2347           0 :     return false;
    2348             :   }
    2349             : 
    2350           9 :   nsIDocument* doc = static_cast<nsIDocument*>(parent);
    2351           9 :   nsIContent* root = doc->GetRootElement();
    2352             : 
    2353           9 :   return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
    2354             : }
    2355             : 
    2356             : nsIDocument*
    2357           0 : nsContentUtils::GetDocumentFromCaller()
    2358             : {
    2359           0 :   AutoJSContext cx;
    2360             : 
    2361             :   nsCOMPtr<nsPIDOMWindowInner> win =
    2362           0 :     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(cx)));
    2363           0 :   if (!win) {
    2364           0 :     return nullptr;
    2365             :   }
    2366             : 
    2367           0 :   return win->GetExtantDoc();
    2368             : }
    2369             : 
    2370             : bool
    2371        9253 : nsContentUtils::IsCallerChrome()
    2372             : {
    2373        9253 :   MOZ_ASSERT(NS_IsMainThread());
    2374        9253 :   if (SubjectPrincipal() == sSystemPrincipal) {
    2375        9196 :     return true;
    2376             :   }
    2377             : 
    2378             :   // If the check failed, look for UniversalXPConnect on the cx compartment.
    2379          57 :   return xpc::IsUniversalXPConnectEnabled(GetCurrentJSContext());
    2380             : }
    2381             : 
    2382             : /* static */
    2383             : bool
    2384          34 : nsContentUtils::ShouldResistFingerprinting()
    2385             : {
    2386          34 :   if (NS_IsMainThread()) {
    2387          34 :     return nsRFPService::IsResistFingerprintingEnabled();
    2388             :   }
    2389             : 
    2390           0 :   workers::WorkerPrivate* workerPrivate = workers::GetCurrentThreadWorkerPrivate();
    2391           0 :   if (NS_WARN_IF(!workerPrivate)) {
    2392           0 :     return false;
    2393             :   }
    2394           0 :   workerPrivate->AssertIsOnWorkerThread();
    2395             : 
    2396           0 :   return workerPrivate->ResistFingerprintingEnabled();
    2397             : }
    2398             : 
    2399             : bool
    2400         152 : nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell)
    2401             : {
    2402         152 :   if (!aDocShell) {
    2403           8 :     return false;
    2404             :   }
    2405         144 :   bool isChrome = nsContentUtils::IsChromeDoc(aDocShell->GetDocument());
    2406         144 :   return !isChrome && ShouldResistFingerprinting();
    2407             : }
    2408             : 
    2409             : /* static */
    2410             : void
    2411           0 : nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(int32_t  aChromeWidth,
    2412             :                                                                 int32_t  aChromeHeight,
    2413             :                                                                 int32_t  aScreenWidth,
    2414             :                                                                 int32_t  aScreenHeight,
    2415             :                                                                 int32_t  aInputWidth,
    2416             :                                                                 int32_t  aInputHeight,
    2417             :                                                                 bool     aSetOuterWidth,
    2418             :                                                                 bool     aSetOuterHeight,
    2419             :                                                                 int32_t* aOutputWidth,
    2420             :                                                                 int32_t* aOutputHeight)
    2421             : {
    2422           0 :   MOZ_ASSERT(aOutputWidth);
    2423           0 :   MOZ_ASSERT(aOutputHeight);
    2424             : 
    2425           0 :   int32_t availContentWidth  = 0;
    2426           0 :   int32_t availContentHeight = 0;
    2427             : 
    2428           0 :   availContentWidth = std::min(sPrivacyMaxInnerWidth,
    2429           0 :                                aScreenWidth - aChromeWidth);
    2430             : #ifdef MOZ_WIDGET_GTK
    2431             :   // In the GTK window, it will not report outside system decorations
    2432             :   // when we get available window size, see Bug 581863. So, we leave a
    2433             :   // 40 pixels space for them when calculating the available content
    2434             :   // height. It is not necessary for the width since the content width
    2435             :   // is usually pretty much the same as the chrome width.
    2436           0 :   availContentHeight = std::min(sPrivacyMaxInnerHeight,
    2437           0 :                                 (-40 + aScreenHeight) - aChromeHeight);
    2438             : #else
    2439             :   availContentHeight = std::min(sPrivacyMaxInnerHeight,
    2440             :                                 aScreenHeight - aChromeHeight);
    2441             : #endif
    2442             : 
    2443             :   // Ideally, we'd like to round window size to 1000x1000, but the
    2444             :   // screen space could be too small to accommodate this size in some
    2445             :   // cases. If it happens, we would round the window size to the nearest
    2446             :   // 200x100.
    2447           0 :   availContentWidth = availContentWidth - (availContentWidth % 200);
    2448           0 :   availContentHeight = availContentHeight - (availContentHeight % 100);
    2449             : 
    2450             :   // If aIsOuter is true, we are setting the outer window. So we
    2451             :   // have to consider the chrome UI.
    2452           0 :   int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
    2453           0 :   int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
    2454           0 :   int32_t resultWidth = 0, resultHeight = 0;
    2455             : 
    2456             :   // if the original size is greater than the maximum available size, we set
    2457             :   // it to the maximum size. And if the original value is less than the
    2458             :   // minimum rounded size, we set it to the minimum 200x100.
    2459           0 :   if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
    2460           0 :     resultWidth = availContentWidth + chromeOffsetWidth;
    2461           0 :   } else if (aInputWidth < (200 + chromeOffsetWidth)) {
    2462           0 :     resultWidth = 200 + chromeOffsetWidth;
    2463             :   } else {
    2464             :     // Otherwise, we round the window to the nearest upper rounded 200x100.
    2465           0 :     resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 + chromeOffsetWidth;
    2466             :   }
    2467             : 
    2468           0 :   if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
    2469           0 :     resultHeight = availContentHeight + chromeOffsetHeight;
    2470           0 :   } else if (aInputHeight < (100 + chromeOffsetHeight)) {
    2471           0 :     resultHeight = 100 + chromeOffsetHeight;
    2472             :   } else {
    2473           0 :     resultHeight = NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 + chromeOffsetHeight;
    2474             :   }
    2475             : 
    2476           0 :   *aOutputWidth = resultWidth;
    2477           0 :   *aOutputHeight = resultHeight;
    2478           0 : }
    2479             : 
    2480             : bool
    2481           0 : nsContentUtils::ThreadsafeIsCallerChrome()
    2482             : {
    2483           0 :   return NS_IsMainThread() ?
    2484             :     IsCallerChrome() :
    2485           0 :     mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
    2486             : }
    2487             : 
    2488             : bool
    2489           0 : nsContentUtils::IsCallerContentXBL()
    2490             : {
    2491           0 :     JSContext *cx = GetCurrentJSContext();
    2492           0 :     if (!cx)
    2493           0 :         return false;
    2494             : 
    2495           0 :     JSCompartment *c = js::GetContextCompartment(cx);
    2496             : 
    2497             :     // For remote XUL, we run XBL in the XUL scope. Given that we care about
    2498             :     // compat and not security for remote XUL, just always claim to be XBL.
    2499           0 :     if (!xpc::AllowContentXBLScope(c)) {
    2500           0 :       MOZ_ASSERT(nsContentUtils::AllowXULXBLForPrincipal(xpc::GetCompartmentPrincipal(c)));
    2501           0 :       return true;
    2502             :     }
    2503             : 
    2504           0 :     return xpc::IsContentXBLScope(c);
    2505             : }
    2506             : 
    2507             : bool
    2508        1439 : nsContentUtils::IsSystemCaller(JSContext* aCx)
    2509             : {
    2510             :   // Note that SubjectPrincipal() assumes we are in a compartment here.
    2511        1439 :   return SubjectPrincipal(aCx) == sSystemPrincipal;
    2512             : }
    2513             : 
    2514             : bool
    2515         199 : nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx)
    2516             : {
    2517         199 :   if (NS_IsMainThread()) {
    2518         183 :     return IsSystemCaller(aCx);
    2519             :   }
    2520             : 
    2521          16 :   return workers::GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal();
    2522             : }
    2523             : 
    2524             : // static
    2525             : bool
    2526           0 : nsContentUtils::LookupBindingMember(JSContext* aCx, nsIContent *aContent,
    2527             :                                     JS::Handle<jsid> aId,
    2528             :                                     JS::MutableHandle<JS::PropertyDescriptor> aDesc)
    2529             : {
    2530           0 :   nsXBLBinding* binding = aContent->GetXBLBinding();
    2531           0 :   if (!binding)
    2532           0 :     return true;
    2533           0 :   return binding->LookupMember(aCx, aId, aDesc);
    2534             : }
    2535             : 
    2536             : // static
    2537             : nsINode*
    2538           0 : nsContentUtils::GetCrossDocParentNode(nsINode* aChild)
    2539             : {
    2540           0 :   NS_PRECONDITION(aChild, "The child is null!");
    2541             : 
    2542           0 :   nsINode* parent = aChild->GetParentNode();
    2543           0 :   if (parent && parent->IsContent() && aChild->IsContent()) {
    2544           0 :     parent = aChild->AsContent()->GetFlattenedTreeParent();
    2545             :   }
    2546             : 
    2547           0 :   if (parent || !aChild->IsNodeOfType(nsINode::eDOCUMENT))
    2548           0 :     return parent;
    2549             : 
    2550           0 :   nsIDocument* doc = static_cast<nsIDocument*>(aChild);
    2551           0 :   nsIDocument* parentDoc = doc->GetParentDocument();
    2552           0 :   return parentDoc ? parentDoc->FindContentForSubDocument(doc) : nullptr;
    2553             : }
    2554             : 
    2555             : // static
    2556             : bool
    2557          73 : nsContentUtils::ContentIsDescendantOf(const nsINode* aPossibleDescendant,
    2558             :                                       const nsINode* aPossibleAncestor)
    2559             : {
    2560          73 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    2561          73 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    2562             : 
    2563         253 :   do {
    2564         326 :     if (aPossibleDescendant == aPossibleAncestor)
    2565          42 :       return true;
    2566         284 :     aPossibleDescendant = aPossibleDescendant->GetParentNode();
    2567         284 :   } while (aPossibleDescendant);
    2568             : 
    2569          31 :   return false;
    2570             : }
    2571             : 
    2572             : bool
    2573           9 : nsContentUtils::ContentIsHostIncludingDescendantOf(
    2574             :   const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor)
    2575             : {
    2576           9 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    2577           9 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    2578             : 
    2579          39 :   do {
    2580          48 :     if (aPossibleDescendant == aPossibleAncestor)
    2581           0 :       return true;
    2582          48 :     if (aPossibleDescendant->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    2583             :       aPossibleDescendant =
    2584           0 :         static_cast<const DocumentFragment*>(aPossibleDescendant)->GetHost();
    2585             :     } else {
    2586          48 :       aPossibleDescendant = aPossibleDescendant->GetParentNode();
    2587             :     }
    2588          48 :   } while (aPossibleDescendant);
    2589             : 
    2590           9 :   return false;
    2591             : }
    2592             : 
    2593             : // static
    2594             : bool
    2595           0 : nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
    2596             :                                               nsINode* aPossibleAncestor)
    2597             : {
    2598           0 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    2599           0 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    2600             : 
    2601           0 :   do {
    2602           0 :     if (aPossibleDescendant == aPossibleAncestor)
    2603           0 :       return true;
    2604             : 
    2605           0 :     aPossibleDescendant = GetCrossDocParentNode(aPossibleDescendant);
    2606           0 :   } while (aPossibleDescendant);
    2607             : 
    2608           0 :   return false;
    2609             : }
    2610             : 
    2611             : // static
    2612             : bool
    2613           0 : nsContentUtils::ContentIsFlattenedTreeDescendantOf(
    2614             :   const nsINode* aPossibleDescendant,
    2615             :   const nsINode* aPossibleAncestor)
    2616             : {
    2617           0 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    2618           0 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    2619             : 
    2620           0 :   do {
    2621           0 :     if (aPossibleDescendant == aPossibleAncestor) {
    2622           0 :       return true;
    2623             :     }
    2624           0 :     aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
    2625           0 :   } while (aPossibleDescendant);
    2626             : 
    2627           0 :   return false;
    2628             : }
    2629             : 
    2630             : // static
    2631             : nsresult
    2632           0 : nsContentUtils::GetAncestors(nsINode* aNode,
    2633             :                              nsTArray<nsINode*>& aArray)
    2634             : {
    2635           0 :   while (aNode) {
    2636           0 :     aArray.AppendElement(aNode);
    2637           0 :     aNode = aNode->GetParentNode();
    2638             :   }
    2639           0 :   return NS_OK;
    2640             : }
    2641             : 
    2642             : // static
    2643             : nsresult
    2644           0 : nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode* aNode,
    2645             :                                        int32_t aOffset,
    2646             :                                        nsTArray<nsIContent*>* aAncestorNodes,
    2647             :                                        nsTArray<int32_t>* aAncestorOffsets)
    2648             : {
    2649           0 :   NS_ENSURE_ARG_POINTER(aNode);
    2650             : 
    2651           0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    2652             : 
    2653           0 :   if (!content) {
    2654           0 :     return NS_ERROR_FAILURE;
    2655             :   }
    2656             : 
    2657           0 :   if (!aAncestorNodes->IsEmpty()) {
    2658           0 :     NS_WARNING("aAncestorNodes is not empty");
    2659           0 :     aAncestorNodes->Clear();
    2660             :   }
    2661             : 
    2662           0 :   if (!aAncestorOffsets->IsEmpty()) {
    2663           0 :     NS_WARNING("aAncestorOffsets is not empty");
    2664           0 :     aAncestorOffsets->Clear();
    2665             :   }
    2666             : 
    2667             :   // insert the node itself
    2668           0 :   aAncestorNodes->AppendElement(content.get());
    2669           0 :   aAncestorOffsets->AppendElement(aOffset);
    2670             : 
    2671             :   // insert all the ancestors
    2672           0 :   nsIContent* child = content;
    2673           0 :   nsIContent* parent = child->GetParent();
    2674           0 :   while (parent) {
    2675           0 :     aAncestorNodes->AppendElement(parent);
    2676           0 :     aAncestorOffsets->AppendElement(parent->IndexOf(child));
    2677           0 :     child = parent;
    2678           0 :     parent = parent->GetParent();
    2679             :   }
    2680             : 
    2681           0 :   return NS_OK;
    2682             : }
    2683             : 
    2684             : // static
    2685             : nsresult
    2686           0 : nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
    2687             :                                   nsIDOMNode *aOther,
    2688             :                                   nsIDOMNode** aCommonAncestor)
    2689             : {
    2690           0 :   *aCommonAncestor = nullptr;
    2691             : 
    2692           0 :   nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode);
    2693           0 :   nsCOMPtr<nsINode> node2 = do_QueryInterface(aOther);
    2694             : 
    2695           0 :   NS_ENSURE_TRUE(node1 && node2, NS_ERROR_UNEXPECTED);
    2696             : 
    2697           0 :   nsINode* common = GetCommonAncestor(node1, node2);
    2698           0 :   NS_ENSURE_TRUE(common, NS_ERROR_NOT_AVAILABLE);
    2699             : 
    2700           0 :   return CallQueryInterface(common, aCommonAncestor);
    2701             : }
    2702             : 
    2703             : template <typename Node, typename GetParentFunc>
    2704             : static Node*
    2705          30 : GetCommonAncestorInternal(Node* aNode1,
    2706             :                           Node* aNode2,
    2707             :                           GetParentFunc aGetParentFunc)
    2708             : {
    2709          30 :   if (aNode1 == aNode2) {
    2710          30 :     return aNode1;
    2711             :   }
    2712             : 
    2713             :   // Build the chain of parents
    2714           0 :   AutoTArray<Node*, 30> parents1, parents2;
    2715           0 :   do {
    2716           0 :     parents1.AppendElement(aNode1);
    2717           0 :     aNode1 = aGetParentFunc(aNode1);
    2718             :   } while (aNode1);
    2719           0 :   do {
    2720           0 :     parents2.AppendElement(aNode2);
    2721           0 :     aNode2 = aGetParentFunc(aNode2);
    2722             :   } while (aNode2);
    2723             : 
    2724             :   // Find where the parent chain differs
    2725           0 :   uint32_t pos1 = parents1.Length();
    2726           0 :   uint32_t pos2 = parents2.Length();
    2727           0 :   Node* parent = nullptr;
    2728             :   uint32_t len;
    2729           0 :   for (len = std::min(pos1, pos2); len > 0; --len) {
    2730           0 :     Node* child1 = parents1.ElementAt(--pos1);
    2731           0 :     Node* child2 = parents2.ElementAt(--pos2);
    2732           0 :     if (child1 != child2) {
    2733           0 :       break;
    2734             :     }
    2735           0 :     parent = child1;
    2736             :   }
    2737             : 
    2738           0 :   return parent;
    2739             : }
    2740             : 
    2741             : /* static */
    2742             : nsINode*
    2743          30 : nsContentUtils::GetCommonAncestor(nsINode* aNode1, nsINode* aNode2)
    2744             : {
    2745          30 :   return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
    2746             :     return aNode->GetParentNode();
    2747          60 :   });
    2748             : }
    2749             : 
    2750             : /* static */
    2751             : nsIContent*
    2752           0 : nsContentUtils::GetCommonFlattenedTreeAncestor(nsIContent* aContent1,
    2753             :                                                nsIContent* aContent2)
    2754             : {
    2755           0 :   return GetCommonAncestorInternal(aContent1, aContent2, [](nsIContent* aContent) {
    2756             :     return aContent->GetFlattenedTreeParent();
    2757           0 :   });
    2758             : }
    2759             : 
    2760             : /* static */
    2761             : bool
    2762           8 : nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2)
    2763             : {
    2764           8 :   return (aNode2->CompareDocumentPosition(*aNode1) &
    2765             :     (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
    2766             :      nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED)) ==
    2767           8 :     nsIDOMNode::DOCUMENT_POSITION_PRECEDING;
    2768             : }
    2769             : 
    2770             : /* static */
    2771             : int32_t
    2772          14 : nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
    2773             :                               nsINode* aParent2, int32_t aOffset2,
    2774             :                               bool* aDisconnected)
    2775             : {
    2776          14 :   if (aParent1 == aParent2) {
    2777          22 :     return aOffset1 < aOffset2 ? -1 :
    2778           8 :            aOffset1 > aOffset2 ? 1 :
    2779          14 :            0;
    2780             :   }
    2781             : 
    2782           0 :   AutoTArray<nsINode*, 32> parents1, parents2;
    2783           0 :   nsINode* node1 = aParent1;
    2784           0 :   nsINode* node2 = aParent2;
    2785           0 :   do {
    2786           0 :     parents1.AppendElement(node1);
    2787           0 :     node1 = node1->GetParentNode();
    2788           0 :   } while (node1);
    2789           0 :   do {
    2790           0 :     parents2.AppendElement(node2);
    2791           0 :     node2 = node2->GetParentNode();
    2792           0 :   } while (node2);
    2793             : 
    2794           0 :   uint32_t pos1 = parents1.Length() - 1;
    2795           0 :   uint32_t pos2 = parents2.Length() - 1;
    2796             : 
    2797           0 :   bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
    2798           0 :   if (aDisconnected) {
    2799           0 :     *aDisconnected = disconnected;
    2800             :   }
    2801           0 :   if (disconnected) {
    2802           0 :     NS_ASSERTION(aDisconnected, "unexpected disconnected nodes");
    2803           0 :     return 1;
    2804             :   }
    2805             : 
    2806             :   // Find where the parent chains differ
    2807           0 :   nsINode* parent = parents1.ElementAt(pos1);
    2808             :   uint32_t len;
    2809           0 :   for (len = std::min(pos1, pos2); len > 0; --len) {
    2810           0 :     nsINode* child1 = parents1.ElementAt(--pos1);
    2811           0 :     nsINode* child2 = parents2.ElementAt(--pos2);
    2812           0 :     if (child1 != child2) {
    2813           0 :       return parent->IndexOf(child1) < parent->IndexOf(child2) ? -1 : 1;
    2814             :     }
    2815           0 :     parent = child1;
    2816             :   }
    2817             : 
    2818             : 
    2819             :   // The parent chains never differed, so one of the nodes is an ancestor of
    2820             :   // the other
    2821             : 
    2822           0 :   NS_ASSERTION(!pos1 || !pos2,
    2823             :                "should have run out of parent chain for one of the nodes");
    2824             : 
    2825           0 :   if (!pos1) {
    2826           0 :     nsINode* child2 = parents2.ElementAt(--pos2);
    2827           0 :     return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
    2828             :   }
    2829             : 
    2830           0 :   nsINode* child1 = parents1.ElementAt(--pos1);
    2831           0 :   return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
    2832             : }
    2833             : 
    2834             : /* static */
    2835             : int32_t
    2836           0 : nsContentUtils::ComparePoints(nsIDOMNode* aParent1, int32_t aOffset1,
    2837             :                               nsIDOMNode* aParent2, int32_t aOffset2,
    2838             :                               bool* aDisconnected)
    2839             : {
    2840           0 :   nsCOMPtr<nsINode> parent1 = do_QueryInterface(aParent1);
    2841           0 :   nsCOMPtr<nsINode> parent2 = do_QueryInterface(aParent2);
    2842           0 :   NS_ENSURE_TRUE(parent1 && parent2, -1);
    2843           0 :   return ComparePoints(parent1, aOffset1, parent2, aOffset2);
    2844             : }
    2845             : 
    2846             : inline bool
    2847           0 : IsCharInSet(const char* aSet,
    2848             :             const char16_t aChar)
    2849             : {
    2850             :   char16_t ch;
    2851           0 :   while ((ch = *aSet)) {
    2852           0 :     if (aChar == char16_t(ch)) {
    2853           0 :       return true;
    2854             :     }
    2855           0 :     ++aSet;
    2856             :   }
    2857           0 :   return false;
    2858             : }
    2859             : 
    2860             : /**
    2861             :  * This method strips leading/trailing chars, in given set, from string.
    2862             :  */
    2863             : 
    2864             : // static
    2865             : const nsDependentSubstring
    2866           0 : nsContentUtils::TrimCharsInSet(const char* aSet,
    2867             :                                const nsAString& aValue)
    2868             : {
    2869           0 :   nsAString::const_iterator valueCurrent, valueEnd;
    2870             : 
    2871           0 :   aValue.BeginReading(valueCurrent);
    2872           0 :   aValue.EndReading(valueEnd);
    2873             : 
    2874             :   // Skip characters in the beginning
    2875           0 :   while (valueCurrent != valueEnd) {
    2876           0 :     if (!IsCharInSet(aSet, *valueCurrent)) {
    2877           0 :       break;
    2878             :     }
    2879           0 :     ++valueCurrent;
    2880             :   }
    2881             : 
    2882           0 :   if (valueCurrent != valueEnd) {
    2883             :     for (;;) {
    2884           0 :       --valueEnd;
    2885           0 :       if (!IsCharInSet(aSet, *valueEnd)) {
    2886           0 :         break;
    2887             :       }
    2888             :     }
    2889           0 :     ++valueEnd; // Step beyond the last character we want in the value.
    2890             :   }
    2891             : 
    2892             :   // valueEnd should point to the char after the last to copy
    2893           0 :   return Substring(valueCurrent, valueEnd);
    2894             : }
    2895             : 
    2896             : /**
    2897             :  * This method strips leading and trailing whitespace from a string.
    2898             :  */
    2899             : 
    2900             : // static
    2901             : template<bool IsWhitespace(char16_t)>
    2902             : const nsDependentSubstring
    2903           0 : nsContentUtils::TrimWhitespace(const nsAString& aStr, bool aTrimTrailing)
    2904             : {
    2905           0 :   nsAString::const_iterator start, end;
    2906             : 
    2907           0 :   aStr.BeginReading(start);
    2908           0 :   aStr.EndReading(end);
    2909             : 
    2910             :   // Skip whitespace characters in the beginning
    2911           0 :   while (start != end && IsWhitespace(*start)) {
    2912           0 :     ++start;
    2913             :   }
    2914             : 
    2915           0 :   if (aTrimTrailing) {
    2916             :     // Skip whitespace characters in the end.
    2917           0 :     while (end != start) {
    2918           0 :       --end;
    2919             : 
    2920           0 :       if (!IsWhitespace(*end)) {
    2921             :         // Step back to the last non-whitespace character.
    2922           0 :         ++end;
    2923             : 
    2924           0 :         break;
    2925             :       }
    2926             :     }
    2927             :   }
    2928             : 
    2929             :   // Return a substring for the string w/o leading and/or trailing
    2930             :   // whitespace
    2931             : 
    2932           0 :   return Substring(start, end);
    2933             : }
    2934             : 
    2935             : // Declaring the templates we are going to use avoid linking issues without
    2936             : // inlining the method. Considering there is not so much spaces checking
    2937             : // methods we can consider this to be better than inlining.
    2938             : template
    2939             : const nsDependentSubstring
    2940             : nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
    2941             : template
    2942             : const nsDependentSubstring
    2943             : nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
    2944             : template
    2945             : const nsDependentSubstring
    2946             : nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
    2947             : 
    2948          44 : static inline void KeyAppendSep(nsACString& aKey)
    2949             : {
    2950          44 :   if (!aKey.IsEmpty()) {
    2951          40 :     aKey.Append('>');
    2952             :   }
    2953          44 : }
    2954             : 
    2955           4 : static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
    2956             : {
    2957           4 :   KeyAppendSep(aKey);
    2958             : 
    2959             :   // Could escape separator here if collisions happen.  > is not a legal char
    2960             :   // for a name or type attribute, so we should be safe avoiding that extra work.
    2961             : 
    2962           4 :   AppendUTF16toUTF8(aString, aKey);
    2963           4 : }
    2964             : 
    2965           0 : static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
    2966             : {
    2967           0 :   KeyAppendSep(aKey);
    2968             : 
    2969             :   // Could escape separator here if collisions happen.  > is not a legal char
    2970             :   // for a name or type attribute, so we should be safe avoiding that extra work.
    2971             : 
    2972           0 :   aKey.Append(aString);
    2973           0 : }
    2974             : 
    2975          40 : static inline void KeyAppendInt(int32_t aInt, nsACString& aKey)
    2976             : {
    2977          40 :   KeyAppendSep(aKey);
    2978             : 
    2979          40 :   aKey.Append(nsPrintfCString("%d", aInt));
    2980          40 : }
    2981             : 
    2982           4 : static inline bool IsAutocompleteOff(const nsIContent* aElement)
    2983             : {
    2984           4 :   return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
    2985           8 :                                NS_LITERAL_STRING("off"), eIgnoreCase);
    2986             : }
    2987             : 
    2988             : /*static*/ nsresult
    2989          10 : nsContentUtils::GenerateStateKey(nsIContent* aContent,
    2990             :                                  const nsIDocument* aDocument,
    2991             :                                  nsACString& aKey)
    2992             : {
    2993          10 :   aKey.Truncate();
    2994             : 
    2995          10 :   uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
    2996             : 
    2997             :   // We must have content if we're not using a special state id
    2998          10 :   NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
    2999             : 
    3000             :   // Don't capture state for anonymous content
    3001          10 :   if (aContent->IsInAnonymousSubtree()) {
    3002           6 :     return NS_OK;
    3003             :   }
    3004             : 
    3005           4 :   if (IsAutocompleteOff(aContent)) {
    3006           0 :     return NS_OK;
    3007             :   }
    3008             : 
    3009             :   nsCOMPtr<nsIHTMLDocument> htmlDocument =
    3010           8 :     do_QueryInterface(aContent->GetUncomposedDoc());
    3011             : 
    3012           4 :   KeyAppendInt(partID, aKey);  // first append a partID
    3013           4 :   bool generatedUniqueKey = false;
    3014             : 
    3015           4 :   if (htmlDocument) {
    3016             :     // Flush our content model so it'll be up to date
    3017             :     // If this becomes unnecessary and the following line is removed,
    3018             :     // please also remove the corresponding flush operation from
    3019             :     // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
    3020           0 :     aContent->GetUncomposedDoc()->FlushPendingNotifications(FlushType::Content);
    3021             : 
    3022           0 :     nsContentList *htmlForms = htmlDocument->GetForms();
    3023           0 :     nsContentList *htmlFormControls = htmlDocument->GetFormControls();
    3024             : 
    3025           0 :     NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
    3026             : 
    3027             :     // If we have a form control and can calculate form information, use that
    3028             :     // as the key - it is more reliable than just recording position in the
    3029             :     // DOM.
    3030             :     // XXXbz Is it, really?  We have bugs on this, I think...
    3031             :     // Important to have a unique key, and tag/type/name may not be.
    3032             :     //
    3033             :     // If the control has a form, the format of the key is:
    3034             :     // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
    3035             :     // else:
    3036             :     // d>type>IndOfControlInDoc>name
    3037             :     //
    3038             :     // XXX We don't need to use index if name is there
    3039             :     // XXXbz We don't?  Why not?  I don't follow.
    3040             :     //
    3041           0 :     nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
    3042           0 :     if (control && htmlFormControls && htmlForms) {
    3043             : 
    3044             :       // Append the control type
    3045           0 :       KeyAppendInt(control->ControlType(), aKey);
    3046             : 
    3047             :       // If in a form, add form name / index of form / index in form
    3048           0 :       int32_t index = -1;
    3049           0 :       Element *formElement = control->GetFormElement();
    3050           0 :       if (formElement) {
    3051           0 :         if (IsAutocompleteOff(formElement)) {
    3052           0 :           aKey.Truncate();
    3053           0 :           return NS_OK;
    3054             :         }
    3055             : 
    3056           0 :         KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
    3057             : 
    3058             :         // Append the index of the form in the document
    3059           0 :         index = htmlForms->IndexOf(formElement, false);
    3060           0 :         if (index <= -1) {
    3061             :           //
    3062             :           // XXX HACK this uses some state that was dumped into the document
    3063             :           // specifically to fix bug 138892.  What we are trying to do is *guess*
    3064             :           // which form this control's state is found in, with the highly likely
    3065             :           // guess that the highest form parsed so far is the one.
    3066             :           // This code should not be on trunk, only branch.
    3067             :           //
    3068           0 :           index = htmlDocument->GetNumFormsSynchronous() - 1;
    3069             :         }
    3070           0 :         if (index > -1) {
    3071           0 :           KeyAppendInt(index, aKey);
    3072             : 
    3073             :           // Append the index of the control in the form
    3074           0 :           nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
    3075           0 :           index = form->IndexOfControl(control);
    3076             : 
    3077           0 :           if (index > -1) {
    3078           0 :             KeyAppendInt(index, aKey);
    3079           0 :             generatedUniqueKey = true;
    3080             :           }
    3081             :         }
    3082             : 
    3083             :         // Append the form name
    3084           0 :         nsAutoString formName;
    3085           0 :         formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
    3086           0 :         KeyAppendString(formName, aKey);
    3087             : 
    3088             :       } else {
    3089             : 
    3090           0 :         KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
    3091             : 
    3092             :         // If not in a form, add index of control in document
    3093             :         // Less desirable than indexing by form info.
    3094             : 
    3095             :         // Hash by index of control in doc (we are not in a form)
    3096             :         // These are important as they are unique, and type/name may not be.
    3097             : 
    3098             :         // We have to flush sink notifications at this point to make
    3099             :         // sure that htmlFormControls is up to date.
    3100           0 :         index = htmlFormControls->IndexOf(aContent, true);
    3101           0 :         if (index > -1) {
    3102           0 :           KeyAppendInt(index, aKey);
    3103           0 :           generatedUniqueKey = true;
    3104             :         }
    3105             :       }
    3106             : 
    3107             :       // Append the control name
    3108           0 :       nsAutoString name;
    3109           0 :       aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3110           0 :       KeyAppendString(name, aKey);
    3111             :     }
    3112             :   }
    3113             : 
    3114           4 :   if (!generatedUniqueKey) {
    3115             :     // Either we didn't have a form control or we aren't in an HTML document so
    3116             :     // we can't figure out form info.  Append the tag name if it's an element
    3117             :     // to avoid restoring state for one type of element on another type.
    3118           4 :     if (aContent->IsElement()) {
    3119           8 :       KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
    3120           4 :                       aKey);
    3121             :     }
    3122             :     else {
    3123             :       // Append a character that is not "d" or "f" to disambiguate from
    3124             :       // the case when we were a form control in an HTML document.
    3125           0 :       KeyAppendString(NS_LITERAL_CSTRING("o"), aKey);
    3126             :     }
    3127             : 
    3128             :     // Now start at aContent and append the indices of it and all its ancestors
    3129             :     // in their containers.  That should at least pin down its position in the
    3130             :     // DOM...
    3131           4 :     nsINode* parent = aContent->GetParentNode();
    3132           4 :     nsINode* content = aContent;
    3133          76 :     while (parent) {
    3134          36 :       KeyAppendInt(parent->IndexOf(content), aKey);
    3135          36 :       content = parent;
    3136          36 :       parent = content->GetParentNode();
    3137             :     }
    3138             :   }
    3139             : 
    3140           4 :   return NS_OK;
    3141             : }
    3142             : 
    3143             : // static
    3144             : nsIPrincipal*
    3145       11290 : nsContentUtils::SubjectPrincipal(JSContext* aCx)
    3146             : {
    3147       11290 :   MOZ_ASSERT(NS_IsMainThread());
    3148             : 
    3149             :   // As opposed to SubjectPrincipal(), we do in fact assume that
    3150             :   // we're in a compartment here; anyone who calls this function
    3151             :   // in situations where that's not the case is doing it wrong.
    3152       11290 :   JSCompartment* compartment = js::GetContextCompartment(aCx);
    3153       11290 :   MOZ_ASSERT(compartment);
    3154             : 
    3155       11290 :   JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
    3156       11290 :   return nsJSPrincipals::get(principals);
    3157             : }
    3158             : 
    3159             : // static
    3160             : nsIPrincipal*
    3161        9896 : nsContentUtils::SubjectPrincipal()
    3162             : {
    3163        9896 :   MOZ_ASSERT(IsInitialized());
    3164        9896 :   MOZ_ASSERT(NS_IsMainThread());
    3165        9896 :   JSContext* cx = GetCurrentJSContext();
    3166        9896 :   if (!cx) {
    3167           0 :     MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
    3168             :   }
    3169             : 
    3170        9896 :   JSCompartment *compartment = js::GetContextCompartment(cx);
    3171             : 
    3172             :   // When an AutoJSAPI is instantiated, we are in a null compartment until the
    3173             :   // first JSAutoCompartment, which is kind of a purgatory as far as permissions
    3174             :   // go. It would be nice to just hard-abort if somebody does a security check
    3175             :   // in this purgatory zone, but that would be too fragile, since it could be
    3176             :   // triggered by random IsCallerChrome() checks 20-levels deep.
    3177             :   //
    3178             :   // So we want to return _something_ here - and definitely not the System
    3179             :   // Principal, since that would make an AutoJSAPI a very dangerous thing to
    3180             :   // instantiate.
    3181             :   //
    3182             :   // The natural thing to return is a null principal. Ideally, we'd return a
    3183             :   // different null principal each time, to avoid any unexpected interactions
    3184             :   // when the principal accidentally gets inherited somewhere. But
    3185             :   // SubjectPrincipal doesn't return strong references, so there's no way to
    3186             :   // sanely manage the lifetime of multiple null principals.
    3187             :   //
    3188             :   // So we use a singleton null principal. To avoid it being accidentally
    3189             :   // inherited and becoming a "real" subject or object principal, we do a
    3190             :   // release-mode assert during compartment creation against using this
    3191             :   // principal on an actual global.
    3192        9896 :   if (!compartment) {
    3193          45 :     return sNullSubjectPrincipal;
    3194             :   }
    3195             : 
    3196        9851 :   return SubjectPrincipal(cx);
    3197             : }
    3198             : 
    3199             : // static
    3200             : nsIPrincipal*
    3201         681 : nsContentUtils::ObjectPrincipal(JSObject* aObj)
    3202             : {
    3203         681 :   MOZ_ASSERT(NS_IsMainThread());
    3204             : 
    3205             : #ifdef DEBUG
    3206         681 :   JS::AssertObjectBelongsToCurrentThread(aObj);
    3207             : #endif
    3208             : 
    3209             :   // This is duplicated from nsScriptSecurityManager. We don't call through there
    3210             :   // because the API unnecessarily requires a JSContext for historical reasons.
    3211         681 :   JSCompartment *compartment = js::GetObjectCompartment(aObj);
    3212         681 :   JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
    3213         681 :   return nsJSPrincipals::get(principals);
    3214             : }
    3215             : 
    3216             : // static
    3217             : nsresult
    3218          29 : nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
    3219             :                                           const nsAString& aSpec,
    3220             :                                           nsIDocument* aDocument,
    3221             :                                           nsIURI* aBaseURI)
    3222             : {
    3223          29 :   if (aDocument) {
    3224          28 :     return NS_NewURI(aResult, aSpec,
    3225             :                      aDocument->GetDocumentCharacterSet(),
    3226          28 :                      aBaseURI, sIOService);
    3227             :   }
    3228           1 :   return NS_NewURI(aResult, aSpec, nullptr, aBaseURI, sIOService);
    3229             : }
    3230             : 
    3231             : // static
    3232             : bool
    3233         883 : nsContentUtils::IsCustomElementName(nsIAtom* aName)
    3234             : {
    3235             :   // A valid custom element name is a sequence of characters name which
    3236             :   // must match the PotentialCustomElementName production:
    3237             :   // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
    3238         883 :   const char16_t* name = aName->GetUTF16String();
    3239         883 :   uint32_t len = aName->GetLength();
    3240         883 :   bool hasDash = false;
    3241             : 
    3242         883 :   if (!len || name[0] < 'a' || name[0] > 'z') {
    3243           0 :     return false;
    3244             :   }
    3245             : 
    3246         883 :   uint32_t i = 1;
    3247       11175 :   while (i < len) {
    3248        5146 :     if (NS_IS_HIGH_SURROGATE(name[i]) && i + 1 < len &&
    3249           0 :         NS_IS_LOW_SURROGATE(name[i + 1])) {
    3250             :       // Merged two 16-bit surrogate pairs into code point.
    3251           0 :       char32_t code = SURROGATE_TO_UCS4(name[i], name[i + 1]);
    3252             : 
    3253           0 :       if (code < 0x10000 || code > 0xEFFFF) {
    3254           0 :         return false;
    3255             :       }
    3256             : 
    3257           0 :       i += 2;
    3258             :     } else {
    3259        5146 :       if (name[i] == '-') {
    3260           0 :         hasDash = true;
    3261             :       }
    3262             : 
    3263       10292 :       if (name[i] != '-' && name[i] != '.' &&
    3264       15438 :           name[i] != '_' && name[i] != 0xB7 &&
    3265       15438 :          (name[i] < '0' || name[i] > '9') &&
    3266       10292 :          (name[i] < 'a' || name[i] > 'z') &&
    3267           0 :          (name[i] < 0xC0 || name[i] > 0xD6) &&
    3268           0 :          (name[i] < 0xF8 || name[i] > 0x37D) &&
    3269           0 :          (name[i] < 0x37F || name[i] > 0x1FFF) &&
    3270           0 :          (name[i] < 0x200C || name[i] > 0x200D) &&
    3271           0 :          (name[i] < 0x203F || name[i] > 0x2040) &&
    3272           0 :          (name[i] < 0x2070 || name[i] > 0x218F) &&
    3273           0 :          (name[i] < 0x2C00 || name[i] > 0x2FEF) &&
    3274           0 :          (name[i] < 0x3001 || name[i] > 0xD7FF) &&
    3275           0 :          (name[i] < 0xF900 || name[i] > 0xFDCF) &&
    3276           0 :          (name[i] < 0xFDF0 || name[i] > 0xFFFD)) {
    3277           0 :         return false;
    3278             :       }
    3279             : 
    3280        5146 :       i++;
    3281             :     }
    3282             :   }
    3283             : 
    3284         883 :   if (!hasDash) {
    3285         883 :     return false;
    3286             :   }
    3287             : 
    3288             :   // The custom element name must not be one of the following values:
    3289             :   //  annotation-xml
    3290             :   //  color-profile
    3291             :   //  font-face
    3292             :   //  font-face-src
    3293             :   //  font-face-uri
    3294             :   //  font-face-format
    3295             :   //  font-face-name
    3296             :   //  missing-glyph
    3297           0 :   return aName != nsGkAtoms::annotation_xml_ &&
    3298           0 :          aName != nsGkAtoms::colorProfile &&
    3299           0 :          aName != nsGkAtoms::font_face &&
    3300           0 :          aName != nsGkAtoms::font_face_src &&
    3301           0 :          aName != nsGkAtoms::font_face_uri &&
    3302           0 :          aName != nsGkAtoms::font_face_format &&
    3303           0 :          aName != nsGkAtoms::font_face_name &&
    3304           0 :          aName != nsGkAtoms::missingGlyph;
    3305             : }
    3306             : 
    3307             : // static
    3308             : nsresult
    3309         672 : nsContentUtils::CheckQName(const nsAString& aQualifiedName,
    3310             :                            bool aNamespaceAware,
    3311             :                            const char16_t** aColon)
    3312             : {
    3313         672 :   const char* colon = nullptr;
    3314         672 :   const char16_t* begin = aQualifiedName.BeginReading();
    3315         672 :   const char16_t* end = aQualifiedName.EndReading();
    3316             : 
    3317         672 :   int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
    3318             :                                  reinterpret_cast<const char*>(end),
    3319         672 :                                  aNamespaceAware, &colon);
    3320             : 
    3321         672 :   if (!result) {
    3322         672 :     if (aColon) {
    3323          66 :       *aColon = reinterpret_cast<const char16_t*>(colon);
    3324             :     }
    3325             : 
    3326         672 :     return NS_OK;
    3327             :   }
    3328             : 
    3329           0 :   return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    3330             : }
    3331             : 
    3332             : //static
    3333             : nsresult
    3334          33 : nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
    3335             :                            const nsString& aQName,
    3336             :                            int32_t *aNamespace, nsIAtom **aLocalName)
    3337             : {
    3338             :   const char16_t* colon;
    3339          33 :   nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
    3340          33 :   NS_ENSURE_SUCCESS(rv, rv);
    3341             : 
    3342          33 :   if (colon) {
    3343             :     const char16_t* end;
    3344           0 :     aQName.EndReading(end);
    3345           0 :     nsAutoString nameSpace;
    3346           0 :     rv = aNamespaceResolver->LookupNamespaceURIInternal(Substring(aQName.get(),
    3347             :                                                                   colon),
    3348           0 :                                                         nameSpace);
    3349           0 :     NS_ENSURE_SUCCESS(rv, rv);
    3350             : 
    3351           0 :     *aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace,
    3352           0 :                                                      nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
    3353           0 :     if (*aNamespace == kNameSpaceID_Unknown)
    3354           0 :       return NS_ERROR_FAILURE;
    3355             : 
    3356           0 :     *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
    3357             :   }
    3358             :   else {
    3359          33 :     *aNamespace = kNameSpaceID_None;
    3360          33 :     *aLocalName = NS_AtomizeMainThread(aQName).take();
    3361             :   }
    3362          33 :   NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
    3363          33 :   return NS_OK;
    3364             : }
    3365             : 
    3366             : // static
    3367             : nsresult
    3368          33 : nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
    3369             :                                      const nsAString& aQualifiedName,
    3370             :                                      nsNodeInfoManager* aNodeInfoManager,
    3371             :                                      uint16_t aNodeType,
    3372             :                                      mozilla::dom::NodeInfo** aNodeInfo)
    3373             : {
    3374          66 :   const nsString& qName = PromiseFlatString(aQualifiedName);
    3375             :   const char16_t* colon;
    3376          33 :   nsresult rv = nsContentUtils::CheckQName(qName, true, &colon);
    3377          33 :   NS_ENSURE_SUCCESS(rv, rv);
    3378             : 
    3379             :   int32_t nsID;
    3380          33 :   sNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsID);
    3381          33 :   if (colon) {
    3382             :     const char16_t* end;
    3383           0 :     qName.EndReading(end);
    3384             : 
    3385             :     nsCOMPtr<nsIAtom> prefix =
    3386           0 :       NS_AtomizeMainThread(Substring(qName.get(), colon));
    3387             : 
    3388           0 :     rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
    3389           0 :                                        nsID, aNodeType, aNodeInfo);
    3390             :   }
    3391             :   else {
    3392          33 :     rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID,
    3393          33 :                                        aNodeType, aNodeInfo);
    3394             :   }
    3395          33 :   NS_ENSURE_SUCCESS(rv, rv);
    3396             : 
    3397          33 :   return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
    3398             :                                          (*aNodeInfo)->GetPrefixAtom(),
    3399          33 :                                          (*aNodeInfo)->NamespaceID()) ?
    3400          33 :          NS_OK : NS_ERROR_DOM_NAMESPACE_ERR;
    3401             : }
    3402             : 
    3403             : // static
    3404             : void
    3405         660 : nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix,
    3406             :                                nsIAtom **aLocalName, int32_t* aNameSpaceID)
    3407             : {
    3408             :   /**
    3409             :    *  Expat can send the following:
    3410             :    *    localName
    3411             :    *    namespaceURI<separator>localName
    3412             :    *    namespaceURI<separator>localName<separator>prefix
    3413             :    *
    3414             :    *  and we use 0xFFFF for the <separator>.
    3415             :    *
    3416             :    */
    3417             : 
    3418         660 :   const char16_t *uriEnd = nullptr;
    3419         660 :   const char16_t *nameEnd = nullptr;
    3420             :   const char16_t *pos;
    3421       14565 :   for (pos = aExpatName; *pos; ++pos) {
    3422       13905 :     if (*pos == 0xFFFF) {
    3423         431 :       if (uriEnd) {
    3424          69 :         nameEnd = pos;
    3425             :       }
    3426             :       else {
    3427         362 :         uriEnd = pos;
    3428             :       }
    3429             :     }
    3430             :   }
    3431             : 
    3432             :   const char16_t *nameStart;
    3433         660 :   if (uriEnd) {
    3434         362 :     if (sNameSpaceManager) {
    3435         724 :       sNameSpaceManager->RegisterNameSpace(nsDependentSubstring(aExpatName,
    3436             :                                                                 uriEnd),
    3437         362 :                                            *aNameSpaceID);
    3438             :     }
    3439             :     else {
    3440           0 :       *aNameSpaceID = kNameSpaceID_Unknown;
    3441             :     }
    3442             : 
    3443         362 :     nameStart = (uriEnd + 1);
    3444         362 :     if (nameEnd)  {
    3445          69 :       const char16_t *prefixStart = nameEnd + 1;
    3446          69 :       *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
    3447             :     }
    3448             :     else {
    3449         293 :       nameEnd = pos;
    3450         293 :       *aPrefix = nullptr;
    3451             :     }
    3452             :   }
    3453             :   else {
    3454         298 :     *aNameSpaceID = kNameSpaceID_None;
    3455         298 :     nameStart = aExpatName;
    3456         298 :     nameEnd = pos;
    3457         298 :     *aPrefix = nullptr;
    3458             :   }
    3459         660 :   *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
    3460         660 : }
    3461             : 
    3462             : // static
    3463             : nsPresContext*
    3464          48 : nsContentUtils::GetContextForContent(const nsIContent* aContent)
    3465             : {
    3466          48 :   nsIDocument* doc = aContent->GetComposedDoc();
    3467          48 :   if (doc) {
    3468          48 :     nsIPresShell *presShell = doc->GetShell();
    3469          48 :     if (presShell) {
    3470          48 :       return presShell->GetPresContext();
    3471             :     }
    3472             :   }
    3473           0 :   return nullptr;
    3474             : }
    3475             : 
    3476             : // static
    3477             : bool
    3478           0 : nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
    3479             :                              nsIDocument* aLoadingDocument,
    3480             :                              nsIPrincipal* aLoadingPrincipal,
    3481             :                              int16_t* aImageBlockingStatus,
    3482             :                              uint32_t aContentType)
    3483             : {
    3484           0 :   NS_PRECONDITION(aURI, "Must have a URI");
    3485           0 :   NS_PRECONDITION(aLoadingDocument, "Must have a document");
    3486           0 :   NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal");
    3487             : 
    3488             :   nsresult rv;
    3489             : 
    3490           0 :   uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
    3491             : 
    3492             :   {
    3493           0 :     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aLoadingDocument->GetDocShell();
    3494           0 :     if (docShellTreeItem) {
    3495           0 :       nsCOMPtr<nsIDocShellTreeItem> root;
    3496           0 :       docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
    3497             : 
    3498           0 :       nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
    3499             : 
    3500           0 :       if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
    3501           0 :         appType = nsIDocShell::APP_TYPE_UNKNOWN;
    3502             :       }
    3503             :     }
    3504             :   }
    3505             : 
    3506           0 :   if (appType != nsIDocShell::APP_TYPE_EDITOR) {
    3507             :     // Editor apps get special treatment here, editors can load images
    3508             :     // from anywhere.  This allows editor to insert images from file://
    3509             :     // into documents that are being edited.
    3510             :     rv = sSecurityManager->
    3511           0 :       CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
    3512           0 :                                 nsIScriptSecurityManager::ALLOW_CHROME);
    3513           0 :     if (NS_FAILED(rv)) {
    3514           0 :       if (aImageBlockingStatus) {
    3515             :         // Reject the request itself, not all requests to the relevant
    3516             :         // server...
    3517           0 :         *aImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
    3518             :       }
    3519           0 :       return false;
    3520             :     }
    3521             :   }
    3522             : 
    3523           0 :   int16_t decision = nsIContentPolicy::ACCEPT;
    3524             : 
    3525           0 :   rv = NS_CheckContentLoadPolicy(aContentType,
    3526             :                                  aURI,
    3527             :                                  aLoadingPrincipal,
    3528             :                                  aContext,
    3529           0 :                                  EmptyCString(), //mime guess
    3530             :                                  nullptr,         //extra
    3531             :                                  &decision,
    3532             :                                  GetContentPolicy(),
    3533           0 :                                  sSecurityManager);
    3534             : 
    3535           0 :   if (aImageBlockingStatus) {
    3536           0 :     *aImageBlockingStatus =
    3537           0 :       NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
    3538             :   }
    3539           0 :   return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
    3540             : }
    3541             : 
    3542             : // static
    3543             : mozilla::OriginAttributes
    3544           0 : nsContentUtils::GetOriginAttributes(nsIDocument* aDocument)
    3545             : {
    3546           0 :   if (!aDocument) {
    3547           0 :     return mozilla::OriginAttributes();
    3548             :   }
    3549             : 
    3550           0 :   nsCOMPtr<nsILoadGroup> loadGroup = aDocument->GetDocumentLoadGroup();
    3551           0 :   if (loadGroup) {
    3552           0 :     return GetOriginAttributes(loadGroup);
    3553             :   }
    3554             : 
    3555           0 :   mozilla::OriginAttributes attrs;
    3556           0 :   nsCOMPtr<nsIChannel> channel = aDocument->GetChannel();
    3557           0 :   if (channel) {
    3558           0 :     NS_GetOriginAttributes(channel, attrs);
    3559             :   }
    3560           0 :   return attrs;
    3561             : }
    3562             : 
    3563             : // static
    3564             : mozilla::OriginAttributes
    3565           2 : nsContentUtils::GetOriginAttributes(nsILoadGroup* aLoadGroup)
    3566             : {
    3567           2 :   if (!aLoadGroup) {
    3568           0 :     return mozilla::OriginAttributes();
    3569             :   }
    3570           4 :   mozilla::OriginAttributes attrs;
    3571           4 :   nsCOMPtr<nsIInterfaceRequestor> callbacks;
    3572           2 :   aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
    3573           2 :   if (callbacks) {
    3574           4 :     nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
    3575           2 :     if (loadContext) {
    3576           2 :       loadContext->GetOriginAttributes(attrs);
    3577             :     }
    3578             :   }
    3579           2 :   return attrs;
    3580             : }
    3581             : 
    3582             : // static
    3583             : bool
    3584         103 : nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc)
    3585             : {
    3586         103 :   if (!aDoc) {
    3587           0 :     return false;
    3588             :   }
    3589             : 
    3590         206 :   nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
    3591         103 :   if (loadGroup) {
    3592         103 :     return IsInPrivateBrowsing(loadGroup);
    3593             :   }
    3594             : 
    3595           0 :   nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
    3596           0 :   return channel && NS_UsePrivateBrowsing(channel);
    3597             : }
    3598             : 
    3599             : // static
    3600             : bool
    3601         103 : nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup)
    3602             : {
    3603         103 :   if (!aLoadGroup) {
    3604           0 :     return false;
    3605             :   }
    3606         103 :   bool isPrivate = false;
    3607         206 :   nsCOMPtr<nsIInterfaceRequestor> callbacks;
    3608         103 :   aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
    3609         103 :   if (callbacks) {
    3610         206 :     nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
    3611         103 :     isPrivate = loadContext && loadContext->UsePrivateBrowsing();
    3612             :   }
    3613         103 :   return isPrivate;
    3614             : }
    3615             : 
    3616             : bool
    3617          68 : nsContentUtils::DocumentInactiveForImageLoads(nsIDocument* aDocument)
    3618             : {
    3619          68 :   if (aDocument && !IsChromeDoc(aDocument) && !aDocument->IsResourceDoc()) {
    3620             :     nsCOMPtr<nsPIDOMWindowInner> win =
    3621           0 :       do_QueryInterface(aDocument->GetScopeObject());
    3622           0 :     return !win || !win->GetDocShell();
    3623             :   }
    3624          68 :   return false;
    3625             : }
    3626             : 
    3627             : imgLoader*
    3628          45 : nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
    3629             : {
    3630          45 :   NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr);
    3631             : 
    3632          45 :   if (!aDoc) {
    3633           0 :     return imgLoader::NormalLoader();
    3634             :   }
    3635          45 :   bool isPrivate = IsInPrivateBrowsing(aDoc);
    3636          45 :   return isPrivate ? imgLoader::PrivateBrowsingLoader()
    3637          45 :                    : imgLoader::NormalLoader();
    3638             : }
    3639             : 
    3640             : // static
    3641             : imgLoader*
    3642          11 : nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
    3643             :                                        nsIDocument* aContext)
    3644             : {
    3645          11 :   NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr);
    3646             : 
    3647          11 :   if (!aChannel) {
    3648          11 :     return imgLoader::NormalLoader();
    3649             :   }
    3650           0 :   nsCOMPtr<nsILoadContext> context;
    3651           0 :   NS_QueryNotificationCallbacks(aChannel, context);
    3652           0 :   return context && context->UsePrivateBrowsing() ?
    3653             :                       imgLoader::PrivateBrowsingLoader() :
    3654           0 :                       imgLoader::NormalLoader();
    3655             : }
    3656             : 
    3657             : // static
    3658             : bool
    3659           0 : nsContentUtils::IsImageInCache(nsIURI* aURI, nsIDocument* aDocument)
    3660             : {
    3661           0 :     imgILoader* loader = GetImgLoaderForDocument(aDocument);
    3662           0 :     nsCOMPtr<imgICache> cache = do_QueryInterface(loader);
    3663             : 
    3664             :     // If something unexpected happened we return false, otherwise if props
    3665             :     // is set, the image is cached and we return true
    3666           0 :     nsCOMPtr<nsIProperties> props;
    3667           0 :     nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
    3668           0 :     nsresult rv = cache->FindEntryProperties(aURI, domDoc, getter_AddRefs(props));
    3669           0 :     return (NS_SUCCEEDED(rv) && props);
    3670             : }
    3671             : 
    3672             : // static
    3673             : nsresult
    3674          45 : nsContentUtils::LoadImage(nsIURI* aURI, nsINode* aContext,
    3675             :                           nsIDocument* aLoadingDocument,
    3676             :                           nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
    3677             :                           net::ReferrerPolicy aReferrerPolicy,
    3678             :                           imgINotificationObserver* aObserver, int32_t aLoadFlags,
    3679             :                           const nsAString& initiatorType,
    3680             :                           imgRequestProxy** aRequest,
    3681             :                           uint32_t aContentPolicyType,
    3682             :                           bool aUseUrgentStartForChannel)
    3683             : {
    3684          45 :   NS_PRECONDITION(aURI, "Must have a URI");
    3685          45 :   NS_PRECONDITION(aContext, "Must have a context");
    3686          45 :   NS_PRECONDITION(aLoadingDocument, "Must have a document");
    3687          45 :   NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
    3688          45 :   NS_PRECONDITION(aRequest, "Null out param");
    3689             : 
    3690          45 :   imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
    3691          45 :   if (!imgLoader) {
    3692             :     // nothing we can do here
    3693           0 :     return NS_ERROR_FAILURE;
    3694             :   }
    3695             : 
    3696          90 :   nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
    3697             : 
    3698          45 :   nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
    3699             : 
    3700          45 :   NS_ASSERTION(loadGroup || IsFontTableURI(documentURI),
    3701             :                "Could not get loadgroup; onload may fire too early");
    3702             : 
    3703             :   // Make the URI immutable so people won't change it under us
    3704          45 :   NS_TryToSetImmutable(aURI);
    3705             : 
    3706             :   // XXXbz using "documentURI" for the initialDocumentURI is not quite
    3707             :   // right, but the best we can do here...
    3708          45 :   return imgLoader->LoadImage(aURI,                 /* uri to load */
    3709             :                               documentURI,          /* initialDocumentURI */
    3710             :                               aReferrer,            /* referrer */
    3711             :                               aReferrerPolicy,      /* referrer policy */
    3712             :                               aLoadingPrincipal,    /* loading principal */
    3713             :                               loadGroup,            /* loadgroup */
    3714             :                               aObserver,            /* imgINotificationObserver */
    3715             :                               aContext,             /* loading context */
    3716             :                               aLoadingDocument,     /* uniquification key */
    3717             :                               aLoadFlags,           /* load flags */
    3718             :                               nullptr,              /* cache key */
    3719             :                               aContentPolicyType,   /* content policy type */
    3720             :                               initiatorType,        /* the load initiator */
    3721             :                               aUseUrgentStartForChannel, /* urgent-start flag */
    3722          45 :                               aRequest);
    3723             : }
    3724             : 
    3725             : // static
    3726             : already_AddRefed<imgIContainer>
    3727           0 : nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
    3728             :                                     imgIRequest **aRequest)
    3729             : {
    3730           0 :   if (aRequest) {
    3731           0 :     *aRequest = nullptr;
    3732             :   }
    3733             : 
    3734           0 :   NS_ENSURE_TRUE(aContent, nullptr);
    3735             : 
    3736           0 :   nsCOMPtr<imgIRequest> imgRequest;
    3737           0 :   aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    3738           0 :                       getter_AddRefs(imgRequest));
    3739           0 :   if (!imgRequest) {
    3740           0 :     return nullptr;
    3741             :   }
    3742             : 
    3743           0 :   nsCOMPtr<imgIContainer> imgContainer;
    3744           0 :   imgRequest->GetImage(getter_AddRefs(imgContainer));
    3745             : 
    3746           0 :   if (!imgContainer) {
    3747           0 :     return nullptr;
    3748             :   }
    3749             : 
    3750           0 :   if (aRequest) {
    3751           0 :     imgRequest.swap(*aRequest);
    3752             :   }
    3753             : 
    3754           0 :   return imgContainer.forget();
    3755             : }
    3756             : 
    3757             : //static
    3758             : already_AddRefed<imgRequestProxy>
    3759           0 : nsContentUtils::GetStaticRequest(imgRequestProxy* aRequest)
    3760             : {
    3761           0 :   NS_ENSURE_TRUE(aRequest, nullptr);
    3762           0 :   RefPtr<imgRequestProxy> retval;
    3763           0 :   aRequest->GetStaticRequest(getter_AddRefs(retval));
    3764           0 :   return retval.forget();
    3765             : }
    3766             : 
    3767             : // static
    3768             : bool
    3769           0 : nsContentUtils::ContentIsDraggable(nsIContent* aContent)
    3770             : {
    3771           0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aContent);
    3772           0 :   if (htmlElement) {
    3773           0 :     bool draggable = false;
    3774           0 :     htmlElement->GetDraggable(&draggable);
    3775           0 :     if (draggable)
    3776           0 :       return true;
    3777             : 
    3778           0 :     if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
    3779             :                               nsGkAtoms::_false, eIgnoreCase))
    3780           0 :       return false;
    3781             :   }
    3782             : 
    3783             :   // special handling for content area image and link dragging
    3784           0 :   return IsDraggableImage(aContent) || IsDraggableLink(aContent);
    3785             : }
    3786             : 
    3787             : // static
    3788             : bool
    3789           0 : nsContentUtils::IsDraggableImage(nsIContent* aContent)
    3790             : {
    3791           0 :   NS_PRECONDITION(aContent, "Must have content node to test");
    3792             : 
    3793           0 :   nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aContent));
    3794           0 :   if (!imageContent) {
    3795           0 :     return false;
    3796             :   }
    3797             : 
    3798           0 :   nsCOMPtr<imgIRequest> imgRequest;
    3799           0 :   imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    3800           0 :                            getter_AddRefs(imgRequest));
    3801             : 
    3802             :   // XXXbz It may be draggable even if the request resulted in an error.  Why?
    3803             :   // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
    3804           0 :   return imgRequest != nullptr;
    3805             : }
    3806             : 
    3807             : // static
    3808             : bool
    3809           0 : nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
    3810           0 :   nsCOMPtr<nsIURI> absURI;
    3811           0 :   return aContent->IsLink(getter_AddRefs(absURI));
    3812             : }
    3813             : 
    3814             : // static
    3815             : nsresult
    3816           0 : nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo, nsIAtom* aName,
    3817             :                              mozilla::dom::NodeInfo** aResult)
    3818             : {
    3819           0 :   nsNodeInfoManager *niMgr = aNodeInfo->NodeInfoManager();
    3820             : 
    3821           0 :   *aResult = niMgr->GetNodeInfo(aName, nullptr,
    3822             :                                 aNodeInfo->NamespaceID(),
    3823           0 :                                 aNodeInfo->NodeType(),
    3824           0 :                                 aNodeInfo->GetExtraName()).take();
    3825           0 :   return NS_OK;
    3826             : }
    3827             : 
    3828             : 
    3829             : static bool
    3830          13 : TestSitePerm(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPerm, bool aExactHostMatch)
    3831             : {
    3832          13 :   if (!aPrincipal) {
    3833             :     // We always deny (i.e. don't allow) the permission if we don't have a
    3834             :     // principal.
    3835           0 :     return aPerm != nsIPermissionManager::ALLOW_ACTION;
    3836             :   }
    3837             : 
    3838          26 :   nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
    3839          13 :   NS_ENSURE_TRUE(permMgr, false);
    3840             : 
    3841             :   uint32_t perm;
    3842             :   nsresult rv;
    3843          13 :   if (aExactHostMatch) {
    3844           0 :     rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
    3845             :   } else {
    3846          13 :     rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
    3847             :   }
    3848          13 :   NS_ENSURE_SUCCESS(rv, false);
    3849             : 
    3850          13 :   return perm == aPerm;
    3851             : }
    3852             : 
    3853             : bool
    3854          13 : nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
    3855             : {
    3856          13 :   return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, false);
    3857             : }
    3858             : 
    3859             : bool
    3860           0 : nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal, const char* aType)
    3861             : {
    3862           0 :   return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, false);
    3863             : }
    3864             : 
    3865             : bool
    3866           0 : nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
    3867             : {
    3868           0 :   return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, true);
    3869             : }
    3870             : 
    3871             : bool
    3872           0 : nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal, const char* aType)
    3873             : {
    3874           0 :   return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, true);
    3875             : }
    3876             : 
    3877             : static const char *gEventNames[] = {"event"};
    3878             : static const char *gSVGEventNames[] = {"evt"};
    3879             : // for b/w compat, the first name to onerror is still 'event', even though it
    3880             : // is actually the error message
    3881             : static const char *gOnErrorNames[] = {"event", "source", "lineno",
    3882             :                                       "colno", "error"};
    3883             : 
    3884             : // static
    3885             : void
    3886          11 : nsContentUtils::GetEventArgNames(int32_t aNameSpaceID,
    3887             :                                  nsIAtom *aEventName,
    3888             :                                  bool aIsForWindow,
    3889             :                                  uint32_t *aArgCount,
    3890             :                                  const char*** aArgArray)
    3891             : {
    3892             : #define SET_EVENT_ARG_NAMES(names) \
    3893             :     *aArgCount = sizeof(names)/sizeof(names[0]); \
    3894             :     *aArgArray = names;
    3895             : 
    3896             :   // JSEventHandler is what does the arg magic for onerror, and it does
    3897             :   // not seem to take the namespace into account.  So we let onerror in all
    3898             :   // namespaces get the 3 arg names.
    3899          11 :   if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
    3900           0 :     SET_EVENT_ARG_NAMES(gOnErrorNames);
    3901          11 :   } else if (aNameSpaceID == kNameSpaceID_SVG) {
    3902           0 :     SET_EVENT_ARG_NAMES(gSVGEventNames);
    3903             :   } else {
    3904          11 :     SET_EVENT_ARG_NAMES(gEventNames);
    3905             :   }
    3906          11 : }
    3907             : 
    3908             : static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
    3909             :   // Must line up with the enum values in |PropertiesFile| enum.
    3910             :   "chrome://global/locale/css.properties",
    3911             :   "chrome://global/locale/xbl.properties",
    3912             :   "chrome://global/locale/xul.properties",
    3913             :   "chrome://global/locale/layout_errors.properties",
    3914             :   "chrome://global/locale/layout/HtmlForm.properties",
    3915             :   "chrome://global/locale/printing.properties",
    3916             :   "chrome://global/locale/dom/dom.properties",
    3917             :   "chrome://global/locale/layout/htmlparser.properties",
    3918             :   "chrome://global/locale/svg/svg.properties",
    3919             :   "chrome://branding/locale/brand.properties",
    3920             :   "chrome://global/locale/commonDialogs.properties",
    3921             :   "chrome://global/locale/mathml/mathml.properties",
    3922             :   "chrome://global/locale/security/security.properties",
    3923             :   "chrome://necko/locale/necko.properties"
    3924             : };
    3925             : 
    3926             : /* static */ nsresult
    3927           0 : nsContentUtils::EnsureStringBundle(PropertiesFile aFile)
    3928             : {
    3929           0 :   if (!sStringBundles[aFile]) {
    3930           0 :     if (!sStringBundleService) {
    3931             :       nsresult rv =
    3932           0 :         CallGetService(NS_STRINGBUNDLE_CONTRACTID, &sStringBundleService);
    3933           0 :       NS_ENSURE_SUCCESS(rv, rv);
    3934             :     }
    3935             :     nsIStringBundle *bundle;
    3936             :     nsresult rv =
    3937           0 :       sStringBundleService->CreateBundle(gPropertiesFiles[aFile], &bundle);
    3938           0 :     NS_ENSURE_SUCCESS(rv, rv);
    3939           0 :     sStringBundles[aFile] = bundle; // transfer ownership
    3940             :   }
    3941           0 :   return NS_OK;
    3942             : }
    3943             : 
    3944             : /* static */
    3945           0 : nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
    3946             :                                             const char* aKey,
    3947             :                                             nsXPIDLString& aResult)
    3948             : {
    3949           0 :   nsresult rv = EnsureStringBundle(aFile);
    3950           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3951           0 :   nsIStringBundle *bundle = sStringBundles[aFile];
    3952             : 
    3953           0 :   return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
    3954           0 :                                    getter_Copies(aResult));
    3955             : }
    3956             : 
    3957             : /* static */
    3958           0 : nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile,
    3959             :                                                const char* aKey,
    3960             :                                                const char16_t **aParams,
    3961             :                                                uint32_t aParamsLength,
    3962             :                                                nsXPIDLString& aResult)
    3963             : {
    3964           0 :   nsresult rv = EnsureStringBundle(aFile);
    3965           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3966           0 :   nsIStringBundle *bundle = sStringBundles[aFile];
    3967             : 
    3968           0 :   if (!aParams || !aParamsLength) {
    3969           0 :     return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
    3970           0 :                                      getter_Copies(aResult));
    3971             :   }
    3972             : 
    3973           0 :   return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
    3974             :                                       aParams, aParamsLength,
    3975           0 :                                       getter_Copies(aResult));
    3976             : }
    3977             : 
    3978             : /* static */
    3979           0 : nsresult nsContentUtils::FormatLocalizedString(
    3980             :                                           PropertiesFile aFile,
    3981             :                                           const char* aKey,
    3982             :                                           const nsTArray<nsString>& aParamArray,
    3983             :                                           nsXPIDLString& aResult)
    3984             : {
    3985           0 :   MOZ_ASSERT(NS_IsMainThread());
    3986             : 
    3987           0 :   UniquePtr<const char16_t*[]> params;
    3988           0 :   uint32_t paramsLength = aParamArray.Length();
    3989           0 :   if (paramsLength > 0) {
    3990           0 :     params = MakeUnique<const char16_t*[]>(paramsLength);
    3991           0 :     for (uint32_t i = 0; i < paramsLength; ++i) {
    3992           0 :       params[i] = aParamArray[i].get();
    3993             :     }
    3994             :   }
    3995           0 :   return FormatLocalizedString(aFile, aKey, params.get(), paramsLength,
    3996           0 :                                aResult);
    3997             : }
    3998             : 
    3999             : 
    4000             : /* static */ void
    4001           0 : nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
    4002             :                                       const char * classification)
    4003             : {
    4004             :   nsCOMPtr<nsIScriptError> scriptError =
    4005           0 :     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
    4006           0 :   if (scriptError) {
    4007             :     nsCOMPtr<nsIConsoleService> console =
    4008           0 :       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
    4009           0 :     if (console && NS_SUCCEEDED(scriptError->Init(aErrorText, EmptyString(),
    4010             :                                                   EmptyString(), 0, 0,
    4011             :                                                   nsIScriptError::errorFlag,
    4012             :                                                   classification))) {
    4013           0 :       console->LogMessage(scriptError);
    4014             :     }
    4015             :   }
    4016           0 : }
    4017             : 
    4018             : /* static */ nsresult
    4019           0 : nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
    4020             :                                 const nsACString& aCategory,
    4021             :                                 const nsIDocument* aDocument,
    4022             :                                 PropertiesFile aFile,
    4023             :                                 const char *aMessageName,
    4024             :                                 const char16_t **aParams,
    4025             :                                 uint32_t aParamsLength,
    4026             :                                 nsIURI* aURI,
    4027             :                                 const nsString& aSourceLine,
    4028             :                                 uint32_t aLineNumber,
    4029             :                                 uint32_t aColumnNumber)
    4030             : {
    4031           0 :   NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
    4032             :                "Supply either both parameters and their number or no"
    4033             :                "parameters and 0.");
    4034             : 
    4035             :   nsresult rv;
    4036           0 :   nsXPIDLString errorText;
    4037           0 :   if (aParams) {
    4038             :     rv = FormatLocalizedString(aFile, aMessageName, aParams, aParamsLength,
    4039           0 :                                errorText);
    4040             :   }
    4041             :   else {
    4042           0 :     rv = GetLocalizedString(aFile, aMessageName, errorText);
    4043             :   }
    4044           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4045             : 
    4046             :   return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
    4047             :                                      aDocument, aURI, aSourceLine,
    4048           0 :                                      aLineNumber, aColumnNumber);
    4049             : }
    4050             : 
    4051             : 
    4052             : /* static */ nsresult
    4053           0 : nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
    4054             :                                             uint32_t aErrorFlags,
    4055             :                                             const nsACString& aCategory,
    4056             :                                             const nsIDocument* aDocument,
    4057             :                                             nsIURI* aURI,
    4058             :                                             const nsString& aSourceLine,
    4059             :                                             uint32_t aLineNumber,
    4060             :                                             uint32_t aColumnNumber,
    4061             :                                             MissingErrorLocationMode aLocationMode)
    4062             : {
    4063           0 :   uint64_t innerWindowID = 0;
    4064           0 :   if (aDocument) {
    4065           0 :     if (!aURI) {
    4066           0 :       aURI = aDocument->GetDocumentURI();
    4067             :     }
    4068           0 :     innerWindowID = aDocument->InnerWindowID();
    4069             :   }
    4070             : 
    4071             :   return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
    4072             :                                    innerWindowID, aURI, aSourceLine,
    4073           0 :                                    aLineNumber, aColumnNumber, aLocationMode);
    4074             : }
    4075             : 
    4076             : /* static */ nsresult
    4077           0 : nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
    4078             :                                           uint32_t aErrorFlags,
    4079             :                                           const nsACString& aCategory,
    4080             :                                           uint64_t aInnerWindowID,
    4081             :                                           nsIURI* aURI,
    4082             :                                           const nsString& aSourceLine,
    4083             :                                           uint32_t aLineNumber,
    4084             :                                           uint32_t aColumnNumber,
    4085             :                                           MissingErrorLocationMode aLocationMode)
    4086             : {
    4087             :   nsresult rv;
    4088           0 :   if (!sConsoleService) { // only need to bother null-checking here
    4089           0 :     rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
    4090           0 :     NS_ENSURE_SUCCESS(rv, rv);
    4091             :   }
    4092             : 
    4093           0 :   nsAutoCString spec;
    4094           0 :   if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
    4095           0 :     JSContext *cx = GetCurrentJSContext();
    4096           0 :     if (cx) {
    4097           0 :       nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
    4098             :     }
    4099             :   }
    4100           0 :   if (spec.IsEmpty() && aURI) {
    4101           0 :     spec = aURI->GetSpecOrDefault();
    4102             :   }
    4103             : 
    4104             :   nsCOMPtr<nsIScriptError> errorObject =
    4105           0 :       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
    4106           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4107             : 
    4108           0 :   rv = errorObject->InitWithWindowID(aErrorText,
    4109           0 :                                      NS_ConvertUTF8toUTF16(spec), // file name
    4110             :                                      aSourceLine,
    4111             :                                      aLineNumber, aColumnNumber,
    4112             :                                      aErrorFlags, aCategory,
    4113           0 :                                      aInnerWindowID);
    4114           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4115             : 
    4116           0 :   return sConsoleService->LogMessage(errorObject);
    4117             : }
    4118             : 
    4119             : void
    4120           0 : nsContentUtils::LogMessageToConsole(const char* aMsg)
    4121             : {
    4122           0 :   if (!sConsoleService) { // only need to bother null-checking here
    4123           0 :     CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
    4124           0 :     if (!sConsoleService) {
    4125           0 :       return;
    4126             :     }
    4127             :   }
    4128           0 :   sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
    4129             : }
    4130             : 
    4131             : bool
    4132        1540 : nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
    4133             : {
    4134        1540 :   if (!aDocument) {
    4135           0 :     return false;
    4136             :   }
    4137        1540 :   return aDocument->NodePrincipal() == sSystemPrincipal;
    4138             : }
    4139             : 
    4140             : bool
    4141           0 : nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
    4142             : {
    4143           0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
    4144           0 :   nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
    4145           0 :   if (docShellAsItem) {
    4146           0 :     docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
    4147             :   }
    4148           0 :   return sameTypeParent != nullptr;
    4149             : }
    4150             : 
    4151             : bool
    4152          22 : nsContentUtils::IsScriptType(const nsACString& aContentType)
    4153             : {
    4154             :   // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
    4155             :   // define in nsContentDLF.h as well.
    4156          44 :   return aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
    4157          44 :          aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
    4158          44 :          aContentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
    4159          44 :          aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
    4160          44 :          aContentType.EqualsLiteral(TEXT_JAVASCRIPT) ||
    4161          66 :          aContentType.EqualsLiteral(APPLICATION_JSON) ||
    4162          44 :          aContentType.EqualsLiteral(TEXT_JSON);
    4163             : }
    4164             : 
    4165             : bool
    4166          22 : nsContentUtils::IsPlainTextType(const nsACString& aContentType)
    4167             : {
    4168             :   // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
    4169             :   // define in nsContentDLF.h as well.
    4170          44 :   return aContentType.EqualsLiteral(TEXT_PLAIN) ||
    4171          44 :          aContentType.EqualsLiteral(TEXT_CSS) ||
    4172          44 :          aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
    4173          66 :          aContentType.EqualsLiteral(TEXT_VTT) ||
    4174          44 :          IsScriptType(aContentType);
    4175             : }
    4176             : 
    4177             : bool
    4178           0 : nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType)
    4179             : {
    4180             :   // NOTE: This must be a subset of the list in IsPlainTextType().
    4181           0 :   return aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
    4182           0 :          aContentType.EqualsLiteral(APPLICATION_JSON) ||
    4183           0 :          aContentType.EqualsLiteral(TEXT_JSON) ||
    4184           0 :          aContentType.EqualsLiteral(TEXT_VTT);
    4185             : }
    4186             : 
    4187             : bool
    4188         375 : nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument* aDocument,
    4189             :                                              nsIURI* aURI,
    4190             :                                              nsACString& aScriptURI,
    4191             :                                              nsresult* aRv)
    4192             : {
    4193         375 :   MOZ_ASSERT(aRv);
    4194         375 :   bool scriptFileNameModified = false;
    4195         375 :   *aRv = NS_OK;
    4196             : 
    4197         375 :   *aRv = aURI->GetSpec(aScriptURI);
    4198         375 :   NS_ENSURE_SUCCESS(*aRv, false);
    4199             : 
    4200         375 :   if (IsChromeDoc(aDocument)) {
    4201             :     nsCOMPtr<nsIChromeRegistry> chromeReg =
    4202         714 :       mozilla::services::GetChromeRegistryService();
    4203             : 
    4204         357 :     if (!chromeReg) {
    4205             :       // If we're running w/o a chrome registry we won't modify any
    4206             :       // script file names.
    4207             : 
    4208           0 :       return scriptFileNameModified;
    4209             :     }
    4210             : 
    4211             :     bool docWrappersEnabled =
    4212         357 :       chromeReg->WrappersEnabled(aDocument->GetDocumentURI());
    4213             : 
    4214         357 :     bool uriWrappersEnabled = chromeReg->WrappersEnabled(aURI);
    4215             : 
    4216         357 :     nsIURI *docURI = aDocument->GetDocumentURI();
    4217             : 
    4218         357 :     if (docURI && docWrappersEnabled && !uriWrappersEnabled) {
    4219             :       // aURI is a script from a URL that doesn't get wrapper
    4220             :       // automation. aDocument is a chrome document that does get
    4221             :       // wrapper automation. Prepend the chrome document's URI
    4222             :       // followed by the string " -> " to the URI of the script we're
    4223             :       // loading here so that script in that URI gets the same wrapper
    4224             :       // automation that the chrome document expects.
    4225           0 :       nsAutoCString spec;
    4226           0 :       *aRv = docURI->GetSpec(spec);
    4227           0 :       if (NS_WARN_IF(NS_FAILED(*aRv))) {
    4228           0 :         return false;
    4229             :       }
    4230             : 
    4231           0 :       spec.AppendLiteral(" -> ");
    4232           0 :       spec.Append(aScriptURI);
    4233             : 
    4234           0 :       aScriptURI = spec;
    4235             : 
    4236           0 :       scriptFileNameModified = true;
    4237             :     }
    4238             :   }
    4239             : 
    4240         375 :   return scriptFileNameModified;
    4241             : }
    4242             : 
    4243             : // static
    4244             : bool
    4245          14 : nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
    4246             : {
    4247          14 :   if (!aDocument) {
    4248           0 :     return false;
    4249             :   }
    4250             : 
    4251          14 :   if (aDocument->GetDisplayDocument()) {
    4252           0 :     return IsInChromeDocshell(aDocument->GetDisplayDocument());
    4253             :   }
    4254             : 
    4255          28 :   nsCOMPtr<nsIDocShellTreeItem> docShell = aDocument->GetDocShell();
    4256          14 :   if (!docShell) {
    4257           0 :     return false;
    4258             :   }
    4259             : 
    4260          14 :   return docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
    4261             : }
    4262             : 
    4263             : // static
    4264             : nsIContentPolicy*
    4265         204 : nsContentUtils::GetContentPolicy()
    4266             : {
    4267         204 :   if (!sTriedToGetContentPolicy) {
    4268           3 :     CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
    4269             :     // It's OK to not have a content policy service
    4270           3 :     sTriedToGetContentPolicy = true;
    4271             :   }
    4272             : 
    4273         204 :   return sContentPolicyService;
    4274             : }
    4275             : 
    4276             : // static
    4277             : bool
    4278        6050 : nsContentUtils::IsEventAttributeName(nsIAtom* aName, int32_t aType)
    4279             : {
    4280        6050 :   const char16_t* name = aName->GetUTF16String();
    4281        6050 :   if (name[0] != 'o' || name[1] != 'n')
    4282        5494 :     return false;
    4283             : 
    4284             :   EventNameMapping mapping;
    4285         556 :   return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
    4286             : }
    4287             : 
    4288             : // static
    4289             : EventMessage
    4290         707 : nsContentUtils::GetEventMessage(nsIAtom* aName)
    4291             : {
    4292         707 :   if (aName) {
    4293             :     EventNameMapping mapping;
    4294         707 :     if (sAtomEventTable->Get(aName, &mapping)) {
    4295         556 :       return mapping.mMessage;
    4296             :     }
    4297             :   }
    4298             : 
    4299         151 :   return eUnidentifiedEvent;
    4300             : }
    4301             : 
    4302             : // static
    4303             : mozilla::EventClassID
    4304         133 : nsContentUtils::GetEventClassID(const nsAString& aName)
    4305             : {
    4306             :   EventNameMapping mapping;
    4307         133 :   if (sStringEventTable->Get(aName, &mapping))
    4308         118 :     return mapping.mEventClassID;
    4309             : 
    4310          15 :   return eBasicEventClass;
    4311             : }
    4312             : 
    4313             : nsIAtom*
    4314         425 : nsContentUtils::GetEventMessageAndAtom(const nsAString& aName,
    4315             :                                        mozilla::EventClassID aEventClassID,
    4316             :                                        EventMessage* aEventMessage)
    4317             : {
    4318             :   EventNameMapping mapping;
    4319         425 :   if (sStringEventTable->Get(aName, &mapping)) {
    4320         274 :     *aEventMessage =
    4321         274 :       mapping.mEventClassID == aEventClassID ? mapping.mMessage :
    4322             :                                                eUnidentifiedEvent;
    4323         274 :     return mapping.mAtom;
    4324             :   }
    4325             : 
    4326             :   // If we have cached lots of user defined event names, clear some of them.
    4327         151 :   if (sUserDefinedEvents->Count() > 127) {
    4328           0 :     while (sUserDefinedEvents->Count() > 64) {
    4329           0 :       nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
    4330           0 :       sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
    4331           0 :       sUserDefinedEvents->RemoveObjectAt(0);
    4332             :     }
    4333             :   }
    4334             : 
    4335         151 :   *aEventMessage = eUnidentifiedEvent;
    4336             :   nsCOMPtr<nsIAtom> atom =
    4337         302 :     NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
    4338         151 :   sUserDefinedEvents->AppendObject(atom);
    4339         151 :   mapping.mAtom = atom;
    4340         151 :   mapping.mMessage = eUnidentifiedEvent;
    4341         151 :   mapping.mType = EventNameType_None;
    4342         151 :   mapping.mEventClassID = eBasicEventClass;
    4343             :   // This is a slow hashtable call, but at least we cache the result for the
    4344             :   // following calls. Because GetEventMessageAndAtomForListener utilizes
    4345             :   // sStringEventTable, it needs to know in which cases sStringEventTable
    4346             :   // doesn't contain the information it needs so that it can use
    4347             :   // sAtomEventTable instead.
    4348         151 :   mapping.mMaybeSpecialSVGorSMILEvent =
    4349         151 :     GetEventMessage(atom) != eUnidentifiedEvent;
    4350         151 :   sStringEventTable->Put(aName, mapping);
    4351         151 :   return mapping.mAtom;
    4352             : }
    4353             : 
    4354             : // static
    4355             : EventMessage
    4356        1852 : nsContentUtils::GetEventMessageAndAtomForListener(const nsAString& aName,
    4357             :                                                   nsIAtom** aOnName)
    4358             : {
    4359             :   // Because of SVG/SMIL sStringEventTable contains a subset of the event names
    4360             :   // comparing to the sAtomEventTable. However, usually sStringEventTable
    4361             :   // contains the information we need, so in order to reduce hashtable
    4362             :   // lookups, start from it.
    4363             :   EventNameMapping mapping;
    4364        1852 :   EventMessage msg = eUnidentifiedEvent;
    4365        3704 :   nsCOMPtr<nsIAtom> atom;
    4366        1852 :   if (sStringEventTable->Get(aName, &mapping)) {
    4367        1720 :     if (mapping.mMaybeSpecialSVGorSMILEvent) {
    4368             :       // Try the atom version so that we should get the right message for
    4369             :       // SVG/SMIL.
    4370           0 :       atom = NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
    4371           0 :       msg = GetEventMessage(atom);
    4372             :     } else {
    4373        1720 :       atom = mapping.mAtom;
    4374        1720 :       msg = mapping.mMessage;
    4375             :     }
    4376        1720 :     atom.forget(aOnName);
    4377        1720 :     return msg;
    4378             :   }
    4379             : 
    4380             :   // GetEventMessageAndAtom will cache the event type for the future usage...
    4381         132 :   GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
    4382             : 
    4383             :   // ...and then call this method recursively to get the message and atom from
    4384             :   // now updated sStringEventTable.
    4385         132 :   return GetEventMessageAndAtomForListener(aName, aOnName);
    4386             : }
    4387             : 
    4388             : static
    4389         123 : nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
    4390             :                            const nsAString& aEventName,
    4391             :                            bool aCanBubble, bool aCancelable,
    4392             :                            bool aTrusted, nsIDOMEvent** aEvent,
    4393             :                            EventTarget** aTargetOut)
    4394             : {
    4395         246 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
    4396         246 :   nsCOMPtr<EventTarget> target(do_QueryInterface(aTarget));
    4397         123 :   NS_ENSURE_TRUE(domDoc && target, NS_ERROR_INVALID_ARG);
    4398             : 
    4399         246 :   nsCOMPtr<nsIDOMEvent> event;
    4400             :   nsresult rv =
    4401         123 :     domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
    4402         123 :   NS_ENSURE_SUCCESS(rv, rv);
    4403             : 
    4404         123 :   event->InitEvent(aEventName, aCanBubble, aCancelable);
    4405         123 :   event->SetTrusted(aTrusted);
    4406             : 
    4407         123 :   rv = event->SetTarget(target);
    4408         123 :   NS_ENSURE_SUCCESS(rv, rv);
    4409             : 
    4410         123 :   event.forget(aEvent);
    4411         123 :   target.forget(aTargetOut);
    4412         123 :   return NS_OK;
    4413             : }
    4414             : 
    4415             : // static
    4416             : nsresult
    4417          52 : nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
    4418             :                                      const nsAString& aEventName,
    4419             :                                      bool aCanBubble, bool aCancelable,
    4420             :                                      bool* aDefaultAction)
    4421             : {
    4422          52 :   return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
    4423          52 :                        true, aDefaultAction);
    4424             : }
    4425             : 
    4426             : // static
    4427             : nsresult
    4428           0 : nsContentUtils::DispatchUntrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
    4429             :                                        const nsAString& aEventName,
    4430             :                                        bool aCanBubble, bool aCancelable,
    4431             :                                        bool* aDefaultAction)
    4432             : {
    4433           0 :   return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
    4434           0 :                        false, aDefaultAction);
    4435             : }
    4436             : 
    4437             : // static
    4438             : nsresult
    4439          56 : nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
    4440             :                               const nsAString& aEventName,
    4441             :                               bool aCanBubble, bool aCancelable,
    4442             :                               bool aTrusted, bool* aDefaultAction,
    4443             :                               bool aOnlyChromeDispatch)
    4444             : {
    4445         112 :   nsCOMPtr<nsIDOMEvent> event;
    4446         112 :   nsCOMPtr<EventTarget> target;
    4447         112 :   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
    4448         112 :                                   aCancelable, aTrusted, getter_AddRefs(event),
    4449         168 :                                   getter_AddRefs(target));
    4450          56 :   NS_ENSURE_SUCCESS(rv, rv);
    4451          56 :   event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
    4452             : 
    4453             :   bool dummy;
    4454          56 :   return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
    4455             : }
    4456             : 
    4457             : // static
    4458             : nsresult
    4459           4 : nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
    4460             :                               WidgetEvent& aEvent,
    4461             :                               EventMessage aEventMessage,
    4462             :                               bool aCanBubble, bool aCancelable,
    4463             :                               bool aTrusted, bool *aDefaultAction,
    4464             :                               bool aOnlyChromeDispatch)
    4465             : {
    4466           4 :   MOZ_ASSERT_IF(aOnlyChromeDispatch, aTrusted);
    4467             : 
    4468           8 :   nsCOMPtr<EventTarget> target(do_QueryInterface(aTarget));
    4469             : 
    4470           4 :   aEvent.mTime = PR_Now();
    4471             : 
    4472           4 :   aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
    4473           4 :   aEvent.SetDefaultComposed();
    4474           4 :   aEvent.SetDefaultComposedInNativeAnonymousContent();
    4475             : 
    4476           4 :   aEvent.mFlags.mBubbles = aCanBubble;
    4477           4 :   aEvent.mFlags.mCancelable = aCancelable;
    4478           4 :   aEvent.mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
    4479             : 
    4480           4 :   aEvent.mTarget = target;
    4481             : 
    4482           4 :   nsEventStatus status = nsEventStatus_eIgnore;
    4483             :   nsresult rv = EventDispatcher::DispatchDOMEvent(target, &aEvent, nullptr,
    4484           4 :                                                   nullptr, &status);
    4485           4 :   if (aDefaultAction) {
    4486           0 :     *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
    4487             :   }
    4488           8 :   return rv;
    4489             : }
    4490             : 
    4491             : nsresult
    4492          67 : nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
    4493             :                                     nsISupports *aTarget,
    4494             :                                     const nsAString& aEventName,
    4495             :                                     bool aCanBubble, bool aCancelable,
    4496             :                                     bool* aDefaultAction)
    4497             : {
    4498             : 
    4499         134 :   nsCOMPtr<nsIDOMEvent> event;
    4500         134 :   nsCOMPtr<EventTarget> target;
    4501         134 :   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
    4502         134 :                                   aCancelable, true, getter_AddRefs(event),
    4503         201 :                                   getter_AddRefs(target));
    4504          67 :   NS_ENSURE_SUCCESS(rv, rv);
    4505             : 
    4506          67 :   NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
    4507          67 :   if (!aDoc->GetWindow())
    4508          44 :     return NS_ERROR_INVALID_ARG;
    4509             : 
    4510          23 :   EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
    4511          23 :   if (!piTarget)
    4512           0 :     return NS_ERROR_INVALID_ARG;
    4513             : 
    4514          23 :   nsEventStatus status = nsEventStatus_eIgnore;
    4515          23 :   rv = piTarget->DispatchDOMEvent(nullptr, event, nullptr, &status);
    4516          23 :   if (aDefaultAction) {
    4517           0 :     *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
    4518             :   }
    4519          23 :   return rv;
    4520             : }
    4521             : 
    4522             : /* static */
    4523             : nsresult
    4524           0 : nsContentUtils::DispatchFocusChromeEvent(nsPIDOMWindowOuter* aWindow)
    4525             : {
    4526           0 :   MOZ_ASSERT(aWindow);
    4527             : 
    4528           0 :   nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
    4529           0 :   if (!doc) {
    4530           0 :     return NS_ERROR_FAILURE;
    4531             :   }
    4532             : 
    4533           0 :   return DispatchChromeEvent(doc, aWindow,
    4534           0 :                              NS_LITERAL_STRING("DOMWindowFocus"),
    4535           0 :                              true, true);
    4536             : }
    4537             : 
    4538             : nsresult
    4539           4 : nsContentUtils::DispatchEventOnlyToChrome(nsIDocument* aDoc,
    4540             :                                           nsISupports* aTarget,
    4541             :                                           const nsAString& aEventName,
    4542             :                                           bool aCanBubble, bool aCancelable,
    4543             :                                           bool* aDefaultAction)
    4544             : {
    4545           4 :   return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
    4546           4 :                        true, aDefaultAction, true);
    4547             : }
    4548             : 
    4549             : /* static */
    4550             : Element*
    4551           0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId)
    4552             : {
    4553           0 :   for (nsIContent* cur = aContent;
    4554           0 :        cur;
    4555           0 :        cur = cur->GetNextNode(aContent)) {
    4556           0 :     if (aId == cur->GetID()) {
    4557           0 :       return cur->AsElement();
    4558             :     }
    4559             :   }
    4560             : 
    4561           0 :   return nullptr;
    4562             : }
    4563             : 
    4564             : /* static */
    4565             : Element *
    4566           0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
    4567             : {
    4568           0 :   NS_PRECONDITION(!aId.IsEmpty(), "Will match random elements");
    4569             : 
    4570             :   // ID attrs are generally stored as atoms, so just atomize this up front
    4571           0 :   nsCOMPtr<nsIAtom> id(NS_Atomize(aId));
    4572           0 :   if (!id) {
    4573             :     // OOM, so just bail
    4574           0 :     return nullptr;
    4575             :   }
    4576             : 
    4577           0 :   return MatchElementId(aContent, id);
    4578             : }
    4579             : 
    4580             : /* static */
    4581             : nsIDocument*
    4582           0 : nsContentUtils::GetSubdocumentWithOuterWindowId(nsIDocument *aDocument,
    4583             :                                                 uint64_t aOuterWindowId)
    4584             : {
    4585           0 :   if (!aDocument || !aOuterWindowId) {
    4586           0 :     return nullptr;
    4587             :   }
    4588             : 
    4589           0 :   RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(aOuterWindowId);
    4590           0 :   if (!window) {
    4591           0 :     return nullptr;
    4592             :   }
    4593             : 
    4594           0 :   nsCOMPtr<nsPIDOMWindowOuter> outerWindow = window->AsOuter();
    4595           0 :   nsCOMPtr<nsIDocument> foundDoc = outerWindow->GetDoc();
    4596           0 :   if (nsContentUtils::ContentIsCrossDocDescendantOf(foundDoc, aDocument)) {
    4597             :     // Note that ContentIsCrossDocDescendantOf will return true if
    4598             :     // foundDoc == aDocument.
    4599           0 :     return foundDoc;
    4600             :   }
    4601             : 
    4602           0 :   return nullptr;
    4603             : }
    4604             : 
    4605             : /* static */
    4606             : void
    4607           8 : nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver)
    4608             : {
    4609             :   nsCOMPtr<nsIObserverService> observerService =
    4610          16 :     mozilla::services::GetObserverService();
    4611           8 :   if (observerService) {
    4612           8 :     observerService->AddObserver(aObserver,
    4613             :                                  NS_XPCOM_SHUTDOWN_OBSERVER_ID,
    4614           8 :                                  false);
    4615             :   }
    4616           8 : }
    4617             : 
    4618             : /* static */
    4619             : void
    4620           0 : nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver)
    4621             : {
    4622             :   nsCOMPtr<nsIObserverService> observerService =
    4623           0 :     mozilla::services::GetObserverService();
    4624           0 :   if (observerService) {
    4625           0 :     observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    4626             :   }
    4627           0 : }
    4628             : 
    4629             : /* static */
    4630             : bool
    4631          94 : nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, int32_t aNameSpaceID,
    4632             :                                 nsIAtom* aName)
    4633             : {
    4634             :   static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nullptr};
    4635          94 :   return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
    4636          94 :     == nsIContent::ATTR_VALUE_NO_MATCH;
    4637             : }
    4638             : 
    4639             : /* static */
    4640             : bool
    4641         836 : nsContentUtils::HasMutationListeners(nsINode* aNode,
    4642             :                                      uint32_t aType,
    4643             :                                      nsINode* aTargetForSubtreeModified)
    4644             : {
    4645         836 :   nsIDocument* doc = aNode->OwnerDoc();
    4646             : 
    4647             :   // global object will be null for documents that don't have windows.
    4648         836 :   nsPIDOMWindowInner* window = doc->GetInnerWindow();
    4649             :   // This relies on EventListenerManager::AddEventListener, which sets
    4650             :   // all mutation bits when there is a listener for DOMSubtreeModified event.
    4651         836 :   if (window && !window->HasMutationListeners(aType)) {
    4652         748 :     return false;
    4653             :   }
    4654             : 
    4655         176 :   if (aNode->IsNodeOfType(nsINode::eCONTENT) &&
    4656          88 :       static_cast<nsIContent*>(aNode)->ChromeOnlyAccess()) {
    4657           0 :     return false;
    4658             :   }
    4659             : 
    4660          88 :   doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
    4661             : 
    4662             :   // If we have a window, we can check it for mutation listeners now.
    4663          88 :   if (aNode->IsInUncomposedDoc()) {
    4664          92 :     nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
    4665          46 :     if (piTarget) {
    4666           0 :       EventListenerManager* manager = piTarget->GetExistingListenerManager();
    4667           0 :       if (manager && manager->HasMutationListeners()) {
    4668           0 :         return true;
    4669             :       }
    4670             :     }
    4671             :   }
    4672             : 
    4673             :   // If we have a window, we know a mutation listener is registered, but it
    4674             :   // might not be in our chain.  If we don't have a window, we might have a
    4675             :   // mutation listener.  Check quickly to see.
    4676         356 :   while (aNode) {
    4677         134 :     EventListenerManager* manager = aNode->GetExistingListenerManager();
    4678         134 :     if (manager && manager->HasMutationListeners()) {
    4679           0 :       return true;
    4680             :     }
    4681             : 
    4682         134 :     if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
    4683          88 :       nsIContent* content = static_cast<nsIContent*>(aNode);
    4684          88 :       nsIContent* insertionParent = content->GetXBLInsertionParent();
    4685          88 :       if (insertionParent) {
    4686           0 :         aNode = insertionParent;
    4687           0 :         continue;
    4688             :       }
    4689             :     }
    4690         134 :     aNode = aNode->GetParentNode();
    4691             :   }
    4692             : 
    4693          88 :   return false;
    4694             : }
    4695             : 
    4696             : /* static */
    4697             : bool
    4698           9 : nsContentUtils::HasMutationListeners(nsIDocument* aDocument,
    4699             :                                      uint32_t aType)
    4700             : {
    4701           9 :   nsPIDOMWindowInner* window = aDocument ?
    4702           9 :     aDocument->GetInnerWindow() : nullptr;
    4703             : 
    4704             :   // This relies on EventListenerManager::AddEventListener, which sets
    4705             :   // all mutation bits when there is a listener for DOMSubtreeModified event.
    4706           9 :   return !window || window->HasMutationListeners(aType);
    4707             : }
    4708             : 
    4709             : void
    4710           6 : nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
    4711             :                                      nsIDocument* aOwnerDoc)
    4712             : {
    4713           6 :   NS_PRECONDITION(aChild, "Missing child");
    4714           6 :   NS_PRECONDITION(aChild->GetParentNode() == aParent, "Wrong parent");
    4715           6 :   NS_PRECONDITION(aChild->OwnerDoc() == aOwnerDoc, "Wrong owner-doc");
    4716             : 
    4717             :   // Having an explicit check here since it's an easy mistake to fall into,
    4718             :   // and there might be existing code with problems. We'd rather be safe
    4719             :   // than fire DOMNodeRemoved in all corner cases. We also rely on it for
    4720             :   // nsAutoScriptBlockerSuppressNodeRemoved.
    4721           6 :   if (!IsSafeToRunScript()) {
    4722             :     // This checks that IsSafeToRunScript is true since we don't want to fire
    4723             :     // events when that is false. We can't rely on EventDispatcher to assert
    4724             :     // this in this situation since most of the time there are no mutation
    4725             :     // event listeners, in which case we won't even attempt to dispatch events.
    4726             :     // However this also allows for two exceptions. First off, we don't assert
    4727             :     // if the mutation happens to native anonymous content since we never fire
    4728             :     // mutation events on such content anyway.
    4729             :     // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
    4730             :     // that is a know case when we'd normally fire a mutation event, but can't
    4731             :     // make that safe and so we suppress it at this time. Ideally this should
    4732             :     // go away eventually.
    4733           1 :     if (!(aChild->IsContent() && aChild->AsContent()->IsInNativeAnonymousSubtree()) &&
    4734           0 :         !sDOMNodeRemovedSuppressCount) {
    4735           0 :       NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe");
    4736           0 :       WarnScriptWasIgnored(aOwnerDoc);
    4737             :     }
    4738           1 :     return;
    4739             :   }
    4740             : 
    4741           5 :   if (HasMutationListeners(aChild,
    4742             :         NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
    4743           0 :     InternalMutationEvent mutation(true, eLegacyNodeRemoved);
    4744           0 :     mutation.mRelatedNode = do_QueryInterface(aParent);
    4745             : 
    4746           0 :     mozAutoSubtreeModified subtree(aOwnerDoc, aParent);
    4747           0 :     EventDispatcher::Dispatch(aChild, nullptr, &mutation);
    4748             :   }
    4749             : }
    4750             : 
    4751             : void
    4752           0 : nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments()
    4753             : {
    4754           0 :   if (!sEventListenerManagersHash) {
    4755           0 :     return;
    4756             :   }
    4757             : 
    4758           0 :   for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
    4759           0 :     auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
    4760           0 :     nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
    4761           0 :     if (n && n->IsInUncomposedDoc() &&
    4762           0 :         nsCCUncollectableMarker::InGeneration(n->OwnerDoc()->GetMarkedCCGeneration())) {
    4763           0 :       entry->mListenerManager->MarkForCC();
    4764             :     }
    4765             :   }
    4766             : }
    4767             : 
    4768             : /* static */
    4769             : void
    4770         178 : nsContentUtils::TraverseListenerManager(nsINode *aNode,
    4771             :                                         nsCycleCollectionTraversalCallback &cb)
    4772             : {
    4773         178 :   if (!sEventListenerManagersHash) {
    4774             :     // We're already shut down, just return.
    4775           0 :     return;
    4776             :   }
    4777             : 
    4778             :   auto entry = static_cast<EventListenerManagerMapEntry*>
    4779         178 :                           (sEventListenerManagersHash->Search(aNode));
    4780         178 :   if (entry) {
    4781         178 :     CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
    4782         178 :                              "[via hash] mListenerManager");
    4783             :   }
    4784             : }
    4785             : 
    4786             : EventListenerManager*
    4787        1209 : nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
    4788             : {
    4789        1209 :   if (!sEventListenerManagersHash) {
    4790             :     // We're already shut down, don't bother creating an event listener
    4791             :     // manager.
    4792             : 
    4793           0 :     return nullptr;
    4794             :   }
    4795             : 
    4796             :   auto entry =
    4797             :     static_cast<EventListenerManagerMapEntry*>
    4798        1209 :                (sEventListenerManagersHash->Add(aNode, fallible));
    4799             : 
    4800        1209 :   if (!entry) {
    4801           0 :     return nullptr;
    4802             :   }
    4803             : 
    4804        1209 :   if (!entry->mListenerManager) {
    4805         556 :     entry->mListenerManager = new EventListenerManager(aNode);
    4806             : 
    4807         556 :     aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
    4808             :   }
    4809             : 
    4810        1209 :   return entry->mListenerManager;
    4811             : }
    4812             : 
    4813             : EventListenerManager*
    4814        1185 : nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode)
    4815             : {
    4816        1185 :   if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
    4817         716 :     return nullptr;
    4818             :   }
    4819             : 
    4820         469 :   if (!sEventListenerManagersHash) {
    4821             :     // We're already shut down, don't bother creating an event listener
    4822             :     // manager.
    4823             : 
    4824           0 :     return nullptr;
    4825             :   }
    4826             : 
    4827             :   auto entry = static_cast<EventListenerManagerMapEntry*>
    4828         469 :                           (sEventListenerManagersHash->Search(aNode));
    4829         469 :   if (entry) {
    4830         469 :     return entry->mListenerManager;
    4831             :   }
    4832             : 
    4833           0 :   return nullptr;
    4834             : }
    4835             : 
    4836             : /* static */
    4837             : void
    4838           3 : nsContentUtils::RemoveListenerManager(nsINode *aNode)
    4839             : {
    4840           3 :   if (sEventListenerManagersHash) {
    4841             :     auto entry = static_cast<EventListenerManagerMapEntry*>
    4842           3 :                             (sEventListenerManagersHash->Search(aNode));
    4843           3 :     if (entry) {
    4844           6 :       RefPtr<EventListenerManager> listenerManager;
    4845           3 :       listenerManager.swap(entry->mListenerManager);
    4846             :       // Remove the entry and *then* do operations that could cause further
    4847             :       // modification of sEventListenerManagersHash.  See bug 334177.
    4848           3 :       sEventListenerManagersHash->RawRemove(entry);
    4849           3 :       if (listenerManager) {
    4850           3 :         listenerManager->Disconnect();
    4851             :       }
    4852             :     }
    4853             :   }
    4854           3 : }
    4855             : 
    4856             : /* static */
    4857             : bool
    4858          33 : nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
    4859             :                                 int32_t aNamespaceID)
    4860             : {
    4861          33 :   if (aNamespaceID == kNameSpaceID_Unknown) {
    4862           0 :     return false;
    4863             :   }
    4864             : 
    4865          33 :   if (!aPrefix) {
    4866             :     // If the prefix is null, then either the QName must be xmlns or the
    4867             :     // namespace must not be XMLNS.
    4868          33 :     return (aLocalName == nsGkAtoms::xmlns) ==
    4869          33 :            (aNamespaceID == kNameSpaceID_XMLNS);
    4870             :   }
    4871             : 
    4872             :   // If the prefix is non-null then the namespace must not be null.
    4873           0 :   if (aNamespaceID == kNameSpaceID_None) {
    4874           0 :     return false;
    4875             :   }
    4876             : 
    4877             :   // If the namespace is the XMLNS namespace then the prefix must be xmlns,
    4878             :   // but the localname must not be xmlns.
    4879           0 :   if (aNamespaceID == kNameSpaceID_XMLNS) {
    4880           0 :     return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
    4881             :   }
    4882             : 
    4883             :   // If the namespace is not the XMLNS namespace then the prefix must not be
    4884             :   // xmlns.
    4885             :   // If the namespace is the XML namespace then the prefix can be anything.
    4886             :   // If the namespace is not the XML namespace then the prefix must not be xml.
    4887           0 :   return aPrefix != nsGkAtoms::xmlns &&
    4888           0 :          (aNamespaceID == kNameSpaceID_XML || aPrefix != nsGkAtoms::xml);
    4889             : }
    4890             : 
    4891             : /* static */
    4892             : nsresult
    4893           0 : nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
    4894             :                                          const nsAString& aFragment,
    4895             :                                          bool aPreventScriptExecution,
    4896             :                                          nsIDOMDocumentFragment** aReturn)
    4897             : {
    4898           0 :   ErrorResult rv;
    4899           0 :   *aReturn = CreateContextualFragment(aContextNode, aFragment,
    4900           0 :                                       aPreventScriptExecution, rv).take();
    4901           0 :   return rv.StealNSResult();
    4902             : }
    4903             : 
    4904             : already_AddRefed<DocumentFragment>
    4905           0 : nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
    4906             :                                          const nsAString& aFragment,
    4907             :                                          bool aPreventScriptExecution,
    4908             :                                          ErrorResult& aRv)
    4909             : {
    4910           0 :   if (!aContextNode) {
    4911           0 :     aRv.Throw(NS_ERROR_INVALID_ARG);
    4912           0 :     return nullptr;
    4913             :   }
    4914             : 
    4915             :   // If we don't have a document here, we can't get the right security context
    4916             :   // for compiling event handlers... so just bail out.
    4917           0 :   nsCOMPtr<nsIDocument> document = aContextNode->OwnerDoc();
    4918           0 :   bool isHTML = document->IsHTMLDocument();
    4919             : #ifdef DEBUG
    4920           0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
    4921           0 :   NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
    4922             : #endif
    4923             : 
    4924           0 :   if (isHTML) {
    4925             :     RefPtr<DocumentFragment> frag =
    4926           0 :       new DocumentFragment(document->NodeInfoManager());
    4927             : 
    4928           0 :     nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
    4929           0 :     if (contextAsContent && !contextAsContent->IsElement()) {
    4930           0 :       contextAsContent = contextAsContent->GetParent();
    4931           0 :       if (contextAsContent && !contextAsContent->IsElement()) {
    4932             :         // can this even happen?
    4933           0 :         contextAsContent = nullptr;
    4934             :       }
    4935             :     }
    4936             : 
    4937           0 :     if (contextAsContent && !contextAsContent->IsHTMLElement(nsGkAtoms::html)) {
    4938           0 :       aRv = ParseFragmentHTML(aFragment, frag,
    4939           0 :                               contextAsContent->NodeInfo()->NameAtom(),
    4940             :                               contextAsContent->GetNameSpaceID(),
    4941           0 :                               (document->GetCompatibilityMode() ==
    4942             :                                eCompatibility_NavQuirks),
    4943           0 :                               aPreventScriptExecution);
    4944             :     } else {
    4945           0 :       aRv = ParseFragmentHTML(aFragment, frag,
    4946             :                               nsGkAtoms::body,
    4947             :                               kNameSpaceID_XHTML,
    4948           0 :                               (document->GetCompatibilityMode() ==
    4949             :                                eCompatibility_NavQuirks),
    4950           0 :                               aPreventScriptExecution);
    4951             :     }
    4952             : 
    4953           0 :     return frag.forget();
    4954             :   }
    4955             : 
    4956           0 :   AutoTArray<nsString, 32> tagStack;
    4957           0 :   nsAutoString uriStr, nameStr;
    4958           0 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
    4959             :   // just in case we have a text node
    4960           0 :   if (content && !content->IsElement())
    4961           0 :     content = content->GetParent();
    4962             : 
    4963           0 :   while (content && content->IsElement()) {
    4964           0 :     nsString& tagName = *tagStack.AppendElement();
    4965           0 :     tagName = content->NodeInfo()->QualifiedName();
    4966             : 
    4967             :     // see if we need to add xmlns declarations
    4968           0 :     uint32_t count = content->GetAttrCount();
    4969           0 :     bool setDefaultNamespace = false;
    4970           0 :     if (count > 0) {
    4971             :       uint32_t index;
    4972             : 
    4973           0 :       for (index = 0; index < count; index++) {
    4974           0 :         const BorrowedAttrInfo info = content->GetAttrInfoAt(index);
    4975           0 :         const nsAttrName* name = info.mName;
    4976           0 :         if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
    4977           0 :           info.mValue->ToString(uriStr);
    4978             : 
    4979             :           // really want something like nsXMLContentSerializer::SerializeAttr
    4980           0 :           tagName.AppendLiteral(" xmlns"); // space important
    4981           0 :           if (name->GetPrefix()) {
    4982           0 :             tagName.Append(char16_t(':'));
    4983           0 :             name->LocalName()->ToString(nameStr);
    4984           0 :             tagName.Append(nameStr);
    4985             :           } else {
    4986           0 :             setDefaultNamespace = true;
    4987             :           }
    4988           0 :           tagName.AppendLiteral(R"(=")");
    4989           0 :           tagName.Append(uriStr);
    4990           0 :           tagName.Append('"');
    4991             :         }
    4992             :       }
    4993             :     }
    4994             : 
    4995           0 :     if (!setDefaultNamespace) {
    4996           0 :       mozilla::dom::NodeInfo* info = content->NodeInfo();
    4997           0 :       if (!info->GetPrefixAtom() &&
    4998           0 :           info->NamespaceID() != kNameSpaceID_None) {
    4999             :         // We have no namespace prefix, but have a namespace ID.  Push
    5000             :         // default namespace attr in, so that our kids will be in our
    5001             :         // namespace.
    5002           0 :         info->GetNamespaceURI(uriStr);
    5003           0 :         tagName.AppendLiteral(R"( xmlns=")");
    5004           0 :         tagName.Append(uriStr);
    5005           0 :         tagName.Append('"');
    5006             :       }
    5007             :     }
    5008             : 
    5009           0 :     content = content->GetParent();
    5010             :   }
    5011             : 
    5012           0 :   nsCOMPtr<nsIDOMDocumentFragment> frag;
    5013           0 :   aRv = ParseFragmentXML(aFragment, document, tagStack,
    5014           0 :                          aPreventScriptExecution, getter_AddRefs(frag));
    5015           0 :   return frag.forget().downcast<DocumentFragment>();
    5016             : }
    5017             : 
    5018             : /* static */
    5019             : void
    5020           0 : nsContentUtils::DropFragmentParsers()
    5021             : {
    5022           0 :   NS_IF_RELEASE(sHTMLFragmentParser);
    5023           0 :   NS_IF_RELEASE(sXMLFragmentParser);
    5024           0 :   NS_IF_RELEASE(sXMLFragmentSink);
    5025           0 : }
    5026             : 
    5027             : /* static */
    5028             : void
    5029           0 : nsContentUtils::XPCOMShutdown()
    5030             : {
    5031           0 :   nsContentUtils::DropFragmentParsers();
    5032           0 : }
    5033             : 
    5034             : /* static */
    5035             : nsresult
    5036           0 : nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
    5037             :                                   nsIContent* aTargetNode,
    5038             :                                   nsIAtom* aContextLocalName,
    5039             :                                   int32_t aContextNamespace,
    5040             :                                   bool aQuirks,
    5041             :                                   bool aPreventScriptExecution)
    5042             : {
    5043           0 :   AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
    5044             : 
    5045           0 :   if (nsContentUtils::sFragmentParsingActive) {
    5046           0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    5047           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    5048             :   }
    5049           0 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    5050           0 :   nsContentUtils::sFragmentParsingActive = true;
    5051           0 :   if (!sHTMLFragmentParser) {
    5052           0 :     NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
    5053             :     // Now sHTMLFragmentParser owns the object
    5054             :   }
    5055             :   nsresult rv =
    5056           0 :     sHTMLFragmentParser->ParseFragment(aSourceBuffer,
    5057             :                                        aTargetNode,
    5058             :                                        aContextLocalName,
    5059             :                                        aContextNamespace,
    5060             :                                        aQuirks,
    5061           0 :                                        aPreventScriptExecution);
    5062           0 :   return rv;
    5063             : }
    5064             : 
    5065             : /* static */
    5066             : nsresult
    5067           0 : nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
    5068             :                                   nsIDocument* aTargetDocument,
    5069             :                                   bool aScriptingEnabledForNoscriptParsing)
    5070             : {
    5071           0 :   AutoTimelineMarker m(aTargetDocument->GetDocShell(), "Parse HTML");
    5072             : 
    5073           0 :   if (nsContentUtils::sFragmentParsingActive) {
    5074           0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    5075           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    5076             :   }
    5077           0 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    5078           0 :   nsContentUtils::sFragmentParsingActive = true;
    5079           0 :   if (!sHTMLFragmentParser) {
    5080           0 :     NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
    5081             :     // Now sHTMLFragmentParser owns the object
    5082             :   }
    5083             :   nsresult rv =
    5084           0 :     sHTMLFragmentParser->ParseDocument(aSourceBuffer,
    5085             :                                        aTargetDocument,
    5086           0 :                                        aScriptingEnabledForNoscriptParsing);
    5087           0 :   return rv;
    5088             : }
    5089             : 
    5090             : /* static */
    5091             : nsresult
    5092           0 : nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
    5093             :                                  nsIDocument* aDocument,
    5094             :                                  nsTArray<nsString>& aTagStack,
    5095             :                                  bool aPreventScriptExecution,
    5096             :                                  nsIDOMDocumentFragment** aReturn)
    5097             : {
    5098           0 :   AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
    5099             : 
    5100           0 :   if (nsContentUtils::sFragmentParsingActive) {
    5101           0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    5102           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    5103             :   }
    5104           0 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    5105           0 :   nsContentUtils::sFragmentParsingActive = true;
    5106           0 :   if (!sXMLFragmentParser) {
    5107           0 :     nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID);
    5108           0 :     parser.forget(&sXMLFragmentParser);
    5109             :     // sXMLFragmentParser now owns the parser
    5110             :   }
    5111           0 :   if (!sXMLFragmentSink) {
    5112           0 :     NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
    5113             :     // sXMLFragmentSink now owns the sink
    5114             :   }
    5115           0 :   nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
    5116           0 :   MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!");
    5117           0 :   sXMLFragmentParser->SetContentSink(contentsink);
    5118             : 
    5119           0 :   sXMLFragmentSink->SetTargetDocument(aDocument);
    5120           0 :   sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
    5121             : 
    5122             :   nsresult rv =
    5123           0 :     sXMLFragmentParser->ParseFragment(aSourceBuffer,
    5124           0 :                                       aTagStack);
    5125           0 :   if (NS_FAILED(rv)) {
    5126             :     // Drop the fragment parser and sink that might be in an inconsistent state
    5127           0 :     NS_IF_RELEASE(sXMLFragmentParser);
    5128           0 :     NS_IF_RELEASE(sXMLFragmentSink);
    5129           0 :     return rv;
    5130             :   }
    5131             : 
    5132           0 :   rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
    5133             : 
    5134           0 :   sXMLFragmentParser->Reset();
    5135             : 
    5136           0 :   return rv;
    5137             : }
    5138             : 
    5139             : /* static */
    5140             : nsresult
    5141           0 : nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
    5142             :                                    nsAString& aResultBuffer,
    5143             :                                    uint32_t aFlags,
    5144             :                                    uint32_t aWrapCol)
    5145             : {
    5146           0 :   nsCOMPtr<nsIURI> uri;
    5147           0 :   NS_NewURI(getter_AddRefs(uri), "about:blank");
    5148           0 :   nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
    5149           0 :   nsCOMPtr<nsIDOMDocument> domDocument;
    5150           0 :   nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
    5151           0 :                                   EmptyString(),
    5152           0 :                                   EmptyString(),
    5153             :                                   nullptr,
    5154             :                                   uri,
    5155             :                                   uri,
    5156             :                                   principal,
    5157             :                                   true,
    5158             :                                   nullptr,
    5159           0 :                                   DocumentFlavorHTML);
    5160           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5161             : 
    5162           0 :   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
    5163           0 :   rv = nsContentUtils::ParseDocumentHTML(aSourceBuffer, document,
    5164           0 :     !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
    5165           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5166             : 
    5167           0 :   nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(
    5168           0 :     "@mozilla.org/layout/documentEncoder;1?type=text/plain");
    5169             : 
    5170           0 :   rv = encoder->Init(domDocument, NS_LITERAL_STRING("text/plain"), aFlags);
    5171           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5172             : 
    5173           0 :   encoder->SetWrapColumn(aWrapCol);
    5174             : 
    5175           0 :   return encoder->EncodeToString(aResultBuffer);
    5176             : }
    5177             : 
    5178             : /* static */
    5179             : nsresult
    5180           2 : nsContentUtils::SetNodeTextContent(nsIContent* aContent,
    5181             :                                    const nsAString& aValue,
    5182             :                                    bool aTryReuse)
    5183             : {
    5184             :   // Fire DOMNodeRemoved mutation events before we do anything else.
    5185           4 :   nsCOMPtr<nsIContent> owningContent;
    5186             : 
    5187             :   // Batch possible DOMSubtreeModified events.
    5188           4 :   mozAutoSubtreeModified subtree(nullptr, nullptr);
    5189             : 
    5190             :   // Scope firing mutation events so that we don't carry any state that
    5191             :   // might be stale
    5192             :   {
    5193             :     // We're relying on mozAutoSubtreeModified to keep a strong reference if
    5194             :     // needed.
    5195           2 :     nsIDocument* doc = aContent->OwnerDoc();
    5196             : 
    5197             :     // Optimize the common case of there being no observers
    5198           2 :     if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
    5199           0 :       subtree.UpdateTarget(doc, nullptr);
    5200           0 :       owningContent = aContent;
    5201           0 :       nsCOMPtr<nsINode> child;
    5202           0 :       bool skipFirst = aTryReuse;
    5203           0 :       for (child = aContent->GetFirstChild();
    5204           0 :            child && child->GetParentNode() == aContent;
    5205           0 :            child = child->GetNextSibling()) {
    5206           0 :         if (skipFirst && child->IsNodeOfType(nsINode::eTEXT)) {
    5207           0 :           skipFirst = false;
    5208           0 :           continue;
    5209             :         }
    5210           0 :         nsContentUtils::MaybeFireNodeRemoved(child, aContent, doc);
    5211             :       }
    5212             :     }
    5213             :   }
    5214             : 
    5215             :   // Might as well stick a batch around this since we're performing several
    5216             :   // mutations.
    5217             :   mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(),
    5218           4 :     UPDATE_CONTENT_MODEL, true);
    5219           4 :   nsAutoMutationBatch mb;
    5220             : 
    5221           2 :   uint32_t childCount = aContent->GetChildCount();
    5222             : 
    5223           2 :   if (aTryReuse && !aValue.IsEmpty()) {
    5224           0 :     uint32_t removeIndex = 0;
    5225             : 
    5226           0 :     for (uint32_t i = 0; i < childCount; ++i) {
    5227           0 :       nsIContent* child = aContent->GetChildAt(removeIndex);
    5228           0 :       if (removeIndex == 0 && child && child->IsNodeOfType(nsINode::eTEXT)) {
    5229           0 :         nsresult rv = child->SetText(aValue, true);
    5230           0 :         NS_ENSURE_SUCCESS(rv, rv);
    5231             : 
    5232           0 :         removeIndex = 1;
    5233             :       }
    5234             :       else {
    5235           0 :         aContent->RemoveChildAt(removeIndex, true);
    5236             :       }
    5237             :     }
    5238             : 
    5239           0 :     if (removeIndex == 1) {
    5240           0 :       return NS_OK;
    5241             :     }
    5242             :   }
    5243             :   else {
    5244           2 :     mb.Init(aContent, true, false);
    5245           4 :     for (uint32_t i = 0; i < childCount; ++i) {
    5246           2 :       aContent->RemoveChildAt(0, true);
    5247             :     }
    5248             :   }
    5249           2 :   mb.RemovalDone();
    5250             : 
    5251           2 :   if (aValue.IsEmpty()) {
    5252           0 :     return NS_OK;
    5253             :   }
    5254             : 
    5255             :   RefPtr<nsTextNode> textContent =
    5256           6 :     new nsTextNode(aContent->NodeInfo()->NodeInfoManager());
    5257             : 
    5258           2 :   textContent->SetText(aValue, true);
    5259             : 
    5260           2 :   nsresult rv = aContent->AppendChildTo(textContent, true);
    5261           2 :   mb.NodesAdded();
    5262           2 :   return rv;
    5263             : }
    5264             : 
    5265             : static bool
    5266           2 : AppendNodeTextContentsRecurse(nsINode* aNode, nsAString& aResult,
    5267             :                               const fallible_t& aFallible)
    5268             : {
    5269           3 :   for (nsIContent* child = aNode->GetFirstChild();
    5270           3 :        child;
    5271           1 :        child = child->GetNextSibling()) {
    5272           1 :     if (child->IsElement()) {
    5273             :       bool ok = AppendNodeTextContentsRecurse(child, aResult,
    5274           0 :                                               aFallible);
    5275           0 :       if (!ok) {
    5276           0 :         return false;
    5277             :       }
    5278             :     }
    5279           1 :     else if (child->IsNodeOfType(nsINode::eTEXT)) {
    5280           1 :       bool ok = child->AppendTextTo(aResult, aFallible);
    5281           1 :       if (!ok) {
    5282           0 :         return false;
    5283             :       }
    5284             :     }
    5285             :   }
    5286             : 
    5287           2 :   return true;
    5288             : }
    5289             : 
    5290             : /* static */
    5291             : bool
    5292           9 : nsContentUtils::AppendNodeTextContent(nsINode* aNode, bool aDeep,
    5293             :                                       nsAString& aResult,
    5294             :                                       const fallible_t& aFallible)
    5295             : {
    5296           9 :   if (aNode->IsNodeOfType(nsINode::eTEXT)) {
    5297             :     return static_cast<nsIContent*>(aNode)->AppendTextTo(aResult,
    5298           0 :                                                          aFallible);
    5299             :   }
    5300           9 :   if (aDeep) {
    5301           2 :     return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
    5302             :   }
    5303             : 
    5304          13 :   for (nsIContent* child = aNode->GetFirstChild();
    5305          13 :        child;
    5306           6 :        child = child->GetNextSibling()) {
    5307           6 :     if (child->IsNodeOfType(nsINode::eTEXT)) {
    5308           6 :       bool ok = child->AppendTextTo(aResult, fallible);
    5309           6 :       if (!ok) {
    5310           0 :         return false;
    5311             :       }
    5312             :     }
    5313             :   }
    5314           7 :   return true;
    5315             : }
    5316             : 
    5317             : bool
    5318           1 : nsContentUtils::HasNonEmptyTextContent(nsINode* aNode,
    5319             :                                        TextContentDiscoverMode aDiscoverMode)
    5320             : {
    5321           1 :   for (nsIContent* child = aNode->GetFirstChild();
    5322           1 :        child;
    5323           0 :        child = child->GetNextSibling()) {
    5324           2 :     if (child->IsNodeOfType(nsINode::eTEXT) &&
    5325           1 :         child->TextLength() > 0) {
    5326           1 :         return true;
    5327             :     }
    5328             : 
    5329           0 :     if (aDiscoverMode == eRecurseIntoChildren &&
    5330           0 :         HasNonEmptyTextContent(child, aDiscoverMode)) {
    5331           0 :       return true;
    5332             :     }
    5333             :   }
    5334             : 
    5335           0 :   return false;
    5336             : }
    5337             : 
    5338             : /* static */
    5339             : bool
    5340          14 : nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
    5341             :                                       const nsIContent* aContent)
    5342             : {
    5343          14 :   NS_PRECONDITION(aNode,
    5344             :                   "Must have a node to work with");
    5345          14 :   NS_PRECONDITION(aContent,
    5346             :                   "Must have a content to work with");
    5347             : 
    5348          14 :   if (!aNode->IsNodeOfType(nsINode::eCONTENT)) {
    5349             :     /**
    5350             :      * The root isn't an nsIContent, so it's a document or attribute.  The only
    5351             :      * nodes in the same anonymous subtree as it will have a null
    5352             :      * bindingParent.
    5353             :      *
    5354             :      * XXXbz strictly speaking, that's not true for attribute nodes.
    5355             :      */
    5356           0 :     return aContent->GetBindingParent() == nullptr;
    5357             :   }
    5358             : 
    5359          14 :   const nsIContent* nodeAsContent = static_cast<const nsIContent*>(aNode);
    5360             : 
    5361             :   // For nodes in a shadow tree, it is insufficient to simply compare
    5362             :   // the binding parent because a node may host multiple ShadowRoots,
    5363             :   // thus nodes in different shadow tree may have the same binding parent.
    5364          14 :   if (aNode->IsInShadowTree()) {
    5365           0 :     return nodeAsContent->GetContainingShadow() ==
    5366           0 :       aContent->GetContainingShadow();
    5367             :   }
    5368             : 
    5369          14 :   return nodeAsContent->GetBindingParent() == aContent->GetBindingParent();
    5370             : }
    5371             : 
    5372          12 : class AnonymousContentDestroyer : public Runnable {
    5373             : public:
    5374           0 :   explicit AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent)
    5375           0 :     : mozilla::Runnable("AnonymousContentDestroyer")
    5376             :   {
    5377           0 :     mContent.swap(*aContent);
    5378           0 :     mParent = mContent->GetParent();
    5379           0 :     mDoc = mContent->OwnerDoc();
    5380           0 :   }
    5381           4 :   explicit AnonymousContentDestroyer(nsCOMPtr<Element>* aElement)
    5382           4 :     : mozilla::Runnable("AnonymousContentDestroyer")
    5383             :   {
    5384           4 :     mContent = aElement->forget();
    5385           4 :     mParent = mContent->GetParent();
    5386           4 :     mDoc = mContent->OwnerDoc();
    5387           4 :   }
    5388           4 :   NS_IMETHOD Run() override {
    5389           4 :     mContent->UnbindFromTree();
    5390           4 :     return NS_OK;
    5391             :   }
    5392             : private:
    5393             :   nsCOMPtr<nsIContent> mContent;
    5394             :   // Hold strong refs to the parent content and document so that they
    5395             :   // don't die unexpectedly
    5396             :   nsCOMPtr<nsIDocument> mDoc;
    5397             :   nsCOMPtr<nsIContent> mParent;
    5398             : };
    5399             : 
    5400             : /* static */
    5401             : void
    5402          28 : nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
    5403             : {
    5404          28 :   if (*aContent) {
    5405           0 :     AddScriptRunner(new AnonymousContentDestroyer(aContent));
    5406             :   }
    5407          28 : }
    5408             : 
    5409             : /* static */
    5410             : void
    5411           6 : nsContentUtils::DestroyAnonymousContent(nsCOMPtr<Element>* aElement)
    5412             : {
    5413           6 :   if (*aElement) {
    5414           4 :     AddScriptRunner(new AnonymousContentDestroyer(aElement));
    5415             :   }
    5416           6 : }
    5417             : 
    5418             : /* static */
    5419             : void
    5420           0 : nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
    5421             : {
    5422           0 :   IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
    5423           0 : }
    5424             : 
    5425           0 : static bool SchemeIs(nsIURI* aURI, const char* aScheme)
    5426             : {
    5427           0 :   nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
    5428           0 :   NS_ENSURE_TRUE(baseURI, false);
    5429             : 
    5430           0 :   bool isScheme = false;
    5431           0 :   return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
    5432             : }
    5433             : 
    5434             : bool
    5435        2284 : nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
    5436             : {
    5437        2284 :   MOZ_ASSERT(IsInitialized());
    5438        2284 :   return aPrincipal == sSystemPrincipal;
    5439             : }
    5440             : 
    5441             : bool
    5442         230 : nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal)
    5443             : {
    5444         460 :   nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
    5445         460 :   return !!ep;
    5446             : }
    5447             : 
    5448             : nsIPrincipal*
    5449        1654 : nsContentUtils::GetSystemPrincipal()
    5450             : {
    5451        1654 :   MOZ_ASSERT(IsInitialized());
    5452        1654 :   return sSystemPrincipal;
    5453             : }
    5454             : 
    5455             : bool
    5456           0 : nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrincipal,
    5457             :                                           nsIPrincipal* aExtraPrincipal)
    5458             : {
    5459           0 :   if (!aExtraPrincipal) {
    5460           0 :     return false;
    5461             :   }
    5462           0 :   if (!*aResourcePrincipal) {
    5463           0 :     *aResourcePrincipal = aExtraPrincipal;
    5464           0 :     return true;
    5465             :   }
    5466           0 :   if (*aResourcePrincipal == aExtraPrincipal) {
    5467           0 :     return false;
    5468             :   }
    5469             :   bool subsumes;
    5470           0 :   if (NS_SUCCEEDED((*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes)) &&
    5471             :       subsumes) {
    5472           0 :     return false;
    5473             :   }
    5474           0 :   *aResourcePrincipal = sSystemPrincipal;
    5475           0 :   return true;
    5476             : }
    5477             : 
    5478             : /* static */
    5479             : void
    5480           0 : nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
    5481             :                             nsIURI *aLinkURI, const nsString &aTargetSpec,
    5482             :                             bool aClick, bool aIsUserTriggered,
    5483             :                             bool aIsTrusted)
    5484             : {
    5485           0 :   NS_ASSERTION(aPresContext, "Need a nsPresContext");
    5486           0 :   NS_PRECONDITION(aLinkURI, "No link URI");
    5487             : 
    5488           0 :   if (aContent->IsEditable()) {
    5489           0 :     return;
    5490             :   }
    5491             : 
    5492           0 :   nsILinkHandler *handler = aPresContext->GetLinkHandler();
    5493           0 :   if (!handler) {
    5494           0 :     return;
    5495             :   }
    5496             : 
    5497           0 :   if (!aClick) {
    5498           0 :     handler->OnOverLink(aContent, aLinkURI, aTargetSpec.get());
    5499           0 :     return;
    5500             :   }
    5501             : 
    5502             :   // Check that this page is allowed to load this URI.
    5503           0 :   nsresult proceed = NS_OK;
    5504             : 
    5505           0 :   if (sSecurityManager) {
    5506             :     uint32_t flag =
    5507           0 :       aIsUserTriggered ?
    5508             :       (uint32_t)nsIScriptSecurityManager::STANDARD :
    5509           0 :       (uint32_t)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT;
    5510             :     proceed =
    5511           0 :       sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(),
    5512           0 :                                                   aLinkURI, flag);
    5513             :   }
    5514             : 
    5515             :   // Only pass off the click event if the script security manager says it's ok.
    5516             :   // We need to rest aTargetSpec for forced downloads.
    5517           0 :   if (NS_SUCCEEDED(proceed)) {
    5518             : 
    5519             :     // A link/area element with a download attribute is allowed to set
    5520             :     // a pseudo Content-Disposition header.
    5521             :     // For security reasons we only allow websites to declare same-origin resources
    5522             :     // as downloadable. If this check fails we will just do the normal thing
    5523             :     // (i.e. navigate to the resource).
    5524           0 :     nsAutoString fileName;
    5525           0 :     if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
    5526           0 :          !aContent->IsHTMLElement(nsGkAtoms::area) &&
    5527           0 :          !aContent->IsSVGElement(nsGkAtoms::a)) ||
    5528           0 :         !aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::download, fileName) ||
    5529           0 :         NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, false, true))) {
    5530           0 :       fileName.SetIsVoid(true); // No actionable download attribute was found.
    5531             :     }
    5532             : 
    5533           0 :     handler->OnLinkClick(aContent, aLinkURI,
    5534           0 :                          fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
    5535           0 :                          fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
    5536             :   }
    5537             : }
    5538             : 
    5539             : /* static */
    5540             : void
    5541           0 : nsContentUtils::GetLinkLocation(Element* aElement, nsString& aLocationString)
    5542             : {
    5543           0 :   nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
    5544           0 :   if (hrefURI) {
    5545           0 :     nsAutoCString specUTF8;
    5546           0 :     nsresult rv = hrefURI->GetSpec(specUTF8);
    5547           0 :     if (NS_SUCCEEDED(rv))
    5548           0 :       CopyUTF8toUTF16(specUTF8, aLocationString);
    5549             :   }
    5550           0 : }
    5551             : 
    5552             : /* static */
    5553             : nsIWidget*
    5554           4 : nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)
    5555             : {
    5556           4 :   if (!aWidget)
    5557           0 :     return nullptr;
    5558             : 
    5559           4 :   return aWidget->GetTopLevelWidget();
    5560             : }
    5561             : 
    5562             : /* static */
    5563             : const nsDependentString
    5564           1 : nsContentUtils::GetLocalizedEllipsis()
    5565             : {
    5566             :   static char16_t sBuf[4] = { 0, 0, 0, 0 };
    5567           1 :   if (!sBuf[0]) {
    5568           2 :     nsAdoptingString tmp = Preferences::GetLocalizedString("intl.ellipsis");
    5569           2 :     uint32_t len = std::min(uint32_t(tmp.Length()),
    5570           3 :                           uint32_t(ArrayLength(sBuf) - 1));
    5571           1 :     CopyUnicodeTo(tmp, 0, sBuf, len);
    5572           1 :     if (!sBuf[0])
    5573           0 :       sBuf[0] = char16_t(0x2026);
    5574             :   }
    5575           1 :   return nsDependentString(sBuf);
    5576             : }
    5577             : 
    5578             : /* static */
    5579             : void
    5580       10839 : nsContentUtils::AddScriptBlocker()
    5581             : {
    5582       10839 :   MOZ_ASSERT(NS_IsMainThread());
    5583       10839 :   if (!sScriptBlockerCount) {
    5584        5381 :     MOZ_ASSERT(sRunnersCountAtFirstBlocker == 0,
    5585             :                "Should not already have a count");
    5586        5381 :     sRunnersCountAtFirstBlocker = sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
    5587             :   }
    5588       10839 :   ++sScriptBlockerCount;
    5589       10839 : }
    5590             : 
    5591             : #ifdef DEBUG
    5592             : static bool sRemovingScriptBlockers = false;
    5593             : #endif
    5594             : 
    5595             : /* static */
    5596             : void
    5597       10839 : nsContentUtils::RemoveScriptBlocker()
    5598             : {
    5599       10839 :   MOZ_ASSERT(NS_IsMainThread());
    5600       10839 :   MOZ_ASSERT(!sRemovingScriptBlockers);
    5601       10839 :   NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers");
    5602       10839 :   --sScriptBlockerCount;
    5603       10839 :   if (sScriptBlockerCount) {
    5604       10916 :     return;
    5605             :   }
    5606             : 
    5607        5381 :   if (!sBlockedScriptRunners) {
    5608           0 :     return;
    5609             :   }
    5610             : 
    5611        5381 :   uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
    5612        5381 :   uint32_t lastBlocker = sBlockedScriptRunners->Length();
    5613        5381 :   uint32_t originalFirstBlocker = firstBlocker;
    5614        5381 :   uint32_t blockersCount = lastBlocker - firstBlocker;
    5615        5381 :   sRunnersCountAtFirstBlocker = 0;
    5616        5381 :   NS_ASSERTION(firstBlocker <= lastBlocker,
    5617             :                "bad sRunnersCountAtFirstBlocker");
    5618             : 
    5619        5799 :   while (firstBlocker < lastBlocker) {
    5620         418 :     nsCOMPtr<nsIRunnable> runnable;
    5621         209 :     runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
    5622         209 :     ++firstBlocker;
    5623             : 
    5624             :     // Calling the runnable can reenter us
    5625         209 :     runnable->Run();
    5626             :     // So can dropping the reference to the runnable
    5627         209 :     runnable = nullptr;
    5628             : 
    5629         209 :     NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
    5630             :                  "Bad count");
    5631         209 :     NS_ASSERTION(!sScriptBlockerCount, "This is really bad");
    5632             :   }
    5633             : #ifdef DEBUG
    5634       10762 :   AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
    5635        5381 :   sRemovingScriptBlockers = true;
    5636             : #endif
    5637        5381 :   sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
    5638             : }
    5639             : 
    5640             : /* static */
    5641             : nsIWindowProvider*
    5642           0 : nsContentUtils::GetWindowProviderForContentProcess()
    5643             : {
    5644           0 :   MOZ_ASSERT(XRE_IsContentProcess());
    5645           0 :   return ContentChild::GetSingleton();
    5646             : }
    5647             : 
    5648             : /* static */
    5649             : already_AddRefed<nsPIDOMWindowOuter>
    5650           0 : nsContentUtils::GetMostRecentNonPBWindow()
    5651             : {
    5652             :   nsCOMPtr<nsIWindowMediator> windowMediator =
    5653           0 :     do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
    5654           0 :   nsCOMPtr<nsIWindowMediator_44> wm = do_QueryInterface(windowMediator);
    5655             : 
    5656           0 :   nsCOMPtr<mozIDOMWindowProxy> window;
    5657           0 :   wm->GetMostRecentNonPBWindow(u"navigator:browser",
    5658           0 :                                getter_AddRefs(window));
    5659           0 :   nsCOMPtr<nsPIDOMWindowOuter> pwindow;
    5660           0 :   pwindow = do_QueryInterface(window);
    5661             : 
    5662           0 :   return pwindow.forget();
    5663             : }
    5664             : 
    5665             : /* static */
    5666             : void
    5667           0 : nsContentUtils::WarnScriptWasIgnored(nsIDocument* aDocument)
    5668             : {
    5669           0 :   nsAutoString msg;
    5670           0 :   if (aDocument) {
    5671           0 :     nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
    5672           0 :     if (uri) {
    5673           0 :       msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
    5674           0 :       msg.AppendLiteral(" : ");
    5675             :     }
    5676             :   }
    5677           0 :   msg.AppendLiteral("Unable to run script because scripts are blocked internally.");
    5678             : 
    5679           0 :   LogSimpleConsoleError(msg, "DOM");
    5680           0 : }
    5681             : 
    5682             : /* static */
    5683             : void
    5684         302 : nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable)
    5685             : {
    5686         395 :   nsCOMPtr<nsIRunnable> runnable = aRunnable;
    5687         302 :   if (!runnable) {
    5688           0 :     return;
    5689             :   }
    5690             : 
    5691         302 :   if (sScriptBlockerCount) {
    5692         209 :     sBlockedScriptRunners->AppendElement(runnable.forget());
    5693         209 :     return;
    5694             :   }
    5695             : 
    5696          93 :   runnable->Run();
    5697             : }
    5698             : 
    5699             : /* static */
    5700             : void
    5701         262 : nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
    5702         524 :   nsCOMPtr<nsIRunnable> runnable = aRunnable;
    5703         262 :   AddScriptRunner(runnable.forget());
    5704         262 : }
    5705             : 
    5706             : /* static */
    5707             : void
    5708           0 : nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable)
    5709             : {
    5710           0 :   MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
    5711           0 :   CycleCollectedJSContext::Get()->RunInStableState(Move(aRunnable));
    5712           0 : }
    5713             : 
    5714             : /* static */
    5715             : void
    5716           0 : nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
    5717             : {
    5718           0 :   MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
    5719           0 :   CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
    5720           0 : }
    5721             : 
    5722             : /* static */
    5723             : nsISerialEventTarget*
    5724           0 : nsContentUtils::GetStableStateEventTarget()
    5725             : {
    5726           0 :   return sStableStateEventTarget;
    5727             : }
    5728             : 
    5729             : void
    5730         656 : nsContentUtils::EnterMicroTask()
    5731             : {
    5732         656 :   MOZ_ASSERT(NS_IsMainThread());
    5733         656 :   ++sMicroTaskLevel;
    5734         656 : }
    5735             : 
    5736             : void
    5737         656 : nsContentUtils::LeaveMicroTask()
    5738             : {
    5739         656 :   MOZ_ASSERT(NS_IsMainThread());
    5740         656 :   if (--sMicroTaskLevel == 0) {
    5741         506 :     PerformMainThreadMicroTaskCheckpoint();
    5742             :   }
    5743         656 : }
    5744             : 
    5745             : bool
    5746         117 : nsContentUtils::IsInMicroTask()
    5747             : {
    5748         117 :   MOZ_ASSERT(NS_IsMainThread());
    5749         117 :   return sMicroTaskLevel != 0;
    5750             : }
    5751             : 
    5752             : uint32_t
    5753           0 : nsContentUtils::MicroTaskLevel()
    5754             : {
    5755           0 :   MOZ_ASSERT(NS_IsMainThread());
    5756           0 :   return sMicroTaskLevel;
    5757             : }
    5758             : 
    5759             : void
    5760           0 : nsContentUtils::SetMicroTaskLevel(uint32_t aLevel)
    5761             : {
    5762           0 :   MOZ_ASSERT(NS_IsMainThread());
    5763           0 :   sMicroTaskLevel = aLevel;
    5764           0 : }
    5765             : 
    5766             : void
    5767        1733 : nsContentUtils::PerformMainThreadMicroTaskCheckpoint()
    5768             : {
    5769        1733 :   MOZ_ASSERT(NS_IsMainThread());
    5770             : 
    5771        1733 :   nsDOMMutationObserver::HandleMutations();
    5772        1733 : }
    5773             : 
    5774             : /*
    5775             :  * Helper function for nsContentUtils::ProcessViewportInfo.
    5776             :  *
    5777             :  * Handles a single key=value pair. If it corresponds to a valid viewport
    5778             :  * attribute, add it to the document header data. No validation is done on the
    5779             :  * value itself (this is done at display time).
    5780             :  */
    5781           0 : static void ProcessViewportToken(nsIDocument *aDocument,
    5782             :                                  const nsAString &token) {
    5783             : 
    5784             :   /* Iterators. */
    5785           0 :   nsAString::const_iterator tip, tail, end;
    5786           0 :   token.BeginReading(tip);
    5787           0 :   tail = tip;
    5788           0 :   token.EndReading(end);
    5789             : 
    5790             :   /* Move tip to the '='. */
    5791           0 :   while ((tip != end) && (*tip != '='))
    5792           0 :     ++tip;
    5793             : 
    5794             :   /* If we didn't find an '=', punt. */
    5795           0 :   if (tip == end)
    5796           0 :     return;
    5797             : 
    5798             :   /* Extract the key and value. */
    5799             :   const nsAString &key =
    5800           0 :     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
    5801           0 :                                                         true);
    5802             :   const nsAString &value =
    5803           0 :     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
    5804           0 :                                                         true);
    5805             : 
    5806             :   /* Check for known keys. If we find a match, insert the appropriate
    5807             :    * information into the document header. */
    5808           0 :   nsCOMPtr<nsIAtom> key_atom = NS_Atomize(key);
    5809           0 :   if (key_atom == nsGkAtoms::height)
    5810           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_height, value);
    5811           0 :   else if (key_atom == nsGkAtoms::width)
    5812           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_width, value);
    5813           0 :   else if (key_atom == nsGkAtoms::initial_scale)
    5814           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_initial_scale, value);
    5815           0 :   else if (key_atom == nsGkAtoms::minimum_scale)
    5816           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_minimum_scale, value);
    5817           0 :   else if (key_atom == nsGkAtoms::maximum_scale)
    5818           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_maximum_scale, value);
    5819           0 :   else if (key_atom == nsGkAtoms::user_scalable)
    5820           0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
    5821             : }
    5822             : 
    5823             : #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
    5824             :                          (c == '\t') || (c == '\n') || (c == '\r'))
    5825             : 
    5826             : /* static */
    5827             : nsresult
    5828           0 : nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
    5829             :                                     const nsAString &viewportInfo) {
    5830             : 
    5831             :   /* We never fail. */
    5832           0 :   nsresult rv = NS_OK;
    5833             : 
    5834           0 :   aDocument->SetHeaderData(nsGkAtoms::viewport, viewportInfo);
    5835             : 
    5836             :   /* Iterators. */
    5837           0 :   nsAString::const_iterator tip, tail, end;
    5838           0 :   viewportInfo.BeginReading(tip);
    5839           0 :   tail = tip;
    5840           0 :   viewportInfo.EndReading(end);
    5841             : 
    5842             :   /* Read the tip to the first non-separator character. */
    5843           0 :   while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5844           0 :     ++tip;
    5845             : 
    5846             :   /* Read through and find tokens separated by separators. */
    5847           0 :   while (tip != end) {
    5848             : 
    5849             :     /* Synchronize tip and tail. */
    5850           0 :     tail = tip;
    5851             : 
    5852             :     /* Advance tip past non-separator characters. */
    5853           0 :     while ((tip != end) && !IS_SEPARATOR(*tip))
    5854           0 :       ++tip;
    5855             : 
    5856             :     /* Allow white spaces that surround the '=' character */
    5857           0 :     if ((tip != end) && (*tip == '=')) {
    5858           0 :       ++tip;
    5859             : 
    5860           0 :       while ((tip != end) && nsCRT::IsAsciiSpace(*tip))
    5861           0 :         ++tip;
    5862             : 
    5863           0 :       while ((tip != end) && !(IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5864           0 :         ++tip;
    5865             :     }
    5866             : 
    5867             :     /* Our token consists of the characters between tail and tip. */
    5868           0 :     ProcessViewportToken(aDocument, Substring(tail, tip));
    5869             : 
    5870             :     /* Skip separators. */
    5871           0 :     while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5872           0 :       ++tip;
    5873             :   }
    5874             : 
    5875           0 :   return rv;
    5876             : 
    5877             : }
    5878             : 
    5879             : #undef IS_SEPARATOR
    5880             : 
    5881             : /* static */
    5882             : void
    5883           4 : nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
    5884             : {
    5885             : #ifdef MOZ_XUL
    5886           4 :   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    5887           4 :   if (pm && aDocument) {
    5888           8 :     nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
    5889           4 :     if (docShellToHide)
    5890           4 :       pm->HidePopupsInDocShell(docShellToHide);
    5891             :   }
    5892             : #endif
    5893           4 : }
    5894             : 
    5895             : /* static */
    5896             : already_AddRefed<nsIDragSession>
    5897           1 : nsContentUtils::GetDragSession()
    5898             : {
    5899           2 :   nsCOMPtr<nsIDragSession> dragSession;
    5900             :   nsCOMPtr<nsIDragService> dragService =
    5901           2 :     do_GetService("@mozilla.org/widget/dragservice;1");
    5902           1 :   if (dragService)
    5903           1 :     dragService->GetCurrentSession(getter_AddRefs(dragSession));
    5904           2 :   return dragSession.forget();
    5905             : }
    5906             : 
    5907             : /* static */
    5908             : nsresult
    5909           0 : nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent)
    5910             : {
    5911           0 :   if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
    5912           0 :     return NS_OK;
    5913             :   }
    5914             : 
    5915             :   // For dragstart events, the data transfer object is
    5916             :   // created before the event fires, so it should already be set. For other
    5917             :   // drag events, get the object from the drag session.
    5918           0 :   NS_ASSERTION(aDragEvent->mMessage != eDragStart,
    5919             :                "draggesture event created without a dataTransfer");
    5920             : 
    5921           0 :   nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
    5922           0 :   NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
    5923             : 
    5924           0 :   nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
    5925           0 :   nsCOMPtr<DataTransfer> initialDataTransfer;
    5926           0 :   dragSession->GetDataTransfer(getter_AddRefs(dataTransfer));
    5927           0 :   if (dataTransfer) {
    5928           0 :     initialDataTransfer = do_QueryInterface(dataTransfer);
    5929           0 :     if (!initialDataTransfer) {
    5930           0 :       return NS_ERROR_FAILURE;
    5931             :     }
    5932             :   } else {
    5933             :     // A dataTransfer won't exist when a drag was started by some other
    5934             :     // means, for instance calling the drag service directly, or a drag
    5935             :     // from another application. In either case, a new dataTransfer should
    5936             :     // be created that reflects the data.
    5937             :     initialDataTransfer =
    5938           0 :       new DataTransfer(aDragEvent->mTarget, aDragEvent->mMessage, true, -1);
    5939             : 
    5940             :     // now set it in the drag session so we don't need to create it again
    5941           0 :     dragSession->SetDataTransfer(initialDataTransfer);
    5942             :   }
    5943             : 
    5944           0 :   bool isCrossDomainSubFrameDrop = false;
    5945           0 :   if (aDragEvent->mMessage == eDrop) {
    5946           0 :     isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
    5947             :   }
    5948             : 
    5949             :   // each event should use a clone of the original dataTransfer.
    5950           0 :   initialDataTransfer->Clone(aDragEvent->mTarget, aDragEvent->mMessage,
    5951           0 :                              aDragEvent->mUserCancelled,
    5952             :                              isCrossDomainSubFrameDrop,
    5953           0 :                              getter_AddRefs(aDragEvent->mDataTransfer));
    5954           0 :   if (NS_WARN_IF(!aDragEvent->mDataTransfer)) {
    5955           0 :     return NS_ERROR_OUT_OF_MEMORY;
    5956             :   }
    5957             : 
    5958             :   // for the dragenter and dragover events, initialize the drop effect
    5959             :   // from the drop action, which platform specific widget code sets before
    5960             :   // the event is fired based on the keyboard state.
    5961           0 :   if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
    5962             :     uint32_t action, effectAllowed;
    5963           0 :     dragSession->GetDragAction(&action);
    5964           0 :     aDragEvent->mDataTransfer->GetEffectAllowedInt(&effectAllowed);
    5965           0 :     aDragEvent->mDataTransfer->SetDropEffectInt(
    5966           0 :                                  FilterDropEffect(action, effectAllowed));
    5967             :   }
    5968           0 :   else if (aDragEvent->mMessage == eDrop ||
    5969           0 :            aDragEvent->mMessage == eDragEnd) {
    5970             :     // For the drop and dragend events, set the drop effect based on the
    5971             :     // last value that the dropEffect had. This will have been set in
    5972             :     // EventStateManager::PostHandleEvent for the last dragenter or
    5973             :     // dragover event.
    5974             :     uint32_t dropEffect;
    5975           0 :     initialDataTransfer->GetDropEffectInt(&dropEffect);
    5976           0 :     aDragEvent->mDataTransfer->SetDropEffectInt(dropEffect);
    5977             :   }
    5978             : 
    5979           0 :   return NS_OK;
    5980             : }
    5981             : 
    5982             : /* static */
    5983             : uint32_t
    5984           0 : nsContentUtils::FilterDropEffect(uint32_t aAction, uint32_t aEffectAllowed)
    5985             : {
    5986             :   // It is possible for the drag action to include more than one action, but
    5987             :   // the widget code which sets the action from the keyboard state should only
    5988             :   // be including one. If multiple actions were set, we just consider them in
    5989             :   //  the following order:
    5990             :   //   copy, link, move
    5991           0 :   if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
    5992           0 :     aAction = nsIDragService::DRAGDROP_ACTION_COPY;
    5993           0 :   else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
    5994           0 :     aAction = nsIDragService::DRAGDROP_ACTION_LINK;
    5995           0 :   else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
    5996           0 :     aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
    5997             : 
    5998             :   // Filter the action based on the effectAllowed. If the effectAllowed
    5999             :   // doesn't include the action, then that action cannot be done, so adjust
    6000             :   // the action to something that is allowed. For a copy, adjust to move or
    6001             :   // link. For a move, adjust to copy or link. For a link, adjust to move or
    6002             :   // link. Otherwise, use none.
    6003           0 :   if (aAction & aEffectAllowed ||
    6004             :       aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
    6005           0 :     return aAction;
    6006           0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
    6007           0 :     return nsIDragService::DRAGDROP_ACTION_MOVE;
    6008           0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
    6009           0 :     return nsIDragService::DRAGDROP_ACTION_COPY;
    6010           0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
    6011           0 :     return nsIDragService::DRAGDROP_ACTION_LINK;
    6012           0 :   return nsIDragService::DRAGDROP_ACTION_NONE;
    6013             : }
    6014             : 
    6015             : /* static */
    6016             : bool
    6017           0 : nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
    6018             :                                      WidgetDragEvent* aDropEvent)
    6019             : {
    6020           0 :   nsCOMPtr<nsIContent> target = do_QueryInterface(aDropEvent->mOriginalTarget);
    6021           0 :   if (!target) {
    6022           0 :     return true;
    6023             :   }
    6024             : 
    6025           0 :   nsIDocument* targetDoc = target->OwnerDoc();
    6026           0 :   nsPIDOMWindowOuter* targetWin = targetDoc->GetWindow();
    6027           0 :   if (!targetWin) {
    6028           0 :     return true;
    6029             :   }
    6030             : 
    6031           0 :   nsCOMPtr<nsIDocShellTreeItem> tdsti = targetWin->GetDocShell();
    6032           0 :   if (!tdsti) {
    6033           0 :     return true;
    6034             :   }
    6035             : 
    6036             :   // Always allow dropping onto chrome shells.
    6037           0 :   if (tdsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
    6038           0 :     return false;
    6039             :   }
    6040             : 
    6041             :   // If there is no source node, then this is a drag from another
    6042             :   // application, which should be allowed.
    6043           0 :   nsCOMPtr<nsIDOMDocument> sourceDocument;
    6044           0 :   aDragSession->GetSourceDocument(getter_AddRefs(sourceDocument));
    6045           0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(sourceDocument);
    6046           0 :   if (doc) {
    6047             :     // Get each successive parent of the source document and compare it to
    6048             :     // the drop document. If they match, then this is a drag from a child frame.
    6049           0 :     do {
    6050           0 :       doc = doc->GetParentDocument();
    6051           0 :       if (doc == targetDoc) {
    6052             :         // The drag is from a child frame.
    6053           0 :         return true;
    6054             :       }
    6055             :     } while (doc);
    6056             :   }
    6057             : 
    6058           0 :   return false;
    6059             : }
    6060             : 
    6061             : /* static */
    6062             : bool
    6063         133 : nsContentUtils::URIIsLocalFile(nsIURI *aURI)
    6064             : {
    6065             :   bool isFile;
    6066         266 :   nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
    6067             : 
    6068             :   // Important: we do NOT test the entire URI chain here!
    6069         266 :   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
    6070             :                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
    6071         266 :                                 &isFile)) &&
    6072         266 :          isFile;
    6073             : }
    6074             : 
    6075             : /* static */
    6076             : nsIScriptContext*
    6077           2 : nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
    6078             :                                            nsresult* aRv)
    6079             : {
    6080           2 :   *aRv = NS_OK;
    6081           2 :   bool hasHadScriptObject = true;
    6082             :   nsIScriptGlobalObject* sgo =
    6083           2 :     aNode->OwnerDoc()->GetScriptHandlingObject(hasHadScriptObject);
    6084             :   // It is bad if the document doesn't have event handling context,
    6085             :   // but it used to have one.
    6086           2 :   if (!sgo && hasHadScriptObject) {
    6087           0 :     *aRv = NS_ERROR_UNEXPECTED;
    6088           0 :     return nullptr;
    6089             :   }
    6090             : 
    6091           2 :   if (sgo) {
    6092           0 :     nsIScriptContext* scx = sgo->GetContext();
    6093             :     // Bad, no context from script global object!
    6094           0 :     if (!scx) {
    6095           0 :       *aRv = NS_ERROR_UNEXPECTED;
    6096           0 :       return nullptr;
    6097             :     }
    6098           0 :     return scx;
    6099             :   }
    6100             : 
    6101           2 :   return nullptr;
    6102             : }
    6103             : 
    6104             : /* static */
    6105             : JSContext *
    6106       65698 : nsContentUtils::GetCurrentJSContext()
    6107             : {
    6108       65698 :   MOZ_ASSERT(NS_IsMainThread());
    6109       65698 :   MOZ_ASSERT(IsInitialized());
    6110       65698 :   if (!IsJSAPIActive()) {
    6111        1467 :     return nullptr;
    6112             :   }
    6113       64231 :   return danger::GetJSContext();
    6114             : }
    6115             : 
    6116             : /* static */
    6117             : JSContext *
    6118        2927 : nsContentUtils::GetCurrentJSContextForThread()
    6119             : {
    6120        2927 :   MOZ_ASSERT(IsInitialized());
    6121        2927 :   if (MOZ_LIKELY(NS_IsMainThread())) {
    6122        2927 :     return GetCurrentJSContext();
    6123             :   }
    6124           0 :   return workers::GetCurrentThreadJSContext();
    6125             : }
    6126             : 
    6127             : template<typename StringType, typename CharType>
    6128             : void
    6129        3998 : _ASCIIToLowerInSitu(StringType& aStr)
    6130             : {
    6131        3998 :   CharType* iter = aStr.BeginWriting();
    6132        3998 :   CharType* end = aStr.EndWriting();
    6133        3998 :   MOZ_ASSERT(iter && end);
    6134             : 
    6135       92514 :   while (iter != end) {
    6136       44258 :     CharType c = *iter;
    6137       44258 :     if (c >= 'A' && c <= 'Z') {
    6138           8 :       *iter = c + ('a' - 'A');
    6139             :     }
    6140       44258 :     ++iter;
    6141             :   }
    6142        3998 : }
    6143             : 
    6144             : /* static */
    6145             : void
    6146        3998 : nsContentUtils::ASCIIToLower(nsAString& aStr)
    6147             : {
    6148        3998 :   return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
    6149             : }
    6150             : 
    6151             : /* static */
    6152             : void
    6153           0 : nsContentUtils::ASCIIToLower(nsACString& aStr)
    6154             : {
    6155           0 :   return _ASCIIToLowerInSitu<nsACString, char>(aStr);
    6156             : }
    6157             : 
    6158             : template<typename StringType, typename CharType>
    6159             : void
    6160        6003 : _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest)
    6161             : {
    6162        6003 :   uint32_t len = aSource.Length();
    6163        6003 :   aDest.SetLength(len);
    6164        6003 :   MOZ_ASSERT(aDest.Length() == len);
    6165             : 
    6166        6003 :   CharType* dest = aDest.BeginWriting();
    6167        6003 :   MOZ_ASSERT(dest);
    6168             : 
    6169        6003 :   const CharType* iter = aSource.BeginReading();
    6170        6003 :   const CharType* end = aSource.EndReading();
    6171       90979 :   while (iter != end) {
    6172       42488 :     CharType c = *iter;
    6173       42488 :     *dest = (c >= 'A' && c <= 'Z') ?
    6174           0 :        c + ('a' - 'A') : c;
    6175       42488 :     ++iter;
    6176       42488 :     ++dest;
    6177             :   }
    6178        6003 : }
    6179             : 
    6180             : /* static */
    6181             : void
    6182        6003 : nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
    6183        6003 :   return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
    6184             : }
    6185             : 
    6186             : /* static */
    6187             : void
    6188           0 : nsContentUtils::ASCIIToLower(const nsACString& aSource, nsACString& aDest) {
    6189           0 :   return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
    6190             : }
    6191             : 
    6192             : 
    6193             : template<typename StringType, typename CharType>
    6194             : void
    6195           0 : _ASCIIToUpperInSitu(StringType& aStr)
    6196             : {
    6197           0 :   CharType* iter = aStr.BeginWriting();
    6198           0 :   CharType* end = aStr.EndWriting();
    6199           0 :   MOZ_ASSERT(iter && end);
    6200             : 
    6201           0 :   while (iter != end) {
    6202           0 :     CharType c = *iter;
    6203           0 :     if (c >= 'a' && c <= 'z') {
    6204           0 :       *iter = c + ('A' - 'a');
    6205             :     }
    6206           0 :     ++iter;
    6207             :   }
    6208           0 : }
    6209             : 
    6210             : /* static */
    6211             : void
    6212           0 : nsContentUtils::ASCIIToUpper(nsAString& aStr)
    6213             : {
    6214           0 :   return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
    6215             : }
    6216             : 
    6217             : /* static */
    6218             : void
    6219           0 : nsContentUtils::ASCIIToUpper(nsACString& aStr)
    6220             : {
    6221           0 :   return _ASCIIToUpperInSitu<nsACString, char>(aStr);
    6222             : }
    6223             : 
    6224             : template<typename StringType, typename CharType>
    6225             : void
    6226          27 : _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest)
    6227             : {
    6228          27 :   uint32_t len = aSource.Length();
    6229          27 :   aDest.SetLength(len);
    6230          27 :   MOZ_ASSERT(aDest.Length() == len);
    6231             : 
    6232          27 :   CharType* dest = aDest.BeginWriting();
    6233          27 :   MOZ_ASSERT(dest);
    6234             : 
    6235          27 :   const CharType* iter = aSource.BeginReading();
    6236          27 :   const CharType* end = aSource.EndReading();
    6237         245 :   while (iter != end) {
    6238         109 :     CharType c = *iter;
    6239         109 :     *dest = (c >= 'a' && c <= 'z') ?
    6240           0 :       c + ('A' - 'a') : c;
    6241         109 :     ++iter;
    6242         109 :     ++dest;
    6243             :   }
    6244          27 : }
    6245             : 
    6246             : /* static */
    6247             : void
    6248          27 : nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
    6249             : {
    6250          27 :   return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
    6251             : }
    6252             : 
    6253             : /* static */
    6254             : void
    6255           0 : nsContentUtils::ASCIIToUpper(const nsACString& aSource, nsACString& aDest)
    6256             : {
    6257           0 :   return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
    6258             : }
    6259             : 
    6260             : /* static */
    6261             : bool
    6262           8 : nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
    6263             :                                       const nsAString& aStr2)
    6264             : {
    6265           8 :   uint32_t len = aStr1.Length();
    6266           8 :   if (len != aStr2.Length()) {
    6267           0 :     return false;
    6268             :   }
    6269             : 
    6270           8 :   const char16_t* str1 = aStr1.BeginReading();
    6271           8 :   const char16_t* str2 = aStr2.BeginReading();
    6272           8 :   const char16_t* end = str1 + len;
    6273             : 
    6274         168 :   while (str1 < end) {
    6275          80 :     char16_t c1 = *str1++;
    6276          80 :     char16_t c2 = *str2++;
    6277             : 
    6278             :     // First check if any bits other than the 0x0020 differs
    6279          80 :     if ((c1 ^ c2) & 0xffdf) {
    6280           0 :       return false;
    6281             :     }
    6282             : 
    6283             :     // We know they can only differ in the 0x0020 bit.
    6284             :     // Likely the two chars are the same, so check that first
    6285          80 :     if (c1 != c2) {
    6286             :       // They do differ, but since it's only in the 0x0020 bit, check if it's
    6287             :       // the same ascii char, but just differing in case
    6288           0 :       char16_t c1Upper = c1 & 0xffdf;
    6289           0 :       if (!('A' <= c1Upper && c1Upper <= 'Z')) {
    6290           0 :         return false;
    6291             :       }
    6292             :     }
    6293             :   }
    6294             : 
    6295           8 :   return true;
    6296             : }
    6297             : 
    6298             : /* static */
    6299             : bool
    6300           7 : nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr)
    6301             : {
    6302           7 :   const char16_t* iter = aStr.BeginReading();
    6303           7 :   const char16_t* end = aStr.EndReading();
    6304         163 :   while (iter != end) {
    6305          78 :     char16_t c = *iter;
    6306          78 :     if (c >= 'A' && c <= 'Z') {
    6307           0 :       return true;
    6308             :     }
    6309          78 :     ++iter;
    6310             :   }
    6311             : 
    6312           7 :   return false;
    6313             : }
    6314             : 
    6315             : /* static */
    6316             : nsIInterfaceRequestor*
    6317           0 : nsContentUtils::SameOriginChecker()
    6318             : {
    6319           0 :   if (!sSameOriginChecker) {
    6320           0 :     sSameOriginChecker = new SameOriginCheckerImpl();
    6321           0 :     NS_ADDREF(sSameOriginChecker);
    6322             :   }
    6323           0 :   return sSameOriginChecker;
    6324             : }
    6325             : 
    6326             : /* static */
    6327             : nsresult
    6328           0 : nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel)
    6329             : {
    6330           0 :   if (!nsContentUtils::GetSecurityManager())
    6331           0 :     return NS_ERROR_NOT_AVAILABLE;
    6332             : 
    6333           0 :   nsCOMPtr<nsIPrincipal> oldPrincipal;
    6334           0 :   nsContentUtils::GetSecurityManager()->
    6335           0 :     GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
    6336             : 
    6337           0 :   nsCOMPtr<nsIURI> newURI;
    6338           0 :   aNewChannel->GetURI(getter_AddRefs(newURI));
    6339           0 :   nsCOMPtr<nsIURI> newOriginalURI;
    6340           0 :   aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
    6341             : 
    6342           0 :   NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
    6343             : 
    6344           0 :   nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
    6345           0 :   if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
    6346           0 :     rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
    6347             :   }
    6348             : 
    6349           0 :   return rv;
    6350             : }
    6351             : 
    6352           0 : NS_IMPL_ISUPPORTS(SameOriginCheckerImpl,
    6353             :                   nsIChannelEventSink,
    6354             :                   nsIInterfaceRequestor)
    6355             : 
    6356             : NS_IMETHODIMP
    6357           0 : SameOriginCheckerImpl::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
    6358             :                                               nsIChannel* aNewChannel,
    6359             :                                               uint32_t aFlags,
    6360             :                                               nsIAsyncVerifyRedirectCallback* cb)
    6361             : {
    6362           0 :   NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
    6363             : 
    6364           0 :   nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
    6365           0 :   if (NS_SUCCEEDED(rv)) {
    6366           0 :     cb->OnRedirectVerifyCallback(NS_OK);
    6367             :   }
    6368             : 
    6369           0 :   return rv;
    6370             : }
    6371             : 
    6372             : NS_IMETHODIMP
    6373           0 : SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult)
    6374             : {
    6375           0 :   return QueryInterface(aIID, aResult);
    6376             : }
    6377             : 
    6378             : /* static */
    6379             : nsresult
    6380           0 : nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal, nsACString& aOrigin)
    6381             : {
    6382           0 :   NS_PRECONDITION(aPrincipal, "missing principal");
    6383             : 
    6384           0 :   aOrigin.Truncate();
    6385             : 
    6386           0 :   nsCOMPtr<nsIURI> uri;
    6387           0 :   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    6388           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6389             : 
    6390           0 :   if (uri) {
    6391           0 :     return GetASCIIOrigin(uri, aOrigin);
    6392             :   }
    6393             : 
    6394           0 :   aOrigin.AssignLiteral("null");
    6395             : 
    6396           0 :   return NS_OK;
    6397             : }
    6398             : 
    6399             : /* static */
    6400             : nsresult
    6401           6 : nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin)
    6402             : {
    6403           6 :   NS_PRECONDITION(aURI, "missing uri");
    6404             : 
    6405             :   // For Blob URI we have to return the origin of page using its principal.
    6406          12 :   nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(aURI);
    6407           6 :   if (uriWithPrincipal) {
    6408           0 :     nsCOMPtr<nsIPrincipal> principal;
    6409           0 :     uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
    6410             : 
    6411           0 :     if (principal) {
    6412           0 :       nsCOMPtr<nsIURI> uri;
    6413           0 :       nsresult rv = principal->GetURI(getter_AddRefs(uri));
    6414           0 :       NS_ENSURE_SUCCESS(rv, rv);
    6415             : 
    6416           0 :       if (uri && uri != aURI) {
    6417           0 :         return GetASCIIOrigin(uri, aOrigin);
    6418             :       }
    6419             :     }
    6420             :   }
    6421             : 
    6422           6 :   aOrigin.Truncate();
    6423             : 
    6424          12 :   nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
    6425           6 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
    6426             : 
    6427          12 :   nsCString host;
    6428           6 :   nsresult rv = uri->GetAsciiHost(host);
    6429             : 
    6430           6 :   if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
    6431          12 :     nsCString scheme;
    6432           6 :     rv = uri->GetScheme(scheme);
    6433           6 :     NS_ENSURE_SUCCESS(rv, rv);
    6434             : 
    6435           6 :     int32_t port = -1;
    6436           6 :     uri->GetPort(&port);
    6437           6 :     if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
    6438           0 :       port = -1;
    6439             : 
    6440          12 :     nsCString hostPort;
    6441           6 :     rv = NS_GenerateHostPort(host, port, hostPort);
    6442           6 :     NS_ENSURE_SUCCESS(rv, rv);
    6443             : 
    6444           6 :     aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
    6445             :   }
    6446             :   else {
    6447           0 :     aOrigin.AssignLiteral("null");
    6448             :   }
    6449             : 
    6450           6 :   return NS_OK;
    6451             : }
    6452             : 
    6453             : /* static */
    6454             : nsresult
    6455           8 : nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin)
    6456             : {
    6457           8 :   NS_PRECONDITION(aPrincipal, "missing principal");
    6458             : 
    6459           8 :   aOrigin.Truncate();
    6460             : 
    6461          16 :   nsCOMPtr<nsIURI> uri;
    6462           8 :   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    6463           8 :   NS_ENSURE_SUCCESS(rv, rv);
    6464             : 
    6465           8 :   if (uri) {
    6466           3 :     return GetUTFOrigin(uri, aOrigin);
    6467             :   }
    6468             : 
    6469           5 :   aOrigin.AssignLiteral("null");
    6470             : 
    6471           5 :   return NS_OK;
    6472             : }
    6473             : 
    6474             : /* static */
    6475             : nsresult
    6476           4 : nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin)
    6477             : {
    6478           4 :   NS_PRECONDITION(aURI, "missing uri");
    6479             : 
    6480             :   // For Blob URI we have to return the origin of page using its principal.
    6481           8 :   nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(aURI);
    6482           4 :   if (uriWithPrincipal) {
    6483           0 :     nsCOMPtr<nsIPrincipal> principal;
    6484           0 :     uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
    6485             : 
    6486           0 :     if (principal) {
    6487           0 :       nsCOMPtr<nsIURI> uri;
    6488           0 :       nsresult rv = principal->GetURI(getter_AddRefs(uri));
    6489           0 :       NS_ENSURE_SUCCESS(rv, rv);
    6490             : 
    6491           0 :       if (uri && uri != aURI) {
    6492           0 :         return GetUTFOrigin(uri, aOrigin);
    6493             :       }
    6494             :     } else {
    6495             :       // We are probably dealing with an unknown blob URL.
    6496           0 :       bool isBlobURL = false;
    6497           0 :       nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
    6498           0 :       NS_ENSURE_SUCCESS(rv, rv);
    6499             : 
    6500           0 :       if (isBlobURL) {
    6501           0 :         nsAutoCString path;
    6502           0 :         rv = aURI->GetPath(path);
    6503           0 :         NS_ENSURE_SUCCESS(rv, rv);
    6504             : 
    6505           0 :         nsCOMPtr<nsIURI> uri;
    6506           0 :         nsresult rv = NS_NewURI(getter_AddRefs(uri), path);
    6507           0 :         if (NS_FAILED(rv)) {
    6508           0 :           aOrigin.AssignLiteral("null");
    6509           0 :           return NS_OK;
    6510             :         }
    6511             : 
    6512           0 :         return GetUTFOrigin(uri, aOrigin);
    6513             :       }
    6514             :     }
    6515             :   }
    6516             : 
    6517           4 :   aOrigin.Truncate();
    6518             : 
    6519           8 :   nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
    6520           4 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
    6521             : 
    6522           8 :   nsCString host;
    6523           4 :   nsresult rv = uri->GetHost(host);
    6524             : 
    6525           4 :   if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
    6526           4 :     nsCString scheme;
    6527           2 :     rv = uri->GetScheme(scheme);
    6528           2 :     NS_ENSURE_SUCCESS(rv, rv);
    6529             : 
    6530           2 :     int32_t port = -1;
    6531           2 :     uri->GetPort(&port);
    6532           2 :     if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
    6533           0 :       port = -1;
    6534             : 
    6535           4 :     nsCString hostPort;
    6536           2 :     rv = NS_GenerateHostPort(host, port, hostPort);
    6537           2 :     NS_ENSURE_SUCCESS(rv, rv);
    6538             : 
    6539           4 :     aOrigin = NS_ConvertUTF8toUTF16(
    6540           6 :       scheme + NS_LITERAL_CSTRING("://") + hostPort);
    6541             :   }
    6542             :   else {
    6543           2 :     aOrigin.AssignLiteral("null");
    6544             :   }
    6545             : 
    6546           4 :   return NS_OK;
    6547             : }
    6548             : 
    6549             : /* static */
    6550             : bool
    6551           0 : nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal)
    6552             : {
    6553           0 :   nsCOMPtr<nsIURI> channelURI;
    6554           0 :   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
    6555           0 :   NS_ENSURE_SUCCESS(rv, false);
    6556             : 
    6557           0 :   return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false, aAllowIfInheritsPrincipal));
    6558             : }
    6559             : 
    6560           5 : nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
    6561           5 :   : mString(aString), mService(nullptr)
    6562             : {
    6563           5 :   CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
    6564           5 : }
    6565             : 
    6566          10 : nsContentTypeParser::~nsContentTypeParser()
    6567             : {
    6568           5 :   NS_IF_RELEASE(mService);
    6569           5 : }
    6570             : 
    6571             : nsresult
    6572          10 : nsContentTypeParser::GetParameter(const char* aParameterName,
    6573             :                                   nsAString& aResult) const
    6574             : {
    6575          10 :   NS_ENSURE_TRUE(mService, NS_ERROR_FAILURE);
    6576          20 :   return mService->GetParameterHTTP(mString, aParameterName,
    6577          10 :                                     EmptyCString(), false, nullptr,
    6578          20 :                                     aResult);
    6579             : }
    6580             : 
    6581             : nsresult
    6582           5 : nsContentTypeParser::GetType(nsAString& aResult) const
    6583             : {
    6584           5 :   nsresult rv = GetParameter(nullptr, aResult);
    6585           5 :   if (NS_FAILED(rv)) {
    6586           0 :     return rv;
    6587             :   }
    6588           5 :   nsContentUtils::ASCIIToLower(aResult);
    6589           5 :   return NS_OK;
    6590             : }
    6591             : 
    6592             : /* static */
    6593             : 
    6594             : bool
    6595           0 : nsContentUtils::CanAccessNativeAnon()
    6596             : {
    6597           0 :   return LegacyIsCallerChromeOrNativeCode() || IsCallerContentXBL();
    6598             : }
    6599             : 
    6600             : /* static */ nsresult
    6601           0 : nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
    6602             :                                    bool aTrusted,
    6603             :                                    nsIDOMEvent* aSourceEvent,
    6604             :                                    nsIPresShell* aShell,
    6605             :                                    bool aCtrl,
    6606             :                                    bool aAlt,
    6607             :                                    bool aShift,
    6608             :                                    bool aMeta)
    6609             : {
    6610           0 :   NS_ENSURE_STATE(aTarget);
    6611           0 :   nsIDocument* doc = aTarget->OwnerDoc();
    6612           0 :   nsIPresShell* shell = doc->GetShell();
    6613           0 :   nsPresContext* presContext = nullptr;
    6614           0 :   if (shell) {
    6615           0 :     presContext = shell->GetPresContext();
    6616             :   }
    6617             :   RefPtr<XULCommandEvent> xulCommand = new XULCommandEvent(doc, presContext,
    6618           0 :                                                            nullptr);
    6619           0 :   xulCommand->InitCommandEvent(NS_LITERAL_STRING("command"), true, true,
    6620           0 :                                doc->GetInnerWindow(), 0, aCtrl, aAlt, aShift,
    6621           0 :                                aMeta, aSourceEvent);
    6622             : 
    6623           0 :   if (aShell) {
    6624           0 :     nsEventStatus status = nsEventStatus_eIgnore;
    6625           0 :     nsCOMPtr<nsIPresShell> kungFuDeathGrip = aShell;
    6626           0 :     return aShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
    6627             :   }
    6628             : 
    6629           0 :   nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget);
    6630           0 :   NS_ENSURE_STATE(target);
    6631             :   bool dummy;
    6632           0 :   return target->DispatchEvent(xulCommand, &dummy);
    6633             : }
    6634             : 
    6635             : // static
    6636             : nsresult
    6637         975 : nsContentUtils::WrapNative(JSContext *cx, nsISupports *native,
    6638             :                            nsWrapperCache *cache, const nsIID* aIID,
    6639             :                            JS::MutableHandle<JS::Value> vp, bool aAllowWrapping)
    6640             : {
    6641         975 :   MOZ_ASSERT(cx == GetCurrentJSContext());
    6642             : 
    6643         975 :   if (!native) {
    6644           0 :     vp.setNull();
    6645             : 
    6646           0 :     return NS_OK;
    6647             :   }
    6648             : 
    6649         975 :   JSObject *wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
    6650         975 :   if (wrapper) {
    6651           0 :     return NS_OK;
    6652             :   }
    6653             : 
    6654         975 :   NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
    6655             : 
    6656         975 :   if (!NS_IsMainThread()) {
    6657           0 :     MOZ_CRASH();
    6658             :   }
    6659             : 
    6660         975 :   nsresult rv = NS_OK;
    6661        1950 :   JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
    6662        2925 :   rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
    6663        2925 :                                      aAllowWrapping, vp);
    6664         975 :   return rv;
    6665             : }
    6666             : 
    6667             : nsresult
    6668           0 : nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
    6669             :                                   JSObject** aResult)
    6670             : {
    6671           0 :   if (!aCx) {
    6672           0 :     return NS_ERROR_FAILURE;
    6673             :   }
    6674             : 
    6675           0 :   int32_t dataLen = aData.Length();
    6676           0 :   *aResult = JS_NewArrayBuffer(aCx, dataLen);
    6677           0 :   if (!*aResult) {
    6678           0 :     return NS_ERROR_FAILURE;
    6679             :   }
    6680             : 
    6681           0 :   if (dataLen > 0) {
    6682           0 :     NS_ASSERTION(JS_IsArrayBufferObject(*aResult), "What happened?");
    6683           0 :     JS::AutoCheckCannotGC nogc;
    6684             :     bool isShared;
    6685           0 :     memcpy(JS_GetArrayBufferData(*aResult, &isShared, nogc), aData.BeginReading(), dataLen);
    6686           0 :     MOZ_ASSERT(!isShared);
    6687             :   }
    6688             : 
    6689           0 :   return NS_OK;
    6690             : }
    6691             : 
    6692             : void
    6693           0 : nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
    6694             : {
    6695             :   // In common cases where we don't have nulls in the
    6696             :   // string we can simple simply bypass the checking code.
    6697           0 :   int32_t firstNullPos = aInStr.FindChar('\0');
    6698           0 :   if (firstNullPos == kNotFound) {
    6699           0 :     aOutStr.Assign(aInStr);
    6700           0 :     return;
    6701             :   }
    6702             : 
    6703           0 :   aOutStr.SetCapacity(aInStr.Length() - 1);
    6704           0 :   nsAString::const_iterator start, end;
    6705           0 :   aInStr.BeginReading(start);
    6706           0 :   aInStr.EndReading(end);
    6707           0 :   while (start != end) {
    6708           0 :     if (*start != '\0')
    6709           0 :       aOutStr.Append(*start);
    6710           0 :     ++start;
    6711             :   }
    6712             : }
    6713             : 
    6714           0 : struct ClassMatchingInfo {
    6715             :   nsAttrValue::AtomArray mClasses;
    6716             :   nsCaseTreatment mCaseTreatment;
    6717             : };
    6718             : 
    6719             : // static
    6720             : bool
    6721           0 : nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
    6722             :                                 nsIAtom* aAtom, void* aData)
    6723             : {
    6724             :   // We can't match if there are no class names
    6725           0 :   const nsAttrValue* classAttr = aElement->GetClasses();
    6726           0 :   if (!classAttr) {
    6727           0 :     return false;
    6728             :   }
    6729             : 
    6730             :   // need to match *all* of the classes
    6731           0 :   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
    6732           0 :   uint32_t length = info->mClasses.Length();
    6733           0 :   if (!length) {
    6734             :     // If we actually had no classes, don't match.
    6735           0 :     return false;
    6736             :   }
    6737             :   uint32_t i;
    6738           0 :   for (i = 0; i < length; ++i) {
    6739           0 :     if (!classAttr->Contains(info->mClasses[i],
    6740             :                              info->mCaseTreatment)) {
    6741           0 :       return false;
    6742             :     }
    6743             :   }
    6744             : 
    6745           0 :   return true;
    6746             : }
    6747             : 
    6748             : // static
    6749             : void
    6750           0 : nsContentUtils::DestroyClassNameArray(void* aData)
    6751             : {
    6752           0 :   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
    6753           0 :   delete info;
    6754           0 : }
    6755             : 
    6756             : // static
    6757             : void*
    6758           0 : nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
    6759             :                                        const nsString* aClasses)
    6760             : {
    6761           0 :   nsAttrValue attrValue;
    6762           0 :   attrValue.ParseAtomArray(*aClasses);
    6763             :   // nsAttrValue::Equals is sensitive to order, so we'll send an array
    6764           0 :   auto* info = new ClassMatchingInfo;
    6765           0 :   if (attrValue.Type() == nsAttrValue::eAtomArray) {
    6766           0 :     info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
    6767           0 :   } else if (attrValue.Type() == nsAttrValue::eAtom) {
    6768           0 :     info->mClasses.AppendElement(attrValue.GetAtomValue());
    6769             :   }
    6770             : 
    6771           0 :   info->mCaseTreatment =
    6772           0 :     aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
    6773             :     eIgnoreCase : eCaseMatters;
    6774           0 :   return info;
    6775             : }
    6776             : 
    6777             : // static
    6778             : bool
    6779           4 : nsContentUtils::IsFocusedContent(const nsIContent* aContent)
    6780             : {
    6781           4 :   nsFocusManager* fm = nsFocusManager::GetFocusManager();
    6782             : 
    6783           4 :   return fm && fm->GetFocusedContent() == aContent;
    6784             : }
    6785             : 
    6786             : bool
    6787           0 : nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
    6788             : {
    6789             :   //XXXsmaug Shadow DOM spec issue!
    6790             :   //         We may need to change this to GetComposedDoc().
    6791           0 :   nsIDocument* doc = aContent->GetUncomposedDoc();
    6792           0 :   if (!doc) {
    6793           0 :     return false;
    6794             :   }
    6795             : 
    6796             :   // If the subdocument lives in another process, the frame is
    6797             :   // tabbable.
    6798           0 :   if (EventStateManager::IsRemoteTarget(aContent)) {
    6799           0 :     return true;
    6800             :   }
    6801             : 
    6802             :   // XXXbz should this use OwnerDoc() for GetSubDocumentFor?
    6803             :   // sXBL/XBL2 issue!
    6804           0 :   nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
    6805           0 :   if (!subDoc) {
    6806           0 :     return false;
    6807             :   }
    6808             : 
    6809           0 :   nsCOMPtr<nsIDocShell> docShell = subDoc->GetDocShell();
    6810           0 :   if (!docShell) {
    6811           0 :     return false;
    6812             :   }
    6813             : 
    6814           0 :   nsCOMPtr<nsIContentViewer> contentViewer;
    6815           0 :   docShell->GetContentViewer(getter_AddRefs(contentViewer));
    6816           0 :   if (!contentViewer) {
    6817           0 :     return false;
    6818             :   }
    6819             : 
    6820           0 :   nsCOMPtr<nsIContentViewer> zombieViewer;
    6821           0 :   contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
    6822             : 
    6823             :   // If there are 2 viewers for the current docshell, that
    6824             :   // means the current document is a zombie document.
    6825             :   // Only navigate into the subdocument if it's not a zombie.
    6826           0 :   return !zombieViewer;
    6827             : }
    6828             : 
    6829             : bool
    6830          17 : nsContentUtils::IsUserFocusIgnored(nsINode* aNode)
    6831             : {
    6832          17 :   if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) {
    6833           0 :     return false;
    6834             :   }
    6835             : 
    6836             :   // Check if our mozbrowser iframe ancestors has ignoreuserfocus attribute.
    6837          51 :   while (aNode) {
    6838          34 :     nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aNode);
    6839          17 :     if (browserFrame &&
    6840          17 :         aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::ignoreuserfocus) &&
    6841           0 :         browserFrame->GetReallyIsBrowser()) {
    6842           0 :       return true;
    6843             :     }
    6844          17 :     nsPIDOMWindowOuter* win = aNode->OwnerDoc()->GetWindow();
    6845          17 :     aNode = win ? win->GetFrameElementInternal() : nullptr;
    6846             :   }
    6847             : 
    6848          17 :   return false;
    6849             : }
    6850             : 
    6851             : bool
    6852         268 : nsContentUtils::HasScrollgrab(nsIContent* aContent)
    6853             : {
    6854             :   // If we ever standardize this feature we'll want to hook this up properly
    6855             :   // again. For now we're removing all the DOM-side code related to it but
    6856             :   // leaving the layout and APZ handling for it in place.
    6857         268 :   return false;
    6858             : }
    6859             : 
    6860             : void
    6861           0 : nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow)
    6862             : {
    6863           0 :   if (!aWindow) {
    6864           0 :     return;
    6865             :   }
    6866             : 
    6867             :   // Note that because FlushPendingNotifications flushes parents, this
    6868             :   // is O(N^2) in docshell tree depth.  However, the docshell tree is
    6869             :   // usually pretty shallow.
    6870             : 
    6871           0 :   if (nsCOMPtr<nsIDocument> doc = aWindow->GetDoc()) {
    6872           0 :     doc->FlushPendingNotifications(FlushType::Layout);
    6873             :   }
    6874             : 
    6875           0 :   if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
    6876           0 :     int32_t i = 0, i_end;
    6877           0 :     docShell->GetChildCount(&i_end);
    6878           0 :     for (; i < i_end; ++i) {
    6879           0 :       nsCOMPtr<nsIDocShellTreeItem> item;
    6880           0 :       docShell->GetChildAt(i, getter_AddRefs(item));
    6881           0 :       if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
    6882           0 :         FlushLayoutForTree(win);
    6883             :       }
    6884             :     }
    6885             :   }
    6886             : }
    6887             : 
    6888          12 : void nsContentUtils::RemoveNewlines(nsString &aString)
    6889             : {
    6890          12 :   aString.StripCRLF();
    6891          12 : }
    6892             : 
    6893             : void
    6894           0 : nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
    6895             : {
    6896           0 :   if (!PlatformToDOMLineBreaks(aString, fallible)) {
    6897           0 :     aString.AllocFailed(aString.Length());
    6898             :   }
    6899           0 : }
    6900             : 
    6901             : bool
    6902           6 : nsContentUtils::PlatformToDOMLineBreaks(nsString& aString, const fallible_t& aFallible)
    6903             : {
    6904           6 :   if (aString.FindChar(char16_t('\r')) != -1) {
    6905             :     // Windows linebreaks: Map CRLF to LF:
    6906           0 :     if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
    6907           0 :       return false;
    6908             :     }
    6909             : 
    6910             :     // Mac linebreaks: Map any remaining CR to LF:
    6911           0 :     if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
    6912           0 :       return false;
    6913             :     }
    6914             :   }
    6915             : 
    6916           6 :   return true;
    6917             : }
    6918             : 
    6919             : void
    6920           0 : nsContentUtils::PopulateStringFromStringBuffer(nsStringBuffer* aBuf,
    6921             :                                                nsAString& aResultString)
    6922             : {
    6923           0 :   MOZ_ASSERT(aBuf, "Expecting a non-null string buffer");
    6924             : 
    6925           0 :   uint32_t stringLen = NS_strlen(static_cast<char16_t*>(aBuf->Data()));
    6926             : 
    6927             :   // SANITY CHECK: In case the nsStringBuffer isn't correctly
    6928             :   // null-terminated, let's clamp its length using the allocated size, to be
    6929             :   // sure the resulting string doesn't sample past the end of the the buffer.
    6930             :   // (Note that StorageSize() is in units of bytes, so we have to convert that
    6931             :   // to units of PRUnichars, and subtract 1 for the null-terminator.)
    6932           0 :   uint32_t allocStringLen = (aBuf->StorageSize() / sizeof(char16_t)) - 1;
    6933           0 :   MOZ_ASSERT(stringLen <= allocStringLen,
    6934             :              "string buffer lacks null terminator!");
    6935           0 :   stringLen = std::min(stringLen, allocStringLen);
    6936             : 
    6937           0 :   aBuf->ToString(stringLen, aResultString);
    6938           0 : }
    6939             : 
    6940             : nsIPresShell*
    6941           0 : nsContentUtils::FindPresShellForDocument(const nsIDocument* aDoc)
    6942             : {
    6943           0 :   const nsIDocument* doc = aDoc;
    6944           0 :   nsIDocument* displayDoc = doc->GetDisplayDocument();
    6945           0 :   if (displayDoc) {
    6946           0 :     doc = displayDoc;
    6947             :   }
    6948             : 
    6949           0 :   nsIPresShell* shell = doc->GetShell();
    6950           0 :   if (shell) {
    6951           0 :     return shell;
    6952             :   }
    6953             : 
    6954           0 :   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
    6955           0 :   while (docShellTreeItem) {
    6956             :     // We may be in a display:none subdocument, or we may not have a presshell
    6957             :     // created yet.
    6958             :     // Walk the docshell tree to find the nearest container that has a presshell,
    6959             :     // and return that.
    6960           0 :     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
    6961           0 :     nsIPresShell* presShell = docShell->GetPresShell();
    6962           0 :     if (presShell) {
    6963           0 :       return presShell;
    6964             :     }
    6965           0 :     nsCOMPtr<nsIDocShellTreeItem> parent;
    6966           0 :     docShellTreeItem->GetParent(getter_AddRefs(parent));
    6967           0 :     docShellTreeItem = parent;
    6968             :   }
    6969             : 
    6970           0 :   return nullptr;
    6971             : }
    6972             : 
    6973             : nsIWidget*
    6974           0 : nsContentUtils::WidgetForDocument(const nsIDocument* aDoc)
    6975             : {
    6976           0 :   nsIPresShell* shell = FindPresShellForDocument(aDoc);
    6977           0 :   if (shell) {
    6978           0 :     nsViewManager* VM = shell->GetViewManager();
    6979           0 :     if (VM) {
    6980           0 :       nsView* rootView = VM->GetRootView();
    6981           0 :       if (rootView) {
    6982           0 :         nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView);
    6983           0 :         if (displayRoot) {
    6984           0 :           return displayRoot->GetNearestWidget(nullptr);
    6985             :         }
    6986             :       }
    6987             :     }
    6988             :   }
    6989             : 
    6990           0 :   return nullptr;
    6991             : }
    6992             : 
    6993             : nsIWidget*
    6994          44 : nsContentUtils::WidgetForContent(const nsIContent* aContent)
    6995             : {
    6996          44 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    6997          44 :   if (frame) {
    6998          44 :     frame = nsLayoutUtils::GetDisplayRootFrame(frame);
    6999             : 
    7000          44 :     nsView* view = frame->GetView();
    7001          44 :     if (view) {
    7002          44 :       return view->GetWidget();
    7003             :     }
    7004             :   }
    7005             : 
    7006           0 :   return nullptr;
    7007             : }
    7008             : 
    7009             : already_AddRefed<LayerManager>
    7010           3 : nsContentUtils::LayerManagerForContent(const nsIContent *aContent)
    7011             : {
    7012           3 :   nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
    7013           3 :   if (widget) {
    7014           6 :     RefPtr<LayerManager> manager = widget->GetLayerManager();
    7015           3 :     return manager.forget();
    7016             :   }
    7017             : 
    7018           0 :   return nullptr;
    7019             : }
    7020             : 
    7021             : static already_AddRefed<LayerManager>
    7022           0 : LayerManagerForDocumentInternal(const nsIDocument *aDoc, bool aRequirePersistent)
    7023             : {
    7024           0 :   nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
    7025           0 :   if (widget) {
    7026             :     RefPtr<LayerManager> manager =
    7027             :       widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
    7028           0 :                               nsIWidget::LAYER_MANAGER_CURRENT);
    7029           0 :     return manager.forget();
    7030             :   }
    7031             : 
    7032           0 :   return nullptr;
    7033             : }
    7034             : 
    7035             : already_AddRefed<LayerManager>
    7036           0 : nsContentUtils::LayerManagerForDocument(const nsIDocument *aDoc)
    7037             : {
    7038           0 :   return LayerManagerForDocumentInternal(aDoc, false);
    7039             : }
    7040             : 
    7041             : already_AddRefed<LayerManager>
    7042           0 : nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc)
    7043             : {
    7044           0 :   return LayerManagerForDocumentInternal(aDoc, true);
    7045             : }
    7046             : 
    7047             : bool
    7048          35 : nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
    7049             : {
    7050          35 :   if (IsSystemPrincipal(aPrincipal)) {
    7051          22 :     return true;
    7052             :   }
    7053             : 
    7054          26 :   nsCOMPtr<nsIURI> princURI;
    7055          13 :   aPrincipal->GetURI(getter_AddRefs(princURI));
    7056             : 
    7057          13 :   return princURI &&
    7058          13 :          ((sAllowXULXBL_for_file && SchemeIs(princURI, "file")) ||
    7059          39 :           IsSitePermAllow(aPrincipal, "allowXULXBL"));
    7060             : }
    7061             : 
    7062             : bool
    7063           0 : nsContentUtils::IsPDFJSEnabled()
    7064             : {
    7065             :    nsCOMPtr<nsIStreamConverterService> convServ =
    7066           0 :      do_GetService("@mozilla.org/streamConverters;1");
    7067           0 :    nsresult rv = NS_ERROR_FAILURE;
    7068           0 :    bool canConvert = false;
    7069           0 :    if (convServ) {
    7070           0 :      rv = convServ->CanConvert("application/pdf", "text/html", &canConvert);
    7071             :    }
    7072           0 :    return NS_SUCCEEDED(rv) && canConvert;
    7073             : }
    7074             : 
    7075             : already_AddRefed<nsIDocumentLoaderFactory>
    7076          12 : nsContentUtils::FindInternalContentViewer(const nsACString& aType,
    7077             :                                           ContentViewerType* aLoaderType)
    7078             : {
    7079          12 :   if (aLoaderType) {
    7080           4 :     *aLoaderType = TYPE_UNSUPPORTED;
    7081             :   }
    7082             : 
    7083             :   // one helper factory, please
    7084          24 :   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
    7085          12 :   if (!catMan)
    7086           0 :     return nullptr;
    7087             : 
    7088          24 :   nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
    7089             : 
    7090          24 :   nsXPIDLCString contractID;
    7091          36 :   nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers",
    7092          24 :                                          PromiseFlatCString(aType).get(),
    7093          36 :                                          getter_Copies(contractID));
    7094          12 :   if (NS_SUCCEEDED(rv)) {
    7095          12 :     docFactory = do_GetService(contractID);
    7096          12 :     if (docFactory && aLoaderType) {
    7097           4 :       if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID))
    7098           4 :         *aLoaderType = TYPE_CONTENT;
    7099           0 :       else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID))
    7100           0 :         *aLoaderType = TYPE_PLUGIN;
    7101             :       else
    7102           0 :       *aLoaderType = TYPE_UNKNOWN;
    7103             :     }
    7104          12 :     return docFactory.forget();
    7105             :   }
    7106             : 
    7107           0 :   if (DecoderTraits::IsSupportedInVideoDocument(aType)) {
    7108           0 :     docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
    7109           0 :     if (docFactory && aLoaderType) {
    7110           0 :       *aLoaderType = TYPE_CONTENT;
    7111             :     }
    7112           0 :     return docFactory.forget();
    7113             :   }
    7114             : 
    7115           0 :   return nullptr;
    7116             : }
    7117             : 
    7118             : static void
    7119           0 : ReportPatternCompileFailure(nsAString& aPattern, nsIDocument* aDocument,
    7120             :                             JSContext* cx)
    7121             : {
    7122           0 :     MOZ_ASSERT(JS_IsExceptionPending(cx));
    7123             : 
    7124           0 :     JS::RootedValue exn(cx);
    7125           0 :     if (!JS_GetPendingException(cx, &exn)) {
    7126           0 :       return;
    7127             :     }
    7128           0 :     if (!exn.isObject()) {
    7129             :       // If pending exception is not an object, it should be OOM.
    7130           0 :       return;
    7131             :     }
    7132             : 
    7133           0 :     JS::AutoSaveExceptionState savedExc(cx);
    7134           0 :     JS::RootedObject exnObj(cx, &exn.toObject());
    7135           0 :     JS::RootedValue messageVal(cx);
    7136           0 :     if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
    7137           0 :       return;
    7138             :     }
    7139           0 :     MOZ_ASSERT(messageVal.isString());
    7140             : 
    7141           0 :     JS::RootedString messageStr(cx, messageVal.toString());
    7142           0 :     MOZ_ASSERT(messageStr);
    7143             : 
    7144           0 :     nsAutoString wideMessage;
    7145           0 :     if (!AssignJSString(cx, wideMessage, messageStr)) {
    7146           0 :         return;
    7147             :     }
    7148             : 
    7149           0 :     const nsString& pattern = PromiseFlatString(aPattern);
    7150           0 :     const char16_t *strings[] = { pattern.get(), wideMessage.get() };
    7151           0 :     nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
    7152           0 :                                     NS_LITERAL_CSTRING("DOM"),
    7153             :                                     aDocument,
    7154             :                                     nsContentUtils::eDOM_PROPERTIES,
    7155             :                                     "PatternAttributeCompileFailure",
    7156           0 :                                     strings, ArrayLength(strings));
    7157           0 :     savedExc.drop();
    7158             : }
    7159             : 
    7160             : // static
    7161             : bool
    7162           0 : nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
    7163             :                                   nsIDocument* aDocument)
    7164             : {
    7165           0 :   NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
    7166             : 
    7167           0 :   AutoJSAPI jsapi;
    7168           0 :   jsapi.Init();
    7169           0 :   JSContext* cx = jsapi.cx();
    7170             : 
    7171             :   // We can use the junk scope here, because we're just using it for
    7172             :   // regexp evaluation, not actual script execution.
    7173           0 :   JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope());
    7174             : 
    7175             :   // The pattern has to match the entire value.
    7176           0 :   aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
    7177           0 :   aPattern.AppendLiteral(")$");
    7178             : 
    7179             :   JS::Rooted<JSObject*> re(cx,
    7180           0 :     JS_NewUCRegExpObject(cx,
    7181           0 :                          static_cast<char16_t*>(aPattern.BeginWriting()),
    7182           0 :                          aPattern.Length(), JSREG_UNICODE));
    7183           0 :   if (!re) {
    7184             :     // Remove extra patterns added above to report with the original pattern.
    7185           0 :     aPattern.Cut(0, 4);
    7186           0 :     aPattern.Cut(aPattern.Length() - 2, 2);
    7187           0 :     ReportPatternCompileFailure(aPattern, aDocument, cx);
    7188           0 :     return true;
    7189             :   }
    7190             : 
    7191           0 :   JS::Rooted<JS::Value> rval(cx, JS::NullValue());
    7192           0 :   size_t idx = 0;
    7193           0 :   if (!JS_ExecuteRegExpNoStatics(cx, re,
    7194           0 :                                  static_cast<char16_t*>(aValue.BeginWriting()),
    7195           0 :                                  aValue.Length(), &idx, true, &rval)) {
    7196           0 :     return true;
    7197             :   }
    7198             : 
    7199           0 :   return !rval.isNull();
    7200             : }
    7201             : 
    7202             : // static
    7203             : nsresult
    7204         143 : nsContentUtils::URIInheritsSecurityContext(nsIURI *aURI, bool *aResult)
    7205             : {
    7206             :   // Note: about:blank URIs do NOT inherit the security context from the
    7207             :   // current document, which is what this function tests for...
    7208             :   return NS_URIChainHasFlags(aURI,
    7209             :                              nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
    7210         143 :                              aResult);
    7211             : }
    7212             : 
    7213             : // static
    7214             : bool
    7215         135 : nsContentUtils::ChannelShouldInheritPrincipal(nsIPrincipal* aLoadingPrincipal,
    7216             :                                               nsIURI* aURI,
    7217             :                                               bool aInheritForAboutBlank,
    7218             :                                               bool aForceInherit)
    7219             : {
    7220         135 :   MOZ_ASSERT(aLoadingPrincipal, "Can not check inheritance without a principal");
    7221             : 
    7222             :   // Only tell the channel to inherit if it can't provide its own security context.
    7223             :   //
    7224             :   // XXX: If this is ever changed, check all callers for what owners
    7225             :   //      they're passing in.  In particular, see the code and
    7226             :   //      comments in nsDocShell::LoadURI where we fall back on
    7227             :   //      inheriting the owner if called from chrome.  That would be
    7228             :   //      very wrong if this code changed anything but channels that
    7229             :   //      can't provide their own security context!
    7230             :   //
    7231             :   // If aForceInherit is true, we will inherit, even for a channel that
    7232             :   // can provide its own security context. This is used for srcdoc loads.
    7233         135 :   bool inherit = aForceInherit;
    7234         135 :   if (!inherit) {
    7235             :     bool uriInherits;
    7236             :     // We expect URIInheritsSecurityContext to return success for an
    7237             :     // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
    7238             :     // This condition needs to match the one in nsDocShell::InternalLoad where
    7239             :     // we're checking for things that will use the owner.
    7240         135 :     inherit =
    7241         270 :       (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits)) &&
    7242         405 :        (uriInherits || (aInheritForAboutBlank && NS_IsAboutBlank(aURI)))) ||
    7243             :       //
    7244             :       // file: uri special-casing
    7245             :       //
    7246             :       // If this is a file: load opened from another file: then it may need
    7247             :       // to inherit the owner from the referrer so they can script each other.
    7248             :       // If we don't set the owner explicitly then each file: gets an owner
    7249             :       // based on its own codebase later.
    7250             :       //
    7251         133 :       (URIIsLocalFile(aURI) &&
    7252           0 :        NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false, false)) &&
    7253             :        // One more check here.  CheckMayLoad will always return true for the
    7254             :        // system principal, but we do NOT want to inherit in that case.
    7255           0 :        !IsSystemPrincipal(aLoadingPrincipal));
    7256             :   }
    7257         135 :   return inherit;
    7258             : }
    7259             : 
    7260             : /* static */
    7261             : bool
    7262           0 : nsContentUtils::IsFullScreenApiEnabled()
    7263             : {
    7264           0 :   return sIsFullScreenApiEnabled;
    7265             : }
    7266             : 
    7267             : /* static */
    7268             : bool
    7269           0 : nsContentUtils::IsRequestFullScreenAllowed(CallerType aCallerType)
    7270             : {
    7271             :   // If more time has elapsed since the user input than is specified by the
    7272             :   // dom.event.handling-user-input-time-limit pref (default 1 second), this
    7273             :   // function also returns false.
    7274             : 
    7275           0 :   if (!sTrustedFullScreenOnly || aCallerType == CallerType::System) {
    7276           0 :     return true;
    7277             :   }
    7278             : 
    7279           0 :   if (EventStateManager::IsHandlingUserInput()) {
    7280           0 :     TimeDuration timeout = HandlingUserInputTimeout();
    7281           0 :     return timeout <= TimeDuration(nullptr) ||
    7282           0 :       (TimeStamp::Now() -
    7283           0 :        EventStateManager::GetHandlingInputStart()) <= timeout;
    7284             :   }
    7285             : 
    7286           0 :   return false;
    7287             : }
    7288             : 
    7289             : /* static */
    7290             : bool
    7291           0 : nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal)
    7292             : {
    7293           0 :   if (!IsCutCopyRestricted() && EventStateManager::IsHandlingUserInput()) {
    7294           0 :     return true;
    7295             :   }
    7296             : 
    7297           0 :   return PrincipalHasPermission(aSubjectPrincipal, NS_LITERAL_STRING("clipboardWrite"));
    7298             : }
    7299             : 
    7300             : /* static */
    7301             : bool
    7302           0 : nsContentUtils::IsFrameTimingEnabled()
    7303             : {
    7304           0 :   return sIsFrameTimingPrefEnabled;
    7305             : }
    7306             : 
    7307             : /* static */
    7308             : bool
    7309           0 : nsContentUtils::HaveEqualPrincipals(nsIDocument* aDoc1, nsIDocument* aDoc2)
    7310             : {
    7311           0 :   if (!aDoc1 || !aDoc2) {
    7312           0 :     return false;
    7313             :   }
    7314           0 :   bool principalsEqual = false;
    7315           0 :   aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
    7316           0 :   return principalsEqual;
    7317             : }
    7318             : 
    7319             : /* static */
    7320             : bool
    7321           0 : nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
    7322             : {
    7323             : #ifdef XP_MACOSX
    7324             :   // We control dispatch to all mac plugins.
    7325             :   return false;
    7326             : #else
    7327           0 :   if (!aContent || !aContent->IsInUncomposedDoc()) {
    7328           0 :     return false;
    7329             :   }
    7330             : 
    7331           0 :   nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aContent);
    7332           0 :   if (!olc) {
    7333           0 :     return false;
    7334             :   }
    7335             : 
    7336           0 :   RefPtr<nsNPAPIPluginInstance> plugin;
    7337           0 :   olc->GetPluginInstance(getter_AddRefs(plugin));
    7338           0 :   if (!plugin) {
    7339           0 :     return false;
    7340             :   }
    7341             : 
    7342           0 :   bool isWindowless = false;
    7343           0 :   nsresult res = plugin->IsWindowless(&isWindowless);
    7344           0 :   if (NS_FAILED(res)) {
    7345           0 :     return false;
    7346             :   }
    7347             : 
    7348           0 :   return !isWindowless;
    7349             : #endif
    7350             : }
    7351             : 
    7352             : /* static */
    7353             : void
    7354           0 : nsContentUtils::FireMutationEventsForDirectParsing(nsIDocument* aDoc,
    7355             :                                                    nsIContent* aDest,
    7356             :                                                    int32_t aOldChildCount)
    7357             : {
    7358             :   // Fire mutation events. Optimize for the case when there are no listeners
    7359           0 :   int32_t newChildCount = aDest->GetChildCount();
    7360           0 :   if (newChildCount && nsContentUtils::
    7361           0 :         HasMutationListeners(aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
    7362           0 :     AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
    7363           0 :     NS_ASSERTION(newChildCount - aOldChildCount >= 0,
    7364             :                  "What, some unexpected dom mutation has happened?");
    7365           0 :     childNodes.SetCapacity(newChildCount - aOldChildCount);
    7366           0 :     for (nsIContent* child = aDest->GetFirstChild();
    7367           0 :          child;
    7368           0 :          child = child->GetNextSibling()) {
    7369           0 :       childNodes.AppendElement(child);
    7370             :     }
    7371           0 :     FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes);
    7372             :   }
    7373           0 : }
    7374             : 
    7375             : /* static */
    7376             : nsIDocument*
    7377           1 : nsContentUtils::GetRootDocument(nsIDocument* aDoc)
    7378             : {
    7379           1 :   if (!aDoc) {
    7380           0 :     return nullptr;
    7381             :   }
    7382           1 :   nsIDocument* doc = aDoc;
    7383           1 :   while (doc->GetParentDocument()) {
    7384           0 :     doc = doc->GetParentDocument();
    7385             :   }
    7386           1 :   return doc;
    7387             : }
    7388             : 
    7389             : /* static */
    7390             : bool
    7391           3 : nsContentUtils::IsInPointerLockContext(nsPIDOMWindowOuter* aWin)
    7392             : {
    7393           3 :   if (!aWin) {
    7394           2 :     return false;
    7395             :   }
    7396             : 
    7397             :   nsCOMPtr<nsIDocument> pointerLockedDoc =
    7398           2 :     do_QueryReferent(EventStateManager::sPointerLockedDoc);
    7399           1 :   if (!pointerLockedDoc || !pointerLockedDoc->GetWindow()) {
    7400           1 :     return false;
    7401             :   }
    7402             : 
    7403             :   nsCOMPtr<nsPIDOMWindowOuter> lockTop =
    7404           0 :     pointerLockedDoc->GetWindow()->GetScriptableTop();
    7405           0 :   nsCOMPtr<nsPIDOMWindowOuter> top = aWin->GetScriptableTop();
    7406             : 
    7407           0 :   return top == lockTop;
    7408             : }
    7409             : 
    7410             : // static
    7411             : int32_t
    7412           0 : nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
    7413             :                                                int32_t aOffset)
    7414             : {
    7415             :   // The structure of the anonymous frames within a text control frame is
    7416             :   // an optional block frame, followed by an optional br frame.
    7417             : 
    7418             :   // If the offset frame has a child, then this frame is the block which
    7419             :   // has the text frames (containing the content) as its children. This will
    7420             :   // be the case if we click to the right of any of the text frames, or at the
    7421             :   // bottom of the text area.
    7422           0 :   nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
    7423           0 :   if (firstChild) {
    7424             :     // In this case, the passed-in offset is incorrect, and we want the length
    7425             :     // of the entire content in the text control frame.
    7426           0 :     return firstChild->GetContent()->Length();
    7427             :   }
    7428             : 
    7429           0 :   if (aOffsetFrame->GetPrevSibling() &&
    7430           0 :       !aOffsetFrame->GetNextSibling()) {
    7431             :     // In this case, we're actually within the last frame, which is a br
    7432             :     // frame. Our offset should therefore be the length of the first child of
    7433             :     // our parent.
    7434             :     int32_t aOutOffset =
    7435           0 :       aOffsetFrame->GetParent()->PrincipalChildList().FirstChild()->GetContent()->Length();
    7436           0 :     return aOutOffset;
    7437             :   }
    7438             : 
    7439             :   // Otherwise, we're within one of the text frames, in which case our offset
    7440             :   // has already been correctly calculated.
    7441           0 :   return aOffset;
    7442             : }
    7443             : 
    7444             : // static
    7445             : void
    7446           3 : nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
    7447             :                                           Element* aRoot,
    7448             :                                           uint32_t& aOutStartOffset,
    7449             :                                           uint32_t& aOutEndOffset)
    7450             : {
    7451           3 :   MOZ_ASSERT(aSelection && aRoot);
    7452             : 
    7453             :   // We don't care which end of this selection is anchor and which is focus.  In
    7454             :   // fact, we explicitly want to know which is the _start_ and which is the
    7455             :   // _end_, not anchor vs focus.
    7456           3 :   const nsRange* range = aSelection->GetAnchorFocusRange();
    7457           3 :   if (!range) {
    7458             :     // Nothing selected
    7459           0 :     aOutStartOffset = aOutEndOffset = 0;
    7460           0 :     return;
    7461             :   }
    7462             : 
    7463             :   // All the node pointers here are raw pointers for performance.  We shouldn't
    7464             :   // be doing anything in this function that invalidates the node tree.
    7465           3 :   nsINode* startContainer = range->GetStartContainer();
    7466           3 :   uint32_t startOffset = range->StartOffset();
    7467           3 :   nsINode* endContainer = range->GetEndContainer();
    7468           3 :   uint32_t endOffset = range->EndOffset();
    7469             : 
    7470             :   // We have at most two children, consisting of an optional text node followed
    7471             :   // by an optional <br>.
    7472           3 :   NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children");
    7473           3 :   nsIContent* firstChild = aRoot->GetFirstChild();
    7474             : #ifdef DEBUG
    7475           6 :   nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
    7476           3 :   NS_ASSERTION(startContainer == aRoot || startContainer == firstChild ||
    7477             :                startContainer == lastChild, "Unexpected startContainer");
    7478           3 :   NS_ASSERTION(endContainer == aRoot || endContainer == firstChild ||
    7479             :                endContainer == lastChild, "Unexpected endContainer");
    7480             :   // firstChild is either text or a <br> (hence an element).
    7481           3 :   MOZ_ASSERT_IF(firstChild,
    7482             :                 firstChild->IsNodeOfType(nsINode::eTEXT) || firstChild->IsElement());
    7483             : #endif
    7484             :   // Testing IsElement() is faster than testing IsNodeOfType(), since it's
    7485             :   // non-virtual.
    7486           3 :   if (!firstChild || firstChild->IsElement()) {
    7487             :     // No text node, so everything is 0
    7488           1 :     startOffset = endOffset = 0;
    7489             :   } else {
    7490             :     // First child is text.  If the start/end is already in the text node,
    7491             :     // or the start of the root node, no change needed.  If it's in the root
    7492             :     // node but not the start, or in the trailing <br>, we need to set the
    7493             :     // offset to the end.
    7494           2 :     if ((startContainer == aRoot && startOffset != 0) ||
    7495           1 :         (startContainer != aRoot && startContainer != firstChild)) {
    7496           1 :       startOffset = firstChild->Length();
    7497             :     }
    7498           2 :     if ((endContainer == aRoot && endOffset != 0) ||
    7499           1 :         (endContainer != aRoot && endContainer != firstChild)) {
    7500           1 :       endOffset = firstChild->Length();
    7501             :     }
    7502             :   }
    7503             : 
    7504           3 :   MOZ_ASSERT(startOffset <= endOffset);
    7505           3 :   aOutStartOffset = startOffset;
    7506           3 :   aOutEndOffset = endOffset;
    7507             : }
    7508             : 
    7509             : 
    7510             : nsIEditor*
    7511           0 : nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext)
    7512             : {
    7513           0 :   nsCOMPtr<nsIDocShell> docShell(aPresContext->GetDocShell());
    7514             :   bool isEditable;
    7515           0 :   if (!docShell ||
    7516           0 :       NS_FAILED(docShell->GetEditable(&isEditable)) || !isEditable)
    7517           0 :     return nullptr;
    7518             : 
    7519           0 :   nsCOMPtr<nsIEditor> editor;
    7520           0 :   docShell->GetEditor(getter_AddRefs(editor));
    7521           0 :   return editor;
    7522             : }
    7523             : 
    7524             : bool
    7525        5720 : nsContentUtils::IsContentInsertionPoint(nsIContent* aContent)
    7526             : {
    7527             :   // Check if the content is a XBL insertion point.
    7528        5720 :   if (aContent->IsActiveChildrenElement()) {
    7529         243 :     return true;
    7530             :   }
    7531             : 
    7532             :   // Check if the content is a web components content insertion point.
    7533             :   HTMLContentElement* contentElement =
    7534        5477 :     HTMLContentElement::FromContent(aContent);
    7535        5477 :   return contentElement && contentElement->IsInsertionPoint();
    7536             : }
    7537             : 
    7538             : // static
    7539             : bool
    7540        4002 : nsContentUtils::HasDistributedChildren(nsIContent* aContent)
    7541             : {
    7542        4002 :   if (!aContent) {
    7543           0 :     return false;
    7544             :   }
    7545             : 
    7546        4002 :   if (aContent->GetShadowRoot()) {
    7547             :     // Children of a shadow root host are distributed
    7548             :     // to content insertion points in the shadow root.
    7549           0 :     return true;
    7550             :   }
    7551             : 
    7552        4002 :   ShadowRoot* shadow = ShadowRoot::FromNode(aContent);
    7553        4002 :   if (shadow) {
    7554             :     // Children of a shadow root are distributed to
    7555             :     // the shadow insertion point of the younger shadow root.
    7556           0 :     return shadow->GetYoungerShadowRoot();
    7557             :   }
    7558             : 
    7559        4002 :   HTMLShadowElement* shadowEl = HTMLShadowElement::FromContent(aContent);
    7560        4002 :   if (shadowEl && shadowEl->IsInsertionPoint()) {
    7561             :     // Children of a shadow insertion points are distributed
    7562             :     // to the insertion points in the older shadow root.
    7563           0 :     return shadowEl->GetOlderShadowRoot();
    7564             :   }
    7565             : 
    7566        4002 :   HTMLContentElement* contentEl = HTMLContentElement::FromContent(aContent);
    7567        4002 :   if (contentEl && contentEl->IsInsertionPoint()) {
    7568             :     // Children of a content insertion point are distributed to the
    7569             :     // content insertion point if the content insertion point does
    7570             :     // not match any nodes (fallback content).
    7571           0 :     return contentEl->MatchedNodes().IsEmpty();
    7572             :   }
    7573             : 
    7574        4002 :   return false;
    7575             : }
    7576             : 
    7577             : // static
    7578             : bool
    7579           0 : nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader)
    7580             : {
    7581           0 :   if (IsForbiddenSystemRequestHeader(aHeader)) {
    7582           0 :     return true;
    7583             :   }
    7584             : 
    7585           0 :   return StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"),
    7586           0 :                           nsCaseInsensitiveCStringComparator()) ||
    7587           0 :          StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"),
    7588           0 :                           nsCaseInsensitiveCStringComparator());
    7589             : }
    7590             : 
    7591             : // static
    7592             : bool
    7593           0 : nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader)
    7594             : {
    7595             :   static const char *kInvalidHeaders[] = {
    7596             :     "accept-charset", "accept-encoding", "access-control-request-headers",
    7597             :     "access-control-request-method", "connection", "content-length",
    7598             :     "cookie", "cookie2", "date", "dnt", "expect", "host", "keep-alive",
    7599             :     "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", "via"
    7600             :   };
    7601           0 :   for (auto& kInvalidHeader : kInvalidHeaders) {
    7602           0 :     if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
    7603           0 :       return true;
    7604             :     }
    7605             :   }
    7606           0 :   return false;
    7607             : }
    7608             : 
    7609             : // static
    7610             : bool
    7611           4 : nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader)
    7612             : {
    7613           7 :   return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
    7614           7 :           aHeader.LowerCaseEqualsASCII("set-cookie2"));
    7615             : }
    7616             : 
    7617             : // static
    7618             : bool
    7619           0 : nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
    7620             : {
    7621           0 :   nsAutoCString contentType;
    7622           0 :   nsAutoCString unused;
    7623             : 
    7624           0 :   nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
    7625           0 :   if (NS_FAILED(rv)) {
    7626           0 :     return false;
    7627             :   }
    7628             : 
    7629           0 :   return contentType.LowerCaseEqualsLiteral("text/plain") ||
    7630           0 :          contentType.LowerCaseEqualsLiteral("application/x-www-form-urlencoded") ||
    7631           0 :          contentType.LowerCaseEqualsLiteral("multipart/form-data");
    7632             : }
    7633             : 
    7634             : bool
    7635           1 : nsContentUtils::DOMWindowDumpEnabled()
    7636             : {
    7637             : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
    7638             :   // In optimized builds we check a pref that controls if we should
    7639             :   // enable output from dump() or not, in debug builds it's always
    7640             :   // enabled.
    7641             :   return nsContentUtils::sDOMWindowDumpEnabled;
    7642             : #else
    7643           1 :   return true;
    7644             : #endif
    7645             : }
    7646             : 
    7647             : bool
    7648           6 : nsContentUtils::DoNotTrackEnabled()
    7649             : {
    7650           6 :   return nsContentUtils::sDoNotTrackEnabled;
    7651             : }
    7652             : 
    7653             : mozilla::LogModule*
    7654           1 : nsContentUtils::DOMDumpLog()
    7655             : {
    7656           1 :   return sDOMDumpLog;
    7657             : }
    7658             : 
    7659             : bool
    7660           9 : nsContentUtils::GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult,
    7661             :                                    const fallible_t& aFallible)
    7662             : {
    7663           9 :   aResult.Truncate();
    7664           9 :   return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
    7665             : }
    7666             : 
    7667             : void
    7668           1 : nsContentUtils::GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult)
    7669             : {
    7670           1 :   if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
    7671           0 :     NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
    7672             :   }
    7673           1 : }
    7674             : 
    7675             : void
    7676           0 : nsContentUtils::DestroyMatchString(void* aData)
    7677             : {
    7678           0 :   if (aData) {
    7679           0 :     nsString* matchString = static_cast<nsString*>(aData);
    7680           0 :     delete matchString;
    7681             :   }
    7682           0 : }
    7683             : 
    7684             : bool
    7685           7 : nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType)
    7686             : {
    7687             :   // Table ordered from most to least likely JS MIME types.
    7688             :   static const char* jsTypes[] = {
    7689             :     "text/javascript",
    7690             :     "text/ecmascript",
    7691             :     "application/javascript",
    7692             :     "application/ecmascript",
    7693             :     "application/x-javascript",
    7694             :     "application/x-ecmascript",
    7695             :     "text/javascript1.0",
    7696             :     "text/javascript1.1",
    7697             :     "text/javascript1.2",
    7698             :     "text/javascript1.3",
    7699             :     "text/javascript1.4",
    7700             :     "text/javascript1.5",
    7701             :     "text/jscript",
    7702             :     "text/livescript",
    7703             :     "text/x-ecmascript",
    7704             :     "text/x-javascript",
    7705             :     nullptr
    7706             :   };
    7707             : 
    7708          11 :   for (uint32_t i = 0; jsTypes[i]; ++i) {
    7709          11 :     if (aMIMEType.LowerCaseEqualsASCII(jsTypes[i])) {
    7710           7 :       return true;
    7711             :     }
    7712             :   }
    7713             : 
    7714           0 :   return false;
    7715             : }
    7716             : 
    7717             : nsresult
    7718           5 : nsContentUtils::GenerateUUIDInPlace(nsID& aUUID)
    7719             : {
    7720           5 :   MOZ_ASSERT(sUUIDGenerator);
    7721             : 
    7722           5 :   nsresult rv = sUUIDGenerator->GenerateUUIDInPlace(&aUUID);
    7723           5 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    7724           0 :     return rv;
    7725             :   }
    7726             : 
    7727           5 :   return NS_OK;
    7728             : }
    7729             : 
    7730             : bool
    7731           0 : nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell)
    7732             : {
    7733             :   //
    7734             :   // SECURITY CHECK: disable prefetching and preloading from mailnews!
    7735             :   //
    7736             :   // walk up the docshell tree to see if any containing
    7737             :   // docshell are of type MAIL.
    7738             :   //
    7739             : 
    7740           0 :   if (!aDocShell) {
    7741           0 :     return false;
    7742             :   }
    7743             : 
    7744           0 :   nsCOMPtr<nsIDocShell> docshell = aDocShell;
    7745           0 :   nsCOMPtr<nsIDocShellTreeItem> parentItem;
    7746             : 
    7747           0 :   do {
    7748           0 :     uint32_t appType = 0;
    7749           0 :     nsresult rv = docshell->GetAppType(&appType);
    7750           0 :     if (NS_FAILED(rv) || appType == nsIDocShell::APP_TYPE_MAIL) {
    7751           0 :       return false; // do not prefetch, preload, preconnect from mailnews
    7752             :     }
    7753             : 
    7754           0 :     docshell->GetParent(getter_AddRefs(parentItem));
    7755           0 :     if (parentItem) {
    7756           0 :       docshell = do_QueryInterface(parentItem);
    7757           0 :       if (!docshell) {
    7758           0 :         NS_ERROR("cannot get a docshell from a treeItem!");
    7759           0 :         return false;
    7760             :       }
    7761             :     }
    7762             :   } while (parentItem);
    7763             : 
    7764           0 :   return true;
    7765             : }
    7766             : 
    7767             : uint64_t
    7768           0 : nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
    7769             : {
    7770             :   // can't do anything if there's no nsIRequest!
    7771           0 :   if (!aRequest) {
    7772           0 :     return 0;
    7773             :   }
    7774             : 
    7775           0 :   nsCOMPtr<nsILoadGroup> loadGroup;
    7776           0 :   nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
    7777             : 
    7778           0 :   if (NS_FAILED(rv) || !loadGroup) {
    7779           0 :     return 0;
    7780             :   }
    7781             : 
    7782           0 :   return GetInnerWindowID(loadGroup);
    7783             : }
    7784             : 
    7785             : uint64_t
    7786           2 : nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup)
    7787             : {
    7788           2 :   if (!aLoadGroup) {
    7789           0 :     return 0;
    7790             :   }
    7791             : 
    7792           4 :   nsCOMPtr<nsIInterfaceRequestor> callbacks;
    7793           2 :   nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
    7794           2 :   if (NS_FAILED(rv) || !callbacks) {
    7795           0 :     return 0;
    7796             :   }
    7797             : 
    7798           4 :   nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
    7799           2 :   if (!loadContext) {
    7800           0 :     return 0;
    7801             :   }
    7802             : 
    7803           4 :   nsCOMPtr<mozIDOMWindowProxy> window;
    7804           2 :   rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
    7805           2 :   if (NS_FAILED(rv) || !window) {
    7806           1 :     return 0;
    7807             :   }
    7808             : 
    7809           1 :   auto* pwindow = nsPIDOMWindowOuter::From(window);
    7810           1 :   if (!pwindow) {
    7811           0 :     return 0;
    7812             :   }
    7813             : 
    7814           1 :   nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
    7815           1 :   return inner ? inner->WindowID() : 0;
    7816             : }
    7817             : 
    7818             : nsresult
    7819           2 : nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost)
    7820             : {
    7821           2 :   aHost.Truncate();
    7822           2 :   nsresult rv = aURI->GetHost(aHost);
    7823           2 :   if (NS_FAILED(rv)) { // Some URIs do not have a host
    7824           0 :     return rv;
    7825             :   }
    7826             : 
    7827           2 :   if (aHost.FindChar(':') != -1) { // Escape IPv6 address
    7828           0 :     MOZ_ASSERT(!aHost.Length() ||
    7829             :       (aHost[0] !='[' && aHost[aHost.Length() - 1] != ']'));
    7830           0 :     aHost.Insert('[', 0);
    7831           0 :     aHost.Append(']');
    7832             :   }
    7833             : 
    7834           2 :   return NS_OK;
    7835             : }
    7836             : 
    7837             : nsresult
    7838           1 : nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost)
    7839             : {
    7840           2 :   nsAutoCString hostname;
    7841           1 :   nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
    7842           1 :   if (NS_FAILED(rv)) {
    7843           0 :     return rv;
    7844             :   }
    7845           1 :   CopyUTF8toUTF16(hostname, aHost);
    7846           1 :   return NS_OK;
    7847             : }
    7848             : 
    7849             : bool
    7850           4 : nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
    7851             :                                         CallOnRemoteChildFunction aCallback,
    7852             :                                         void* aArg)
    7853             : {
    7854           4 :   uint32_t tabChildCount = 0;
    7855           4 :   aManager->GetChildCount(&tabChildCount);
    7856           8 :   for (uint32_t j = 0; j < tabChildCount; ++j) {
    7857           6 :     nsCOMPtr<nsIMessageListenerManager> childMM;
    7858           4 :     aManager->GetChildAt(j, getter_AddRefs(childMM));
    7859           4 :     if (!childMM) {
    7860           0 :       continue;
    7861             :     }
    7862             : 
    7863           6 :     nsCOMPtr<nsIMessageBroadcaster> nonLeafMM = do_QueryInterface(childMM);
    7864           4 :     if (nonLeafMM) {
    7865           2 :       if (CallOnAllRemoteChildren(nonLeafMM, aCallback, aArg)) {
    7866           0 :         return true;
    7867             :       }
    7868           2 :       continue;
    7869             :     }
    7870             : 
    7871           4 :     nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM);
    7872             : 
    7873             :     mozilla::dom::ipc::MessageManagerCallback* cb =
    7874           2 :      static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback();
    7875           2 :     if (cb) {
    7876           2 :       nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
    7877           2 :       TabParent* remote = TabParent::GetFrom(fl);
    7878           2 :       if (remote && aCallback) {
    7879           2 :         if (aCallback(remote, aArg)) {
    7880           0 :           return true;
    7881             :         }
    7882             :       }
    7883             :     }
    7884             :   }
    7885             : 
    7886           4 :   return false;
    7887             : }
    7888             : 
    7889             : void
    7890           6 : nsContentUtils::CallOnAllRemoteChildren(nsPIDOMWindowOuter* aWindow,
    7891             :                                         CallOnRemoteChildFunction aCallback,
    7892             :                                         void* aArg)
    7893             : {
    7894          12 :   nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aWindow));
    7895           6 :   if (chromeWindow) {
    7896           4 :     nsCOMPtr<nsIMessageBroadcaster> windowMM;
    7897           2 :     chromeWindow->GetMessageManager(getter_AddRefs(windowMM));
    7898           2 :     if (windowMM) {
    7899           2 :       CallOnAllRemoteChildren(windowMM, aCallback, aArg);
    7900             :     }
    7901             :   }
    7902           6 : }
    7903             : 
    7904             : struct UIStateChangeInfo {
    7905             :   UIStateChangeType mShowAccelerators;
    7906             :   UIStateChangeType mShowFocusRings;
    7907             : 
    7908           1 :   UIStateChangeInfo(UIStateChangeType aShowAccelerators,
    7909             :                     UIStateChangeType aShowFocusRings)
    7910           1 :     : mShowAccelerators(aShowAccelerators),
    7911           1 :       mShowFocusRings(aShowFocusRings)
    7912           1 :   {}
    7913             : };
    7914             : 
    7915             : bool
    7916           0 : SetKeyboardIndicatorsChild(TabParent* aParent, void* aArg)
    7917             : {
    7918           0 :   UIStateChangeInfo* stateInfo = static_cast<UIStateChangeInfo*>(aArg);
    7919           0 :   Unused << aParent->SendSetKeyboardIndicators(stateInfo->mShowAccelerators,
    7920             :                                                stateInfo->mShowFocusRings);
    7921           0 :   return false;
    7922             : }
    7923             : 
    7924             : void
    7925           1 : nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(nsPIDOMWindowOuter* aWindow,
    7926             :                                                       UIStateChangeType aShowAccelerators,
    7927             :                                                       UIStateChangeType aShowFocusRings)
    7928             : {
    7929           1 :   UIStateChangeInfo stateInfo(aShowAccelerators, aShowFocusRings);
    7930             :   CallOnAllRemoteChildren(aWindow, SetKeyboardIndicatorsChild,
    7931           1 :                           (void *)&stateInfo);
    7932           1 : }
    7933             : 
    7934             : nsresult
    7935           0 : nsContentUtils::IPCTransferableToTransferable(const IPCDataTransfer& aDataTransfer,
    7936             :                                               const bool& aIsPrivateData,
    7937             :                                               nsIPrincipal* aRequestingPrincipal,
    7938             :                                               nsITransferable* aTransferable,
    7939             :                                               mozilla::dom::nsIContentParent* aContentParent,
    7940             :                                               mozilla::dom::TabChild* aTabChild)
    7941             : {
    7942             :   nsresult rv;
    7943             : 
    7944           0 :   const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
    7945           0 :   for (const auto& item : items) {
    7946           0 :     aTransferable->AddDataFlavor(item.flavor().get());
    7947             : 
    7948           0 :     if (item.data().type() == IPCDataTransferData::TnsString) {
    7949             :       nsCOMPtr<nsISupportsString> dataWrapper =
    7950           0 :         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
    7951           0 :       NS_ENSURE_SUCCESS(rv, rv);
    7952             : 
    7953           0 :       const nsString& text = item.data().get_nsString();
    7954           0 :       rv = dataWrapper->SetData(text);
    7955           0 :       NS_ENSURE_SUCCESS(rv, rv);
    7956             : 
    7957           0 :       rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
    7958           0 :                                   text.Length() * sizeof(char16_t));
    7959             : 
    7960           0 :       NS_ENSURE_SUCCESS(rv, rv);
    7961           0 :     } else if (item.data().type() == IPCDataTransferData::TShmem) {
    7962           0 :       if (nsContentUtils::IsFlavorImage(item.flavor())) {
    7963           0 :         nsCOMPtr<imgIContainer> imageContainer;
    7964           0 :         rv = nsContentUtils::DataTransferItemToImage(item,
    7965           0 :                                                      getter_AddRefs(imageContainer));
    7966           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7967             : 
    7968             :         nsCOMPtr<nsISupportsInterfacePointer> imgPtr =
    7969           0 :           do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
    7970           0 :         NS_ENSURE_TRUE(imgPtr, NS_ERROR_FAILURE);
    7971             : 
    7972           0 :         rv = imgPtr->SetData(imageContainer);
    7973           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7974             : 
    7975           0 :         aTransferable->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
    7976             :       } else {
    7977             :         nsCOMPtr<nsISupportsCString> dataWrapper =
    7978           0 :           do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
    7979           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7980             : 
    7981             :         // The buffer contains the terminating null.
    7982           0 :         Shmem itemData = item.data().get_Shmem();
    7983           0 :         const nsDependentCString text(itemData.get<char>(),
    7984           0 :                                       itemData.Size<char>());
    7985           0 :         rv = dataWrapper->SetData(text);
    7986           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7987             : 
    7988           0 :         rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
    7989             : 
    7990           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7991             :       }
    7992             : 
    7993           0 :       if (aContentParent) {
    7994           0 :         Unused << aContentParent->DeallocShmem(item.data().get_Shmem());
    7995           0 :       } else if (aTabChild) {
    7996           0 :         Unused << aTabChild->DeallocShmem(item.data().get_Shmem());
    7997             :       }
    7998             :     }
    7999             :   }
    8000             : 
    8001           0 :   aTransferable->SetIsPrivateData(aIsPrivateData);
    8002           0 :   aTransferable->SetRequestingPrincipal(aRequestingPrincipal);
    8003           0 :   return NS_OK;
    8004             : }
    8005             : 
    8006             : void
    8007           0 : nsContentUtils::TransferablesToIPCTransferables(nsIArray* aTransferables,
    8008             :                                                 nsTArray<IPCDataTransfer>& aIPC,
    8009             :                                                 bool aInSyncMessage,
    8010             :                                                 mozilla::dom::nsIContentChild* aChild,
    8011             :                                                 mozilla::dom::nsIContentParent* aParent)
    8012             : {
    8013           0 :   aIPC.Clear();
    8014           0 :   if (aTransferables) {
    8015           0 :     uint32_t transferableCount = 0;
    8016           0 :     aTransferables->GetLength(&transferableCount);
    8017           0 :     for (uint32_t i = 0; i < transferableCount; ++i) {
    8018           0 :       IPCDataTransfer* dt = aIPC.AppendElement();
    8019           0 :       nsCOMPtr<nsITransferable> transferable = do_QueryElementAt(aTransferables, i);
    8020           0 :       TransferableToIPCTransferable(transferable, dt, aInSyncMessage, aChild, aParent);
    8021             :     }
    8022             :   }
    8023           0 : }
    8024             : 
    8025             : nsresult
    8026           0 : nsContentUtils::SlurpFileToString(nsIFile* aFile, nsACString& aString)
    8027             : {
    8028           0 :   aString.Truncate();
    8029             : 
    8030           0 :   nsCOMPtr<nsIURI> fileURI;
    8031           0 :   nsresult rv = NS_NewFileURI(getter_AddRefs(fileURI), aFile);
    8032           0 :   if (NS_FAILED(rv)) {
    8033           0 :     return rv;
    8034             :   }
    8035             : 
    8036           0 :   nsCOMPtr<nsIChannel> channel;
    8037           0 :   rv = NS_NewChannel(getter_AddRefs(channel),
    8038             :                      fileURI,
    8039             :                      nsContentUtils::GetSystemPrincipal(),
    8040             :                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
    8041           0 :                      nsIContentPolicy::TYPE_OTHER);
    8042           0 :   if (NS_FAILED(rv)) {
    8043           0 :     return rv;
    8044             :   }
    8045             : 
    8046           0 :   nsCOMPtr<nsIInputStream> stream;
    8047           0 :   rv = channel->Open2(getter_AddRefs(stream));
    8048           0 :   if (NS_FAILED(rv)) {
    8049           0 :     return rv;
    8050             :   }
    8051             : 
    8052           0 :   rv = NS_ConsumeStream(stream, UINT32_MAX, aString);
    8053           0 :   if (NS_FAILED(rv)) {
    8054           0 :     return rv;
    8055             :   }
    8056             : 
    8057           0 :   rv = stream->Close();
    8058           0 :   if (NS_FAILED(rv)) {
    8059           0 :     return rv;
    8060             :   }
    8061             : 
    8062           0 :   return NS_OK;
    8063             : }
    8064             : 
    8065             : bool
    8066           0 : nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
    8067             : {
    8068           0 :   nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
    8069           0 :   if (!mime) {
    8070           0 :     return false;
    8071             :   }
    8072             : 
    8073           0 :   nsresult rv = mime->GetTypeFromFile(aFile, aType);
    8074           0 :   if (NS_FAILED(rv)) {
    8075           0 :     return false;
    8076             :   }
    8077             : 
    8078           0 :   return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
    8079             : }
    8080             : 
    8081             : nsresult
    8082           0 : nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
    8083             :                                         imgIContainer** aContainer)
    8084             : {
    8085           0 :   MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TShmem);
    8086           0 :   MOZ_ASSERT(IsFlavorImage(aItem.flavor()));
    8087             : 
    8088           0 :   const IPCDataTransferImage& imageDetails = aItem.imageDetails();
    8089           0 :   const IntSize size(imageDetails.width(), imageDetails.height());
    8090           0 :   if (!size.width || !size.height) {
    8091           0 :     return NS_ERROR_FAILURE;
    8092             :   }
    8093             : 
    8094           0 :   Shmem data = aItem.data().get_Shmem();
    8095             : 
    8096             :   RefPtr<DataSourceSurface> image =
    8097           0 :       CreateDataSourceSurfaceFromData(size,
    8098           0 :                                       static_cast<SurfaceFormat>(imageDetails.format()),
    8099           0 :                                       data.get<uint8_t>(),
    8100           0 :                                       imageDetails.stride());
    8101             : 
    8102           0 :   RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
    8103             :   nsCOMPtr<imgIContainer> imageContainer =
    8104           0 :     image::ImageOps::CreateFromDrawable(drawable);
    8105           0 :   imageContainer.forget(aContainer);
    8106             : 
    8107           0 :   return NS_OK;
    8108             : }
    8109             : 
    8110             : bool
    8111           0 : nsContentUtils::IsFlavorImage(const nsACString& aFlavor)
    8112             : {
    8113           0 :   return aFlavor.EqualsLiteral(kNativeImageMime) ||
    8114           0 :          aFlavor.EqualsLiteral(kJPEGImageMime) ||
    8115           0 :          aFlavor.EqualsLiteral(kJPGImageMime) ||
    8116           0 :          aFlavor.EqualsLiteral(kPNGImageMime) ||
    8117           0 :          aFlavor.EqualsLiteral(kGIFImageMime);
    8118             : }
    8119             : 
    8120             : static Shmem
    8121           0 : ConvertToShmem(mozilla::dom::nsIContentChild* aChild,
    8122             :                mozilla::dom::nsIContentParent* aParent,
    8123             :                const nsACString& aInput)
    8124             : {
    8125           0 :   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
    8126             : 
    8127             :   IShmemAllocator* allocator =
    8128           0 :     aChild ? static_cast<IShmemAllocator*>(aChild)
    8129           0 :            : static_cast<IShmemAllocator*>(aParent);
    8130             : 
    8131           0 :   Shmem result;
    8132           0 :   if (!allocator->AllocShmem(aInput.Length() + 1,
    8133             :                              SharedMemory::TYPE_BASIC,
    8134           0 :                              &result)) {
    8135           0 :     return result;
    8136             :   }
    8137             : 
    8138           0 :   memcpy(result.get<char>(),
    8139           0 :          aInput.BeginReading(),
    8140           0 :          aInput.Length() + 1);
    8141             : 
    8142           0 :   return result;
    8143             : }
    8144             : 
    8145             : void
    8146           0 : nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
    8147             :                                               IPCDataTransfer* aIPCDataTransfer,
    8148             :                                               bool aInSyncMessage,
    8149             :                                               mozilla::dom::nsIContentChild* aChild,
    8150             :                                               mozilla::dom::nsIContentParent* aParent)
    8151             : {
    8152           0 :   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
    8153             : 
    8154           0 :   if (aTransferable) {
    8155           0 :     nsCOMPtr<nsIArray> flavorList;
    8156           0 :     aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
    8157           0 :     if (flavorList) {
    8158           0 :       uint32_t flavorCount = 0;
    8159           0 :       flavorList->GetLength(&flavorCount);
    8160           0 :       for (uint32_t j = 0; j < flavorCount; ++j) {
    8161           0 :         nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
    8162           0 :         if (!flavor) {
    8163           0 :           continue;
    8164             :         }
    8165             : 
    8166           0 :         nsAutoCString flavorStr;
    8167           0 :         flavor->GetData(flavorStr);
    8168           0 :         if (!flavorStr.Length()) {
    8169           0 :           continue;
    8170             :         }
    8171             : 
    8172           0 :         nsCOMPtr<nsISupports> data;
    8173           0 :         uint32_t dataLen = 0;
    8174           0 :         aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
    8175             : 
    8176           0 :         nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
    8177           0 :         nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
    8178           0 :         if (text) {
    8179           0 :           nsAutoString dataAsString;
    8180           0 :           text->GetData(dataAsString);
    8181           0 :           IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8182           0 :           item->flavor() = flavorStr;
    8183           0 :           item->data() = dataAsString;
    8184           0 :         } else if (ctext) {
    8185           0 :           nsAutoCString dataAsString;
    8186           0 :           ctext->GetData(dataAsString);
    8187           0 :           IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8188           0 :           item->flavor() = flavorStr;
    8189             : 
    8190           0 :           Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
    8191           0 :           if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
    8192           0 :             continue;
    8193             :           }
    8194             : 
    8195           0 :           item->data() = dataAsShmem;
    8196             :         } else {
    8197             :           nsCOMPtr<nsISupportsInterfacePointer> sip =
    8198           0 :             do_QueryInterface(data);
    8199           0 :           if (sip) {
    8200           0 :             sip->GetData(getter_AddRefs(data));
    8201             :           }
    8202             : 
    8203             :           // Images to be pasted on the clipboard are nsIInputStreams
    8204           0 :           nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
    8205           0 :           if (stream) {
    8206           0 :             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8207           0 :             item->flavor() = flavorStr;
    8208             : 
    8209           0 :             nsCString imageData;
    8210           0 :             NS_ConsumeStream(stream, UINT32_MAX, imageData);
    8211             : 
    8212           0 :             Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
    8213           0 :             if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
    8214           0 :               continue;
    8215             :             }
    8216             : 
    8217           0 :             item->data() = imageDataShmem;
    8218           0 :             continue;
    8219             :           }
    8220             : 
    8221             :           // Images to be placed on the clipboard are imgIContainers.
    8222           0 :           nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
    8223           0 :           if (image) {
    8224             :             RefPtr<mozilla::gfx::SourceSurface> surface =
    8225           0 :               image->GetFrame(imgIContainer::FRAME_CURRENT,
    8226           0 :                               imgIContainer::FLAG_SYNC_DECODE);
    8227           0 :             if (!surface) {
    8228           0 :               continue;
    8229             :             }
    8230             :             RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
    8231           0 :               surface->GetDataSurface();
    8232           0 :             if (!dataSurface) {
    8233           0 :               continue;
    8234             :             }
    8235             :             size_t length;
    8236             :             int32_t stride;
    8237           0 :             IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
    8238           0 :                                                 : static_cast<IShmemAllocator*>(aParent);
    8239             :             Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
    8240           0 :                                                       allocator);
    8241             : 
    8242           0 :             if (surfaceData.isNothing()) {
    8243           0 :               continue;
    8244             :             }
    8245             : 
    8246           0 :             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8247           0 :             item->flavor() = flavorStr;
    8248             :             // Turn item->data() into an nsCString prior to accessing it.
    8249           0 :             item->data() = surfaceData.ref();
    8250             : 
    8251           0 :             IPCDataTransferImage& imageDetails = item->imageDetails();
    8252           0 :             mozilla::gfx::IntSize size = dataSurface->GetSize();
    8253           0 :             imageDetails.width() = size.width;
    8254           0 :             imageDetails.height() = size.height;
    8255           0 :             imageDetails.stride() = stride;
    8256           0 :             imageDetails.format() = static_cast<uint8_t>(dataSurface->GetFormat());
    8257             : 
    8258           0 :             continue;
    8259             :           }
    8260             : 
    8261             :           // Otherwise, handle this as a file.
    8262           0 :           nsCOMPtr<BlobImpl> blobImpl;
    8263           0 :           nsCOMPtr<nsIFile> file = do_QueryInterface(data);
    8264           0 :           if (file) {
    8265             :             // If we can send this over as a blob, do so. Otherwise, we're
    8266             :             // responding to a sync message and the child can't process the blob
    8267             :             // constructor before processing our response, which would crash. In
    8268             :             // that case, hope that the caller is nsClipboardProxy::GetData,
    8269             :             // called from editor and send over images as raw data.
    8270           0 :             if (aInSyncMessage) {
    8271           0 :               nsAutoCString type;
    8272           0 :               if (IsFileImage(file, type)) {
    8273           0 :                 IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8274           0 :                 item->flavor() = type;
    8275           0 :                 nsAutoCString data;
    8276           0 :                 SlurpFileToString(file, data);
    8277             : 
    8278           0 :                 Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
    8279           0 :                 item->data() = dataAsShmem;
    8280             :               }
    8281             : 
    8282           0 :               continue;
    8283             :             }
    8284             : 
    8285           0 :             if (aParent) {
    8286           0 :               bool isDir = false;
    8287           0 :               if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
    8288           0 :                 nsAutoString path;
    8289           0 :                 if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
    8290           0 :                   continue;
    8291             :                 }
    8292             : 
    8293           0 :                 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
    8294           0 :                 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
    8295             :               }
    8296             :             }
    8297             : 
    8298           0 :             blobImpl = new FileBlobImpl(file);
    8299             : 
    8300           0 :             IgnoredErrorResult rv;
    8301             : 
    8302             :             // Ensure that file data is cached no that the content process
    8303             :             // has this data available to it when passed over:
    8304           0 :             blobImpl->GetSize(rv);
    8305           0 :             if (NS_WARN_IF(rv.Failed())) {
    8306           0 :               continue;
    8307             :             }
    8308             : 
    8309           0 :             blobImpl->GetLastModified(rv);
    8310           0 :             if (NS_WARN_IF(rv.Failed())) {
    8311           0 :               continue;
    8312             :             }
    8313             :           } else {
    8314           0 :             if (aInSyncMessage) {
    8315             :               // Can't do anything.
    8316           0 :               continue;
    8317             :             }
    8318           0 :             blobImpl = do_QueryInterface(data);
    8319             :           }
    8320           0 :           if (blobImpl) {
    8321           0 :             IPCDataTransferData data;
    8322           0 :             IPCBlob ipcBlob;
    8323             : 
    8324             :             // If we failed to create the blob actor, then this blob probably
    8325             :             // can't get the file size for the underlying file, ignore it for
    8326             :             // now. TODO pass this through anyway.
    8327           0 :             if (aChild) {
    8328           0 :               nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
    8329           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    8330           0 :                 continue;
    8331             :               }
    8332             : 
    8333           0 :               data = ipcBlob;
    8334           0 :             } else if (aParent) {
    8335           0 :               nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
    8336           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    8337           0 :                 continue;
    8338             :               }
    8339             : 
    8340           0 :               data = ipcBlob;
    8341             :             }
    8342             : 
    8343           0 :             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8344           0 :             item->flavor() = flavorStr;
    8345           0 :             item->data() = data;
    8346             :           } else {
    8347             :             // This is a hack to support kFilePromiseMime.
    8348             :             // On Windows there just needs to be an entry for it,
    8349             :             // and for OSX we need to create
    8350             :             // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
    8351           0 :             if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
    8352           0 :               IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8353           0 :               item->flavor() = flavorStr;
    8354           0 :               item->data() = NS_ConvertUTF8toUTF16(flavorStr);
    8355           0 :             } else if (!data) {
    8356             :               // Empty element, transfer only the flavor
    8357           0 :               IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
    8358           0 :               item->flavor() = flavorStr;
    8359           0 :               item->data() = nsString();
    8360           0 :               continue;
    8361             :             }
    8362             :           }
    8363             :         }
    8364             :       }
    8365             :     }
    8366             :   }
    8367           0 : }
    8368             : 
    8369             : namespace {
    8370             : // The default type used for calling GetSurfaceData(). Gets surface data as
    8371             : // raw buffer.
    8372             : struct GetSurfaceDataRawBuffer
    8373             : {
    8374             :   using ReturnType = mozilla::UniquePtr<char[]>;
    8375             :   using BufferType = char*;
    8376             : 
    8377           0 :   ReturnType Allocate(size_t aSize)
    8378             :   {
    8379           0 :     return ReturnType(new char[aSize]);
    8380             :   }
    8381             : 
    8382             :   static BufferType
    8383           0 :   GetBuffer(const ReturnType& aReturnValue)
    8384             :   {
    8385           0 :     return aReturnValue.get();
    8386             :   }
    8387             : 
    8388             :   static ReturnType
    8389           0 :   NullValue()
    8390             :   {
    8391           0 :     return ReturnType();
    8392             :   }
    8393             : };
    8394             : 
    8395             : // The type used for calling GetSurfaceData() that allocates and writes to
    8396             : // a shared memory buffer.
    8397             : struct GetSurfaceDataShmem
    8398             : {
    8399             :   using ReturnType = Maybe<Shmem>;
    8400             :   using BufferType = char*;
    8401             : 
    8402           0 :   explicit GetSurfaceDataShmem(IShmemAllocator* aAllocator)
    8403           0 :     : mAllocator(aAllocator)
    8404           0 :   { }
    8405             : 
    8406           0 :   ReturnType Allocate(size_t aSize)
    8407             :   {
    8408           0 :     Shmem shmem;
    8409           0 :     if (!mAllocator->AllocShmem(aSize, SharedMemory::TYPE_BASIC, &shmem)) {
    8410           0 :       return Nothing();
    8411             :     }
    8412             : 
    8413           0 :     return Some(shmem);
    8414             :   }
    8415             : 
    8416             :   static BufferType
    8417           0 :   GetBuffer(const ReturnType& aReturnValue)
    8418             :   {
    8419           0 :     return aReturnValue.isSome() ? aReturnValue.ref().get<char>() : nullptr;
    8420             :   }
    8421             : 
    8422             :   static ReturnType
    8423           0 :   NullValue()
    8424             :   {
    8425           0 :     return ReturnType();
    8426             :   }
    8427             : private:
    8428             :   IShmemAllocator* mAllocator;
    8429             : };
    8430             : 
    8431             : /*
    8432             :  * Get the pixel data from the given source surface and return it as a buffer.
    8433             :  * The length and stride will be assigned from the surface.
    8434             :  */
    8435             : template <typename GetSurfaceDataContext = GetSurfaceDataRawBuffer>
    8436             : typename GetSurfaceDataContext::ReturnType
    8437           0 : GetSurfaceDataImpl(mozilla::gfx::DataSourceSurface* aSurface,
    8438             :                    size_t* aLength, int32_t* aStride,
    8439             :                    GetSurfaceDataContext aContext = GetSurfaceDataContext())
    8440             : {
    8441             :   mozilla::gfx::DataSourceSurface::MappedSurface map;
    8442           0 :   if (!aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
    8443           0 :     return GetSurfaceDataContext::NullValue();
    8444             :   }
    8445             : 
    8446           0 :   mozilla::gfx::IntSize size = aSurface->GetSize();
    8447             :   mozilla::CheckedInt32 requiredBytes =
    8448           0 :     mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
    8449           0 :   if (!requiredBytes.isValid()) {
    8450           0 :     return GetSurfaceDataContext::NullValue();
    8451             :   }
    8452             : 
    8453           0 :   size_t maxBufLen = requiredBytes.value();
    8454           0 :   mozilla::gfx::SurfaceFormat format = aSurface->GetFormat();
    8455             : 
    8456             :   // Surface data handling is totally nuts. This is the magic one needs to
    8457             :   // know to access the data.
    8458           0 :   size_t bufLen = maxBufLen - map.mStride + (size.width * BytesPerPixel(format));
    8459             : 
    8460             :   // nsDependentCString wants null-terminated string.
    8461           0 :   typename GetSurfaceDataContext::ReturnType surfaceData = aContext.Allocate(maxBufLen + 1);
    8462           0 :   if (GetSurfaceDataContext::GetBuffer(surfaceData)) {
    8463           0 :     memcpy(GetSurfaceDataContext::GetBuffer(surfaceData),
    8464           0 :            reinterpret_cast<char*>(map.mData),
    8465             :            bufLen);
    8466           0 :     memset(GetSurfaceDataContext::GetBuffer(surfaceData) + bufLen,
    8467             :            0,
    8468           0 :            maxBufLen - bufLen + 1);
    8469             :   }
    8470             : 
    8471           0 :   *aLength = maxBufLen;
    8472           0 :   *aStride = map.mStride;
    8473             : 
    8474           0 :   aSurface->Unmap();
    8475           0 :   return surfaceData;
    8476             : }
    8477             : } // Anonymous namespace.
    8478             : 
    8479             : mozilla::UniquePtr<char[]>
    8480           0 : nsContentUtils::GetSurfaceData(
    8481             :   NotNull<mozilla::gfx::DataSourceSurface*> aSurface,
    8482             :   size_t* aLength, int32_t* aStride)
    8483             : {
    8484           0 :   return GetSurfaceDataImpl(aSurface, aLength, aStride);
    8485             : }
    8486             : 
    8487             : Maybe<Shmem>
    8488           0 : nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
    8489             :                                size_t* aLength, int32_t* aStride,
    8490             :                                IShmemAllocator* aAllocator)
    8491             : {
    8492             :   return GetSurfaceDataImpl(aSurface, aLength, aStride,
    8493           0 :                             GetSurfaceDataShmem(aAllocator));
    8494             : }
    8495             : 
    8496             : mozilla::Modifiers
    8497           0 : nsContentUtils::GetWidgetModifiers(int32_t aModifiers)
    8498             : {
    8499           0 :   Modifiers result = 0;
    8500           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
    8501           0 :     result |= mozilla::MODIFIER_SHIFT;
    8502             :   }
    8503           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
    8504           0 :     result |= mozilla::MODIFIER_CONTROL;
    8505             :   }
    8506           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
    8507           0 :     result |= mozilla::MODIFIER_ALT;
    8508             :   }
    8509           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
    8510           0 :     result |= mozilla::MODIFIER_META;
    8511             :   }
    8512           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
    8513           0 :     result |= mozilla::MODIFIER_ALTGRAPH;
    8514             :   }
    8515           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
    8516           0 :     result |= mozilla::MODIFIER_CAPSLOCK;
    8517             :   }
    8518           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
    8519           0 :     result |= mozilla::MODIFIER_FN;
    8520             :   }
    8521           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
    8522           0 :     result |= mozilla::MODIFIER_FNLOCK;
    8523             :   }
    8524           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
    8525           0 :     result |= mozilla::MODIFIER_NUMLOCK;
    8526             :   }
    8527           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
    8528           0 :     result |= mozilla::MODIFIER_SCROLLLOCK;
    8529             :   }
    8530           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
    8531           0 :     result |= mozilla::MODIFIER_SYMBOL;
    8532             :   }
    8533           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
    8534           0 :     result |= mozilla::MODIFIER_SYMBOLLOCK;
    8535             :   }
    8536           0 :   if (aModifiers & nsIDOMWindowUtils::MODIFIER_OS) {
    8537           0 :     result |= mozilla::MODIFIER_OS;
    8538             :   }
    8539           0 :   return result;
    8540             : }
    8541             : 
    8542             : nsIWidget*
    8543           0 : nsContentUtils::GetWidget(nsIPresShell* aPresShell, nsPoint* aOffset) {
    8544           0 :   if (aPresShell) {
    8545           0 :     nsIFrame* frame = aPresShell->GetRootFrame();
    8546           0 :     if (frame)
    8547           0 :       return frame->GetView()->GetNearestWidget(aOffset);
    8548             :   }
    8549           0 :   return nullptr;
    8550             : }
    8551             : 
    8552             : int16_t
    8553           0 : nsContentUtils::GetButtonsFlagForButton(int32_t aButton)
    8554             : {
    8555           0 :   switch (aButton) {
    8556             :     case -1:
    8557           0 :       return WidgetMouseEvent::eNoButtonFlag;
    8558             :     case WidgetMouseEvent::eLeftButton:
    8559           0 :       return WidgetMouseEvent::eLeftButtonFlag;
    8560             :     case WidgetMouseEvent::eMiddleButton:
    8561           0 :       return WidgetMouseEvent::eMiddleButtonFlag;
    8562             :     case WidgetMouseEvent::eRightButton:
    8563           0 :       return WidgetMouseEvent::eRightButtonFlag;
    8564             :     case 4:
    8565           0 :       return WidgetMouseEvent::e4thButtonFlag;
    8566             :     case 5:
    8567           0 :       return WidgetMouseEvent::e5thButtonFlag;
    8568             :     default:
    8569           0 :       NS_ERROR("Button not known.");
    8570           0 :       return 0;
    8571             :   }
    8572             : }
    8573             : 
    8574             : LayoutDeviceIntPoint
    8575           0 : nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
    8576             :                               const nsPoint& aOffset,
    8577             :                               nsPresContext* aPresContext)
    8578             : {
    8579             :   return LayoutDeviceIntPoint::FromAppUnitsRounded(
    8580           0 :     (CSSPoint::ToAppUnits(aPoint) +
    8581           0 :     aOffset).ApplyResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(aPresContext->PresShell())),
    8582           0 :     aPresContext->AppUnitsPerDevPixel());
    8583             : }
    8584             : 
    8585             : nsView*
    8586           0 : nsContentUtils::GetViewToDispatchEvent(nsPresContext* presContext,
    8587             :                                        nsIPresShell** presShell)
    8588             : {
    8589           0 :   if (presContext && presShell) {
    8590           0 :     *presShell = presContext->PresShell();
    8591           0 :     if (*presShell) {
    8592           0 :       NS_ADDREF(*presShell);
    8593           0 :       if (nsViewManager* viewManager = (*presShell)->GetViewManager()) {
    8594           0 :         if (nsView* view = viewManager->GetRootView()) {
    8595           0 :           return view;
    8596             :         }
    8597             :       }
    8598             :     }
    8599             :   }
    8600           0 :   return nullptr;
    8601             : }
    8602             : 
    8603             : nsresult
    8604           0 : nsContentUtils::SendKeyEvent(nsIWidget* aWidget,
    8605             :                              const nsAString& aType,
    8606             :                              int32_t aKeyCode,
    8607             :                              int32_t aCharCode,
    8608             :                              int32_t aModifiers,
    8609             :                              uint32_t aAdditionalFlags,
    8610             :                              bool* aDefaultActionTaken)
    8611             : {
    8612             :   // get the widget to send the event to
    8613           0 :   if (!aWidget)
    8614           0 :     return NS_ERROR_FAILURE;
    8615             : 
    8616             :   EventMessage msg;
    8617           0 :   if (aType.EqualsLiteral("keydown"))
    8618           0 :     msg = eKeyDown;
    8619           0 :   else if (aType.EqualsLiteral("keyup"))
    8620           0 :     msg = eKeyUp;
    8621           0 :   else if (aType.EqualsLiteral("keypress"))
    8622           0 :     msg = eKeyPress;
    8623             :   else
    8624           0 :     return NS_ERROR_FAILURE;
    8625             : 
    8626           0 :   WidgetKeyboardEvent event(true, msg, aWidget);
    8627           0 :   event.mModifiers = GetWidgetModifiers(aModifiers);
    8628             : 
    8629           0 :   if (msg == eKeyPress) {
    8630           0 :     event.mKeyCode = aCharCode ? 0 : aKeyCode;
    8631           0 :     event.mCharCode = aCharCode;
    8632             :   } else {
    8633           0 :     event.mKeyCode = aKeyCode;
    8634           0 :     event.mCharCode = 0;
    8635             :   }
    8636             : 
    8637             :   uint32_t locationFlag = (aAdditionalFlags &
    8638             :     (nsIDOMWindowUtils::KEY_FLAG_LOCATION_STANDARD | nsIDOMWindowUtils::KEY_FLAG_LOCATION_LEFT |
    8639           0 :      nsIDOMWindowUtils::KEY_FLAG_LOCATION_RIGHT | nsIDOMWindowUtils::KEY_FLAG_LOCATION_NUMPAD));
    8640           0 :   switch (locationFlag) {
    8641             :     case nsIDOMWindowUtils::KEY_FLAG_LOCATION_STANDARD:
    8642           0 :       event.mLocation = eKeyLocationStandard;
    8643           0 :       break;
    8644             :     case nsIDOMWindowUtils::KEY_FLAG_LOCATION_LEFT:
    8645           0 :       event.mLocation = eKeyLocationLeft;
    8646           0 :       break;
    8647             :     case nsIDOMWindowUtils::KEY_FLAG_LOCATION_RIGHT:
    8648           0 :       event.mLocation = eKeyLocationRight;
    8649           0 :       break;
    8650             :     case nsIDOMWindowUtils::KEY_FLAG_LOCATION_NUMPAD:
    8651           0 :       event.mLocation = eKeyLocationNumpad;
    8652           0 :       break;
    8653             :     default:
    8654           0 :       if (locationFlag != 0) {
    8655           0 :         return NS_ERROR_INVALID_ARG;
    8656             :       }
    8657             :       // If location flag isn't set, choose the location from keycode.
    8658           0 :       switch (aKeyCode) {
    8659             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD0:
    8660             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD1:
    8661             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD2:
    8662             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD3:
    8663             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD4:
    8664             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD5:
    8665             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD6:
    8666             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD7:
    8667             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD8:
    8668             :         case nsIDOMKeyEvent::DOM_VK_NUMPAD9:
    8669             :         case nsIDOMKeyEvent::DOM_VK_MULTIPLY:
    8670             :         case nsIDOMKeyEvent::DOM_VK_ADD:
    8671             :         case nsIDOMKeyEvent::DOM_VK_SEPARATOR:
    8672             :         case nsIDOMKeyEvent::DOM_VK_SUBTRACT:
    8673             :         case nsIDOMKeyEvent::DOM_VK_DECIMAL:
    8674             :         case nsIDOMKeyEvent::DOM_VK_DIVIDE:
    8675           0 :           event.mLocation = eKeyLocationNumpad;
    8676           0 :           break;
    8677             :         case nsIDOMKeyEvent::DOM_VK_SHIFT:
    8678             :         case nsIDOMKeyEvent::DOM_VK_CONTROL:
    8679             :         case nsIDOMKeyEvent::DOM_VK_ALT:
    8680             :         case nsIDOMKeyEvent::DOM_VK_META:
    8681           0 :           event.mLocation = eKeyLocationLeft;
    8682           0 :           break;
    8683             :         default:
    8684           0 :           event.mLocation = eKeyLocationStandard;
    8685           0 :           break;
    8686             :       }
    8687           0 :       break;
    8688             :   }
    8689             : 
    8690           0 :   event.mRefPoint = LayoutDeviceIntPoint(0, 0);
    8691           0 :   event.mTime = PR_IntervalNow();
    8692           0 :   if (!(aAdditionalFlags & nsIDOMWindowUtils::KEY_FLAG_NOT_SYNTHESIZED_FOR_TESTS)) {
    8693           0 :     event.mFlags.mIsSynthesizedForTests = true;
    8694             :   }
    8695             : 
    8696           0 :   if (aAdditionalFlags & nsIDOMWindowUtils::KEY_FLAG_PREVENT_DEFAULT) {
    8697           0 :     event.PreventDefaultBeforeDispatch();
    8698             :   }
    8699             : 
    8700             :   nsEventStatus status;
    8701           0 :   nsresult rv = aWidget->DispatchEvent(&event, status);
    8702           0 :   NS_ENSURE_SUCCESS(rv, rv);
    8703             : 
    8704           0 :   *aDefaultActionTaken = (status != nsEventStatus_eConsumeNoDefault);
    8705             : 
    8706           0 :   return NS_OK;
    8707             : }
    8708             : 
    8709             : nsresult
    8710           0 : nsContentUtils::SendMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell,
    8711             :                                const nsAString& aType,
    8712             :                                float aX,
    8713             :                                float aY,
    8714             :                                int32_t aButton,
    8715             :                                int32_t aButtons,
    8716             :                                int32_t aClickCount,
    8717             :                                int32_t aModifiers,
    8718             :                                bool aIgnoreRootScrollFrame,
    8719             :                                float aPressure,
    8720             :                                unsigned short aInputSourceArg,
    8721             :                                uint32_t aIdentifier,
    8722             :                                bool aToWindow,
    8723             :                                bool *aPreventDefault,
    8724             :                                bool aIsDOMEventSynthesized,
    8725             :                                bool aIsWidgetEventSynthesized)
    8726             : {
    8727           0 :   nsPoint offset;
    8728           0 :   nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
    8729           0 :   if (!widget)
    8730           0 :     return NS_ERROR_FAILURE;
    8731             : 
    8732             :   EventMessage msg;
    8733           0 :   WidgetMouseEvent::ExitFrom exitFrom = WidgetMouseEvent::eChild;
    8734           0 :   bool contextMenuKey = false;
    8735           0 :   if (aType.EqualsLiteral("mousedown")) {
    8736           0 :     msg = eMouseDown;
    8737           0 :   } else if (aType.EqualsLiteral("mouseup")) {
    8738           0 :     msg = eMouseUp;
    8739           0 :   } else if (aType.EqualsLiteral("mousemove")) {
    8740           0 :     msg = eMouseMove;
    8741           0 :   } else if (aType.EqualsLiteral("mouseover")) {
    8742           0 :     msg = eMouseEnterIntoWidget;
    8743           0 :   } else if (aType.EqualsLiteral("mouseout")) {
    8744           0 :     msg = eMouseExitFromWidget;
    8745           0 :   } else if (aType.EqualsLiteral("mousecancel")) {
    8746           0 :     msg = eMouseExitFromWidget;
    8747           0 :     exitFrom = WidgetMouseEvent::eTopLevel;
    8748           0 :   } else if (aType.EqualsLiteral("mouselongtap")) {
    8749           0 :     msg = eMouseLongTap;
    8750           0 :   } else if (aType.EqualsLiteral("contextmenu")) {
    8751           0 :     msg = eContextMenu;
    8752           0 :     contextMenuKey = (aButton == 0);
    8753           0 :   } else if (aType.EqualsLiteral("MozMouseHittest")) {
    8754           0 :     msg = eMouseHitTest;
    8755             :   } else {
    8756           0 :     return NS_ERROR_FAILURE;
    8757             :   }
    8758             : 
    8759           0 :   if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
    8760           0 :     aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
    8761             :   }
    8762             : 
    8763             :   WidgetMouseEvent event(true, msg, widget,
    8764             :                          aIsWidgetEventSynthesized ?
    8765             :                            WidgetMouseEvent::eSynthesized :
    8766             :                            WidgetMouseEvent::eReal,
    8767             :                          contextMenuKey ? WidgetMouseEvent::eContextMenuKey :
    8768           0 :                                           WidgetMouseEvent::eNormal);
    8769           0 :   event.pointerId = aIdentifier;
    8770           0 :   event.mModifiers = GetWidgetModifiers(aModifiers);
    8771           0 :   event.button = aButton;
    8772           0 :   event.buttons = aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ?
    8773             :                   aButtons :
    8774           0 :                   msg == eMouseUp ? 0 : GetButtonsFlagForButton(aButton);
    8775           0 :   event.pressure = aPressure;
    8776           0 :   event.inputSource = aInputSourceArg;
    8777           0 :   event.mClickCount = aClickCount;
    8778           0 :   event.mTime = PR_IntervalNow();
    8779           0 :   event.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
    8780           0 :   event.mExitFrom = exitFrom;
    8781             : 
    8782           0 :   nsPresContext* presContext = aPresShell->GetPresContext();
    8783           0 :   if (!presContext)
    8784           0 :     return NS_ERROR_FAILURE;
    8785             : 
    8786           0 :   event.mRefPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
    8787           0 :   event.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
    8788             : 
    8789           0 :   nsEventStatus status = nsEventStatus_eIgnore;
    8790           0 :   if (aToWindow) {
    8791           0 :     nsCOMPtr<nsIPresShell> presShell;
    8792           0 :     nsView* view = GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
    8793           0 :     if (!presShell || !view) {
    8794           0 :       return NS_ERROR_FAILURE;
    8795             :     }
    8796           0 :     return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
    8797             :   }
    8798           0 :   if (gfxPrefs::TestEventsAsyncEnabled()) {
    8799           0 :     status = widget->DispatchInputEvent(&event);
    8800             :   } else {
    8801           0 :     nsresult rv = widget->DispatchEvent(&event, status);
    8802           0 :     NS_ENSURE_SUCCESS(rv, rv);
    8803             :   }
    8804           0 :   if (aPreventDefault) {
    8805           0 :     *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
    8806             :   }
    8807             : 
    8808           0 :   return NS_OK;
    8809             : }
    8810             : 
    8811             : /* static */
    8812             : void
    8813           0 : nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
    8814             :                                   EventTarget* aChromeEventHandler)
    8815             : {
    8816           0 :   nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
    8817           0 :   NS_ASSERTION(doc, "What happened here?");
    8818           0 :   doc->OnPageHide(true, aChromeEventHandler);
    8819             : 
    8820           0 :   int32_t childCount = 0;
    8821           0 :   aItem->GetChildCount(&childCount);
    8822           0 :   AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
    8823           0 :   kids.AppendElements(childCount);
    8824           0 :   for (int32_t i = 0; i < childCount; ++i) {
    8825           0 :     aItem->GetChildAt(i, getter_AddRefs(kids[i]));
    8826             :   }
    8827             : 
    8828           0 :   for (uint32_t i = 0; i < kids.Length(); ++i) {
    8829           0 :     if (kids[i]) {
    8830           0 :       FirePageHideEvent(kids[i], aChromeEventHandler);
    8831             :     }
    8832             :   }
    8833           0 : }
    8834             : 
    8835             : // The pageshow event is fired for a given document only if IsShowing() returns
    8836             : // the same thing as aFireIfShowing.  This gives us a way to fire pageshow only
    8837             : // on documents that are still loading or only on documents that are already
    8838             : // loaded.
    8839             : /* static */
    8840             : void
    8841           0 : nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
    8842             :                                   EventTarget* aChromeEventHandler,
    8843             :                                   bool aFireIfShowing)
    8844             : {
    8845           0 :   int32_t childCount = 0;
    8846           0 :   aItem->GetChildCount(&childCount);
    8847           0 :   AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
    8848           0 :   kids.AppendElements(childCount);
    8849           0 :   for (int32_t i = 0; i < childCount; ++i) {
    8850           0 :     aItem->GetChildAt(i, getter_AddRefs(kids[i]));
    8851             :   }
    8852             : 
    8853           0 :   for (uint32_t i = 0; i < kids.Length(); ++i) {
    8854           0 :     if (kids[i]) {
    8855           0 :       FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
    8856             :     }
    8857             :   }
    8858             : 
    8859           0 :   nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
    8860           0 :   NS_ASSERTION(doc, "What happened here?");
    8861           0 :   if (doc->IsShowing() == aFireIfShowing) {
    8862           0 :     doc->OnPageShow(true, aChromeEventHandler);
    8863             :   }
    8864           0 : }
    8865             : 
    8866             : /* static */
    8867             : already_AddRefed<nsPIWindowRoot>
    8868           5 : nsContentUtils::GetWindowRoot(nsIDocument* aDoc)
    8869             : {
    8870           5 :   if (aDoc) {
    8871           5 :     if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
    8872           5 :       return win->GetTopWindowRoot();
    8873             :     }
    8874             :   }
    8875           0 :   return nullptr;
    8876             : }
    8877             : 
    8878             : /* static */
    8879             : bool
    8880        1268 : nsContentUtils::IsPreloadType(nsContentPolicyType aType)
    8881             : {
    8882        1268 :   if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
    8883        1254 :       aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
    8884             :       aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
    8885          14 :     return true;
    8886             :   }
    8887        1254 :   return false;
    8888             : }
    8889             : 
    8890             : nsresult
    8891           0 : nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
    8892             :                                               nsIDocument* aDoc,
    8893             :                                               nsIHttpChannel* aChannel,
    8894             :                                               mozilla::net::ReferrerPolicy aReferrerPolicy)
    8895             : {
    8896           0 :   NS_ENSURE_ARG_POINTER(aPrincipal);
    8897           0 :   NS_ENSURE_ARG_POINTER(aChannel);
    8898             : 
    8899           0 :   nsCOMPtr<nsIURI> principalURI;
    8900             : 
    8901           0 :   if (IsSystemPrincipal(aPrincipal)) {
    8902           0 :     return NS_OK;
    8903             :   }
    8904             : 
    8905           0 :   aPrincipal->GetURI(getter_AddRefs(principalURI));
    8906             : 
    8907           0 :   if (!aDoc) {
    8908           0 :     return aChannel->SetReferrerWithPolicy(principalURI, aReferrerPolicy);
    8909             :   }
    8910             : 
    8911             :   // If it weren't for history.push/replaceState, we could just use the
    8912             :   // principal's URI here.  But since we want changes to the URI effected
    8913             :   // by push/replaceState to be reflected in the XHR referrer, we have to
    8914             :   // be more clever.
    8915             :   //
    8916             :   // If the document's original URI (before any push/replaceStates) matches
    8917             :   // our principal, then we use the document's current URI (after
    8918             :   // push/replaceStates).  Otherwise (if the document is, say, a data:
    8919             :   // URI), we just use the principal's URI.
    8920           0 :   nsCOMPtr<nsIURI> docCurURI = aDoc->GetDocumentURI();
    8921           0 :   nsCOMPtr<nsIURI> docOrigURI = aDoc->GetOriginalURI();
    8922             : 
    8923           0 :   nsCOMPtr<nsIURI> referrerURI;
    8924             : 
    8925           0 :   if (principalURI && docCurURI && docOrigURI) {
    8926           0 :     bool equal = false;
    8927           0 :     principalURI->Equals(docOrigURI, &equal);
    8928           0 :     if (equal) {
    8929           0 :       referrerURI = docCurURI;
    8930             :     }
    8931             :   }
    8932             : 
    8933           0 :   if (!referrerURI) {
    8934           0 :     referrerURI = principalURI;
    8935             :   }
    8936             : 
    8937           0 :   return aChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
    8938             : }
    8939             : 
    8940             : // static
    8941             : net::ReferrerPolicy
    8942           0 : nsContentUtils::GetReferrerPolicyFromHeader(const nsAString& aHeader)
    8943             : {
    8944             :   // Multiple headers could be concatenated into one comma-separated
    8945             :   // list of policies. Need to tokenize the multiple headers.
    8946           0 :   nsCharSeparatedTokenizer tokenizer(aHeader, ',');
    8947           0 :   nsAutoString token;
    8948           0 :   net::ReferrerPolicy referrerPolicy = mozilla::net::RP_Unset;
    8949           0 :   while (tokenizer.hasMoreTokens()) {
    8950           0 :     token = tokenizer.nextToken();
    8951           0 :     if (token.IsEmpty()) {
    8952           0 :       continue;
    8953             :     }
    8954           0 :     net::ReferrerPolicy policy = net::ReferrerPolicyFromString(token);
    8955           0 :     if (policy != net::RP_Unset) {
    8956           0 :       referrerPolicy = policy;
    8957             :     }
    8958             :   }
    8959           0 :   return referrerPolicy;
    8960             : }
    8961             : 
    8962             : // static
    8963             : bool
    8964           1 : nsContentUtils::PromiseRejectionEventsEnabled(JSContext* aCx, JSObject* aObj)
    8965             : {
    8966           1 :   if (NS_IsMainThread()) {
    8967           0 :     return Preferences::GetBool("dom.promise_rejection_events.enabled", false);
    8968             :   }
    8969             : 
    8970             :   using namespace workers;
    8971             : 
    8972             :   // Otherwise, check the pref via the WorkerPrivate
    8973           1 :   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
    8974           1 :   if (!workerPrivate) {
    8975           0 :     return false;
    8976             :   }
    8977             : 
    8978           1 :   return workerPrivate->PromiseRejectionEventsEnabled();
    8979             : }
    8980             : 
    8981             : // static
    8982             : bool
    8983           4 : nsContentUtils::PushEnabled(JSContext* aCx, JSObject* aObj)
    8984             : {
    8985           4 :   if (NS_IsMainThread()) {
    8986           0 :     return Preferences::GetBool("dom.push.enabled", false);
    8987             :   }
    8988             : 
    8989             :   using namespace workers;
    8990             : 
    8991             :   // Otherwise, check the pref via the WorkerPrivate
    8992           4 :   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
    8993           4 :   if (!workerPrivate) {
    8994           0 :     return false;
    8995             :   }
    8996             : 
    8997           4 :   return workerPrivate->PushEnabled();
    8998             : }
    8999             : 
    9000             : // static
    9001             : bool
    9002          10 : nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel)
    9003             : {
    9004          10 :   nsLoadFlags loadFlags = 0;
    9005          10 :   aChannel->GetLoadFlags(&loadFlags);
    9006          10 :   if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
    9007           2 :     return true;
    9008             :   }
    9009             : 
    9010          16 :   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
    9011           8 :   if (!loadInfo) {
    9012           0 :     return false;
    9013             :   }
    9014           8 :   nsContentPolicyType type = loadInfo->InternalContentPolicyType();
    9015           8 :   return type == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
    9016           8 :          type == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
    9017             : }
    9018             : 
    9019             : // static, public
    9020             : nsContentUtils::StorageAccess
    9021           0 : nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
    9022             : {
    9023           0 :   MOZ_ASSERT(aWindow->IsInnerWindow());
    9024             : 
    9025           0 :   if (nsIDocument* document = aWindow->GetExtantDoc()) {
    9026           0 :     nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
    9027           0 :     return InternalStorageAllowedForPrincipal(principal, aWindow);
    9028             :   }
    9029             : 
    9030           0 :   return StorageAccess::eDeny;
    9031             : }
    9032             : 
    9033             : // static, public
    9034             : nsContentUtils::StorageAccess
    9035           0 : nsContentUtils::StorageAllowedForPrincipal(nsIPrincipal* aPrincipal)
    9036             : {
    9037           0 :   return InternalStorageAllowedForPrincipal(aPrincipal, nullptr);
    9038             : }
    9039             : 
    9040             : // static, private
    9041             : void
    9042           0 : nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
    9043             :                                               uint32_t* aLifetimePolicy,
    9044             :                                               uint32_t* aBehavior)
    9045             : {
    9046           0 :   *aLifetimePolicy = sCookiesLifetimePolicy;
    9047           0 :   *aBehavior = sCookiesBehavior;
    9048             : 
    9049             :   // Any permissions set for the given principal will override our default
    9050             :   // settings from preferences.
    9051             :   nsCOMPtr<nsIPermissionManager> permissionManager =
    9052           0 :     services::GetPermissionManager();
    9053           0 :   if (!permissionManager) {
    9054           0 :     return;
    9055             :   }
    9056             : 
    9057             :   uint32_t perm;
    9058           0 :   permissionManager->TestPermissionFromPrincipal(aPrincipal, "cookie", &perm);
    9059           0 :   switch (perm) {
    9060             :     case nsICookiePermission::ACCESS_ALLOW:
    9061           0 :       *aBehavior = nsICookieService::BEHAVIOR_ACCEPT;
    9062           0 :       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
    9063           0 :       break;
    9064             :     case nsICookiePermission::ACCESS_DENY:
    9065           0 :       *aBehavior = nsICookieService::BEHAVIOR_REJECT;
    9066           0 :       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
    9067           0 :       break;
    9068             :     case nsICookiePermission::ACCESS_SESSION:
    9069           0 :       *aBehavior = nsICookieService::BEHAVIOR_ACCEPT;
    9070           0 :       *aLifetimePolicy = nsICookieService::ACCEPT_SESSION;
    9071           0 :       break;
    9072             :     case nsICookiePermission::ACCESS_ALLOW_FIRST_PARTY_ONLY:
    9073           0 :       *aBehavior = nsICookieService::BEHAVIOR_REJECT_FOREIGN;
    9074             :       // NOTE: The decision was made here to override the lifetime policy to be
    9075             :       // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
    9076             :       // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
    9077             :       // specific domain. As BEHAVIOR_REJECT_FOREIGN isn't visible in our UI,
    9078             :       // this is probably not an issue.
    9079           0 :       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
    9080           0 :       break;
    9081             :     case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
    9082           0 :       *aBehavior = nsICookieService::BEHAVIOR_LIMIT_FOREIGN;
    9083             :       // NOTE: The decision was made here to override the lifetime policy to be
    9084             :       // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
    9085             :       // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
    9086             :       // specific domain. As BEHAVIOR_LIMIT_FOREIGN isn't visible in our UI,
    9087             :       // this is probably not an issue.
    9088           0 :       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
    9089           0 :       break;
    9090             :   }
    9091             : }
    9092             : 
    9093             : // static, private
    9094             : nsContentUtils::StorageAccess
    9095           0 : nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
    9096             :                                                    nsPIDOMWindowInner* aWindow)
    9097             : {
    9098           0 :   MOZ_ASSERT(aPrincipal);
    9099           0 :   MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
    9100             : 
    9101           0 :   StorageAccess access = StorageAccess::eAllow;
    9102             : 
    9103             :   // We don't allow storage on the null principal, in general. Even if the
    9104             :   // calling context is chrome.
    9105           0 :   if (aPrincipal->GetIsNullPrincipal()) {
    9106           0 :     return StorageAccess::eDeny;
    9107             :   }
    9108             : 
    9109           0 :   if (aWindow) {
    9110             :     // If the document is sandboxed, then it is not permitted to use storage
    9111           0 :     nsIDocument* document = aWindow->GetExtantDoc();
    9112           0 :     if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) {
    9113           0 :       return StorageAccess::eDeny;
    9114             :     }
    9115             : 
    9116             :     // Check if we are in private browsing, and record that fact
    9117           0 :     if (IsInPrivateBrowsing(document)) {
    9118           0 :       access = StorageAccess::ePrivateBrowsing;
    9119             :     }
    9120             :   }
    9121             : 
    9122             :   uint32_t lifetimePolicy;
    9123             :   uint32_t behavior;
    9124           0 :   GetCookieBehaviorForPrincipal(aPrincipal, &lifetimePolicy, &behavior);
    9125             : 
    9126             :   // Check if we should only allow storage for the session, and record that fact
    9127           0 :   if (lifetimePolicy == nsICookieService::ACCEPT_SESSION) {
    9128             :     // Storage could be StorageAccess::ePrivateBrowsing or StorageAccess::eAllow
    9129             :     // so perform a std::min comparison to make sure we preserve ePrivateBrowsing
    9130             :     // if it has been set.
    9131           0 :     access = std::min(StorageAccess::eSessionScoped, access);
    9132             :   }
    9133             : 
    9134             :   // About URIs are allowed to access storage, even if they don't have chrome
    9135             :   // privileges. If this is not desired, than the consumer will have to
    9136             :   // implement their own restriction functionality.
    9137             :   //
    9138             :   // This is due to backwards-compatibility and the state of storage access before
    9139             :   // the introducton of nsContentUtils::InternalStorageAllowedForPrincipal:
    9140             :   //
    9141             :   // BEFORE:
    9142             :   // localStorage, caches: allowed in 3rd-party iframes always
    9143             :   // IndexedDB: allowed in 3rd-party iframes only if 3rd party URI is an about:
    9144             :   //   URI within a specific whitelist
    9145             :   //
    9146             :   // AFTER:
    9147             :   // localStorage, caches: allowed in 3rd-party iframes by default. Preference
    9148             :   //   can be set to disable in 3rd-party, which will not disallow in about: URIs.
    9149             :   // IndexedDB: allowed in 3rd-party iframes by default. Preference can be set to
    9150             :   //   disable in 3rd-party, which will disallow in about: URIs, unless they are
    9151             :   //   within a specific whitelist.
    9152             :   //
    9153             :   // This means that behavior for storage with internal about: URIs should not be
    9154             :   // affected, which is desireable due to the lack of automated testing for about:
    9155             :   // URIs with these preferences set, and the importance of the correct functioning
    9156             :   // of these URIs even with custom preferences.
    9157           0 :   nsCOMPtr<nsIURI> uri;
    9158           0 :   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    9159           0 :   if (NS_SUCCEEDED(rv) && uri) {
    9160           0 :     bool isAbout = false;
    9161           0 :     MOZ_ALWAYS_SUCCEEDS(uri->SchemeIs("about", &isAbout));
    9162           0 :     if (isAbout) {
    9163           0 :       return access;
    9164             :     }
    9165             :   }
    9166             : 
    9167             :   // We don't want to prompt for every attempt to access permissions.
    9168           0 :   if (behavior == nsICookieService::BEHAVIOR_REJECT) {
    9169           0 :     return StorageAccess::eDeny;
    9170             :   }
    9171             : 
    9172             :   // In the absense of a window, we assume that we are first-party.
    9173           0 :   if (aWindow && (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
    9174           0 :                   behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN)) {
    9175             :     nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
    9176           0 :       do_GetService(THIRDPARTYUTIL_CONTRACTID);
    9177           0 :     MOZ_ASSERT(thirdPartyUtil);
    9178             : 
    9179           0 :     bool thirdPartyWindow = false;
    9180           0 :     if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow(
    9181           0 :           aWindow->GetOuterWindow(), nullptr, &thirdPartyWindow)) && thirdPartyWindow) {
    9182             :       // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
    9183             :       // simply rejecting the request to use the storage. In the future, if we
    9184             :       // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
    9185             :       // for non-cookie storage types, this may change.
    9186             : 
    9187           0 :       return StorageAccess::eDeny;
    9188             :     }
    9189             :   }
    9190             : 
    9191           0 :   return access;
    9192             : }
    9193             : 
    9194             : namespace {
    9195             : 
    9196             : // We put StringBuilder in the anonymous namespace to prevent anything outside
    9197             : // this file from accidentally being linked against it.
    9198             : 
    9199             : class StringBuilder
    9200             : {
    9201             : private:
    9202             :   // Try to keep the size of StringBuilder close to a jemalloc bucket size.
    9203             :   static const uint32_t STRING_BUFFER_UNITS = 1020;
    9204             :   class Unit
    9205             :   {
    9206             :   public:
    9207           0 :     Unit() : mAtom(nullptr), mType(eUnknown), mLength(0)
    9208             :     {
    9209           0 :       MOZ_COUNT_CTOR(StringBuilder::Unit);
    9210           0 :     }
    9211           0 :     ~Unit()
    9212           0 :     {
    9213           0 :       if (mType == eString || mType == eStringWithEncode) {
    9214           0 :         delete mString;
    9215             :       }
    9216           0 :       MOZ_COUNT_DTOR(StringBuilder::Unit);
    9217           0 :     }
    9218             : 
    9219             :     enum Type
    9220             :     {
    9221             :       eUnknown,
    9222             :       eAtom,
    9223             :       eString,
    9224             :       eStringWithEncode,
    9225             :       eLiteral,
    9226             :       eTextFragment,
    9227             :       eTextFragmentWithEncode,
    9228             :     };
    9229             : 
    9230             :     union
    9231             :     {
    9232             :       nsIAtom*              mAtom;
    9233             :       const char*           mLiteral;
    9234             :       nsAutoString*         mString;
    9235             :       const nsTextFragment* mTextFragment;
    9236             :     };
    9237             :     Type     mType;
    9238             :     uint32_t mLength;
    9239             :   };
    9240             : public:
    9241           0 :   StringBuilder() : mLast(this), mLength(0)
    9242             :   {
    9243           0 :     MOZ_COUNT_CTOR(StringBuilder);
    9244           0 :   }
    9245             : 
    9246           0 :   ~StringBuilder()
    9247           0 :   {
    9248           0 :     MOZ_COUNT_DTOR(StringBuilder);
    9249           0 :   }
    9250             : 
    9251           0 :   void Append(nsIAtom* aAtom)
    9252             :   {
    9253           0 :     Unit* u = AddUnit();
    9254           0 :     u->mAtom = aAtom;
    9255           0 :     u->mType = Unit::eAtom;
    9256           0 :     uint32_t len = aAtom->GetLength();
    9257           0 :     u->mLength = len;
    9258           0 :     mLength += len;
    9259           0 :   }
    9260             : 
    9261             :   template<int N>
    9262           0 :   void Append(const char (&aLiteral)[N])
    9263             :   {
    9264           0 :     Unit* u = AddUnit();
    9265           0 :     u->mLiteral = aLiteral;
    9266           0 :     u->mType = Unit::eLiteral;
    9267           0 :     uint32_t len = N - 1;
    9268           0 :     u->mLength = len;
    9269           0 :     mLength += len;
    9270           0 :   }
    9271             : 
    9272             :   template<int N>
    9273             :   void Append(char (&aLiteral)[N])
    9274             :   {
    9275             :     Unit* u = AddUnit();
    9276             :     u->mLiteral = aLiteral;
    9277             :     u->mType = Unit::eLiteral;
    9278             :     uint32_t len = N - 1;
    9279             :     u->mLength = len;
    9280             :     mLength += len;
    9281             :   }
    9282             : 
    9283           0 :   void Append(const nsAString& aString)
    9284             :   {
    9285           0 :     Unit* u = AddUnit();
    9286           0 :     u->mString = new nsAutoString(aString);
    9287           0 :     u->mType = Unit::eString;
    9288           0 :     uint32_t len = aString.Length();
    9289           0 :     u->mLength = len;
    9290           0 :     mLength += len;
    9291           0 :   }
    9292             : 
    9293           0 :   void Append(nsAutoString* aString)
    9294             :   {
    9295           0 :     Unit* u = AddUnit();
    9296           0 :     u->mString = aString;
    9297           0 :     u->mType = Unit::eString;
    9298           0 :     uint32_t len = aString->Length();
    9299           0 :     u->mLength = len;
    9300           0 :     mLength += len;
    9301           0 :   }
    9302             : 
    9303           0 :   void AppendWithAttrEncode(nsAutoString* aString, uint32_t aLen)
    9304             :   {
    9305           0 :     Unit* u = AddUnit();
    9306           0 :     u->mString = aString;
    9307           0 :     u->mType = Unit::eStringWithEncode;
    9308           0 :     u->mLength = aLen;
    9309           0 :     mLength += aLen;
    9310           0 :   }
    9311             : 
    9312           0 :   void Append(const nsTextFragment* aTextFragment)
    9313             :   {
    9314           0 :     Unit* u = AddUnit();
    9315           0 :     u->mTextFragment = aTextFragment;
    9316           0 :     u->mType = Unit::eTextFragment;
    9317           0 :     uint32_t len = aTextFragment->GetLength();
    9318           0 :     u->mLength = len;
    9319           0 :     mLength += len;
    9320           0 :   }
    9321             : 
    9322           0 :   void AppendWithEncode(const nsTextFragment* aTextFragment, uint32_t aLen)
    9323             :   {
    9324           0 :     Unit* u = AddUnit();
    9325           0 :     u->mTextFragment = aTextFragment;
    9326           0 :     u->mType = Unit::eTextFragmentWithEncode;
    9327           0 :     u->mLength = aLen;
    9328           0 :     mLength += aLen;
    9329           0 :   }
    9330             : 
    9331           0 :   bool ToString(nsAString& aOut)
    9332             :   {
    9333           0 :     if (!aOut.SetCapacity(mLength, fallible)) {
    9334           0 :       return false;
    9335             :     }
    9336             : 
    9337           0 :     for (StringBuilder* current = this; current; current = current->mNext) {
    9338           0 :       uint32_t len = current->mUnits.Length();
    9339           0 :       for (uint32_t i = 0; i < len; ++i) {
    9340           0 :         Unit& u = current->mUnits[i];
    9341           0 :         switch (u.mType) {
    9342             :           case Unit::eAtom:
    9343           0 :             aOut.Append(nsDependentAtomString(u.mAtom));
    9344           0 :             break;
    9345             :           case Unit::eString:
    9346           0 :             aOut.Append(*(u.mString));
    9347           0 :             break;
    9348             :           case Unit::eStringWithEncode:
    9349           0 :             EncodeAttrString(*(u.mString), aOut);
    9350           0 :             break;
    9351             :           case Unit::eLiteral:
    9352           0 :             aOut.AppendASCII(u.mLiteral, u.mLength);
    9353           0 :             break;
    9354             :           case Unit::eTextFragment:
    9355           0 :             u.mTextFragment->AppendTo(aOut);
    9356           0 :             break;
    9357             :           case Unit::eTextFragmentWithEncode:
    9358           0 :             EncodeTextFragment(u.mTextFragment, aOut);
    9359           0 :             break;
    9360             :           default:
    9361           0 :             MOZ_CRASH("Unknown unit type?");
    9362             :         }
    9363             :       }
    9364             :     }
    9365           0 :     return true;
    9366             :   }
    9367             : private:
    9368           0 :   Unit* AddUnit()
    9369             :   {
    9370           0 :     if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
    9371           0 :       new StringBuilder(this);
    9372             :     }
    9373           0 :     return mLast->mUnits.AppendElement();
    9374             :   }
    9375             : 
    9376           0 :   explicit StringBuilder(StringBuilder* aFirst)
    9377           0 :   : mLast(nullptr), mLength(0)
    9378             :   {
    9379           0 :     MOZ_COUNT_CTOR(StringBuilder);
    9380           0 :     aFirst->mLast->mNext = this;
    9381           0 :     aFirst->mLast = this;
    9382           0 :   }
    9383             : 
    9384           0 :   void EncodeAttrString(const nsAutoString& aValue, nsAString& aOut)
    9385             :   {
    9386           0 :     const char16_t* c = aValue.BeginReading();
    9387           0 :     const char16_t* end = aValue.EndReading();
    9388           0 :     while (c < end) {
    9389           0 :       switch (*c) {
    9390             :       case '"':
    9391           0 :         aOut.AppendLiteral("&quot;");
    9392           0 :         break;
    9393             :       case '&':
    9394           0 :         aOut.AppendLiteral("&amp;");
    9395           0 :         break;
    9396             :       case 0x00A0:
    9397           0 :         aOut.AppendLiteral("&nbsp;");
    9398           0 :         break;
    9399             :       default:
    9400           0 :         aOut.Append(*c);
    9401           0 :         break;
    9402             :       }
    9403           0 :       ++c;
    9404             :     }
    9405           0 :   }
    9406             : 
    9407           0 :   void EncodeTextFragment(const nsTextFragment* aValue, nsAString& aOut)
    9408             :   {
    9409           0 :     uint32_t len = aValue->GetLength();
    9410           0 :     if (aValue->Is2b()) {
    9411           0 :       const char16_t* data = aValue->Get2b();
    9412           0 :       for (uint32_t i = 0; i < len; ++i) {
    9413           0 :         const char16_t c = data[i];
    9414           0 :         switch (c) {
    9415             :           case '<':
    9416           0 :             aOut.AppendLiteral("&lt;");
    9417           0 :             break;
    9418             :           case '>':
    9419           0 :             aOut.AppendLiteral("&gt;");
    9420           0 :             break;
    9421             :           case '&':
    9422           0 :             aOut.AppendLiteral("&amp;");
    9423           0 :             break;
    9424             :           case 0x00A0:
    9425           0 :             aOut.AppendLiteral("&nbsp;");
    9426           0 :             break;
    9427             :           default:
    9428           0 :             aOut.Append(c);
    9429           0 :             break;
    9430             :         }
    9431             :       }
    9432             :     } else {
    9433           0 :       const char* data = aValue->Get1b();
    9434           0 :       for (uint32_t i = 0; i < len; ++i) {
    9435           0 :         const unsigned char c = data[i];
    9436           0 :         switch (c) {
    9437             :           case '<':
    9438           0 :             aOut.AppendLiteral("&lt;");
    9439           0 :             break;
    9440             :           case '>':
    9441           0 :             aOut.AppendLiteral("&gt;");
    9442           0 :             break;
    9443             :           case '&':
    9444           0 :             aOut.AppendLiteral("&amp;");
    9445           0 :             break;
    9446             :           case 0x00A0:
    9447           0 :             aOut.AppendLiteral("&nbsp;");
    9448           0 :             break;
    9449             :           default:
    9450           0 :             aOut.Append(c);
    9451           0 :             break;
    9452             :         }
    9453             :       }
    9454             :     }
    9455           0 :   }
    9456             : 
    9457             :   AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
    9458             :   nsAutoPtr<StringBuilder>                mNext;
    9459             :   StringBuilder*                          mLast;
    9460             :   // mLength is used only in the first StringBuilder object in the linked list.
    9461             :   uint32_t                                mLength;
    9462             : };
    9463             : 
    9464             : } // namespace
    9465             : 
    9466             : static void
    9467           0 : AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)
    9468             : {
    9469           0 :   uint32_t extraSpaceNeeded = 0;
    9470           0 :   uint32_t len = aText->GetLength();
    9471           0 :   if (aText->Is2b()) {
    9472           0 :     const char16_t* data = aText->Get2b();
    9473           0 :     for (uint32_t i = 0; i < len; ++i) {
    9474           0 :       const char16_t c = data[i];
    9475           0 :       switch (c) {
    9476             :         case '<':
    9477           0 :           extraSpaceNeeded += ArrayLength("&lt;") - 2;
    9478           0 :           break;
    9479             :         case '>':
    9480           0 :           extraSpaceNeeded += ArrayLength("&gt;") - 2;
    9481           0 :           break;
    9482             :         case '&':
    9483           0 :           extraSpaceNeeded += ArrayLength("&amp;") - 2;
    9484           0 :           break;
    9485             :         case 0x00A0:
    9486           0 :           extraSpaceNeeded += ArrayLength("&nbsp;") - 2;
    9487           0 :           break;
    9488             :         default:
    9489           0 :           break;
    9490             :       }
    9491             :     }
    9492             :   } else {
    9493           0 :     const char* data = aText->Get1b();
    9494           0 :     for (uint32_t i = 0; i < len; ++i) {
    9495           0 :       const unsigned char c = data[i];
    9496           0 :       switch (c) {
    9497             :         case '<':
    9498           0 :           extraSpaceNeeded += ArrayLength("&lt;") - 2;
    9499           0 :           break;
    9500             :         case '>':
    9501           0 :           extraSpaceNeeded += ArrayLength("&gt;") - 2;
    9502           0 :           break;
    9503             :         case '&':
    9504           0 :           extraSpaceNeeded += ArrayLength("&amp;") - 2;
    9505           0 :           break;
    9506             :         case 0x00A0:
    9507           0 :           extraSpaceNeeded += ArrayLength("&nbsp;") - 2;
    9508           0 :           break;
    9509             :         default:
    9510           0 :           break;
    9511             :       }
    9512             :     }
    9513             :   }
    9514             : 
    9515           0 :   if (extraSpaceNeeded) {
    9516           0 :     aBuilder.AppendWithEncode(aText, len + extraSpaceNeeded);
    9517             :   } else {
    9518           0 :     aBuilder.Append(aText);
    9519             :   }
    9520           0 : }
    9521             : 
    9522             : static void
    9523           0 : AppendEncodedAttributeValue(nsAutoString* aValue, StringBuilder& aBuilder)
    9524             : {
    9525           0 :   const char16_t* c = aValue->BeginReading();
    9526           0 :   const char16_t* end = aValue->EndReading();
    9527             : 
    9528           0 :   uint32_t extraSpaceNeeded = 0;
    9529           0 :   while (c < end) {
    9530           0 :     switch (*c) {
    9531             :       case '"':
    9532           0 :         extraSpaceNeeded += ArrayLength("&quot;") - 2;
    9533           0 :         break;
    9534             :       case '&':
    9535           0 :         extraSpaceNeeded += ArrayLength("&amp;") - 2;
    9536           0 :         break;
    9537             :       case 0x00A0:
    9538           0 :         extraSpaceNeeded += ArrayLength("&nbsp;") - 2;
    9539           0 :         break;
    9540             :       default:
    9541           0 :         break;
    9542             :     }
    9543           0 :     ++c;
    9544             :   }
    9545             : 
    9546           0 :   if (extraSpaceNeeded) {
    9547           0 :     aBuilder.AppendWithAttrEncode(aValue, aValue->Length() + extraSpaceNeeded);
    9548             :   } else {
    9549           0 :     aBuilder.Append(aValue);
    9550             :   }
    9551           0 : }
    9552             : 
    9553             : static void
    9554           0 : StartElement(Element* aContent, StringBuilder& aBuilder)
    9555             : {
    9556           0 :   nsIAtom* localName = aContent->NodeInfo()->NameAtom();
    9557           0 :   int32_t tagNS = aContent->GetNameSpaceID();
    9558             : 
    9559           0 :   aBuilder.Append("<");
    9560           0 :   if (aContent->IsHTMLElement() || aContent->IsSVGElement() ||
    9561           0 :       aContent->IsMathMLElement()) {
    9562           0 :     aBuilder.Append(localName);
    9563             :   } else {
    9564           0 :     aBuilder.Append(aContent->NodeName());
    9565             :   }
    9566             : 
    9567           0 :   int32_t count = aContent->GetAttrCount();
    9568           0 :   for (int32_t i = 0; i < count; i++) {
    9569           0 :     const nsAttrName* name = aContent->GetAttrNameAt(i);
    9570           0 :     int32_t attNs = name->NamespaceID();
    9571           0 :     nsIAtom* attName = name->LocalName();
    9572             : 
    9573             :     // Filter out any attribute starting with [-|_]moz
    9574           0 :     nsDependentAtomString attrNameStr(attName);
    9575           0 :     if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
    9576           0 :         StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
    9577           0 :       continue;
    9578             :     }
    9579             : 
    9580           0 :     auto* attValue = new nsAutoString();
    9581           0 :     aContent->GetAttr(attNs, attName, *attValue);
    9582             : 
    9583             :     // Filter out special case of <br type="_moz*"> used by the editor.
    9584             :     // Bug 16988.  Yuck.
    9585           0 :     if (localName == nsGkAtoms::br && tagNS == kNameSpaceID_XHTML &&
    9586           0 :         attName == nsGkAtoms::type && attNs == kNameSpaceID_None &&
    9587           0 :         StringBeginsWith(*attValue, NS_LITERAL_STRING("_moz"))) {
    9588           0 :       delete attValue;
    9589           0 :       continue;
    9590             :     }
    9591             : 
    9592           0 :     aBuilder.Append(" ");
    9593             : 
    9594           0 :     if (MOZ_LIKELY(attNs == kNameSpaceID_None) ||
    9595           0 :         (attNs == kNameSpaceID_XMLNS &&
    9596           0 :          attName == nsGkAtoms::xmlns)) {
    9597             :       // Nothing else required
    9598           0 :     } else if (attNs == kNameSpaceID_XML) {
    9599           0 :       aBuilder.Append("xml:");
    9600           0 :     } else if (attNs == kNameSpaceID_XMLNS) {
    9601           0 :       aBuilder.Append("xmlns:");
    9602           0 :     } else if (attNs == kNameSpaceID_XLink) {
    9603           0 :       aBuilder.Append("xlink:");
    9604             :     } else {
    9605           0 :       nsIAtom* prefix = name->GetPrefix();
    9606           0 :       if (prefix) {
    9607           0 :         aBuilder.Append(prefix);
    9608           0 :         aBuilder.Append(":");
    9609             :       }
    9610             :     }
    9611             : 
    9612           0 :     aBuilder.Append(attName);
    9613           0 :     aBuilder.Append(R"(=")");
    9614           0 :     AppendEncodedAttributeValue(attValue, aBuilder);
    9615           0 :     aBuilder.Append(R"(")");
    9616             :   }
    9617             : 
    9618           0 :   aBuilder.Append(">");
    9619             : 
    9620             :   /*
    9621             :   // Per HTML spec we should append one \n if the first child of
    9622             :   // pre/textarea/listing is a textnode and starts with a \n.
    9623             :   // But because browsers haven't traditionally had that behavior,
    9624             :   // we're not changing our behavior either - yet.
    9625             :   if (aContent->IsHTMLElement()) {
    9626             :     if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
    9627             :         localName == nsGkAtoms::listing) {
    9628             :       nsIContent* fc = aContent->GetFirstChild();
    9629             :       if (fc &&
    9630             :           (fc->NodeType() == nsIDOMNode::TEXT_NODE ||
    9631             :            fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
    9632             :         const nsTextFragment* text = fc->GetText();
    9633             :         if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
    9634             :           aBuilder.Append("\n");
    9635             :         }
    9636             :       }
    9637             :     }
    9638             :   }*/
    9639           0 : }
    9640             : 
    9641             : static inline bool
    9642           0 : ShouldEscape(nsIContent* aParent)
    9643             : {
    9644           0 :   if (!aParent || !aParent->IsHTMLElement()) {
    9645           0 :     return true;
    9646             :   }
    9647             : 
    9648             :   static const nsIAtom* nonEscapingElements[] = {
    9649             :     nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
    9650             :     nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
    9651             :     nsGkAtoms::plaintext,
    9652             :     // Per the current spec noscript should be escaped in case
    9653             :     // scripts are disabled or if document doesn't have
    9654             :     // browsing context. However the latter seems to be a spec bug
    9655             :     // and Gecko hasn't traditionally done the former.
    9656             :     nsGkAtoms::noscript
    9657           0 :   };
    9658           0 :   static mozilla::BloomFilter<12, nsIAtom> sFilter;
    9659             :   static bool sInitialized = false;
    9660           0 :   if (!sInitialized) {
    9661           0 :     sInitialized = true;
    9662           0 :     for (auto& nonEscapingElement : nonEscapingElements) {
    9663           0 :       sFilter.add(nonEscapingElement);
    9664             :     }
    9665             :   }
    9666             : 
    9667           0 :   nsIAtom* tag = aParent->NodeInfo()->NameAtom();
    9668           0 :   if (sFilter.mightContain(tag)) {
    9669           0 :     for (auto& nonEscapingElement : nonEscapingElements) {
    9670           0 :       if (tag == nonEscapingElement) {
    9671           0 :         return false;
    9672             :       }
    9673             :     }
    9674             :   }
    9675           0 :   return true;
    9676             : }
    9677             : 
    9678             : static inline bool
    9679           0 : IsVoidTag(Element* aElement)
    9680             : {
    9681           0 :   if (!aElement->IsHTMLElement()) {
    9682           0 :     return false;
    9683             :   }
    9684           0 :   return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
    9685             : }
    9686             : 
    9687             : bool
    9688           0 : nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
    9689             :                                       bool aDescendentsOnly,
    9690             :                                       nsAString& aOut)
    9691             : {
    9692             :   // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
    9693           0 :   MOZ_ASSERT(aDescendentsOnly ||
    9694             :              aRoot->NodeType() != nsIDOMNode::DOCUMENT_NODE);
    9695             : 
    9696           0 :   nsINode* current = aDescendentsOnly ?
    9697           0 :     nsNodeUtils::GetFirstChildOfTemplateOrNode(aRoot) : aRoot;
    9698             : 
    9699           0 :   if (!current) {
    9700           0 :     return true;
    9701             :   }
    9702             : 
    9703           0 :   StringBuilder builder;
    9704             :   nsIContent* next;
    9705             :   while (true) {
    9706           0 :     bool isVoid = false;
    9707           0 :     switch (current->NodeType()) {
    9708             :       case nsIDOMNode::ELEMENT_NODE: {
    9709           0 :         Element* elem = current->AsElement();
    9710           0 :         StartElement(elem, builder);
    9711           0 :         isVoid = IsVoidTag(elem);
    9712           0 :         if (!isVoid &&
    9713             :             (next = nsNodeUtils::GetFirstChildOfTemplateOrNode(current))) {
    9714           0 :           current = next;
    9715           0 :           continue;
    9716             :         }
    9717           0 :         break;
    9718             :       }
    9719             : 
    9720             :       case nsIDOMNode::TEXT_NODE:
    9721             :       case nsIDOMNode::CDATA_SECTION_NODE: {
    9722           0 :         const nsTextFragment* text = static_cast<nsIContent*>(current)->GetText();
    9723           0 :         nsIContent* parent = current->GetParent();
    9724           0 :         if (ShouldEscape(parent)) {
    9725           0 :           AppendEncodedCharacters(text, builder);
    9726             :         } else {
    9727           0 :           builder.Append(text);
    9728             :         }
    9729           0 :         break;
    9730             :       }
    9731             : 
    9732             :       case nsIDOMNode::COMMENT_NODE: {
    9733           0 :         builder.Append("<!--");
    9734           0 :         builder.Append(static_cast<nsIContent*>(current)->GetText());
    9735           0 :         builder.Append("-->");
    9736           0 :         break;
    9737             :       }
    9738             : 
    9739             :       case nsIDOMNode::DOCUMENT_TYPE_NODE: {
    9740           0 :         builder.Append("<!DOCTYPE ");
    9741           0 :         builder.Append(current->NodeName());
    9742           0 :         builder.Append(">");
    9743           0 :         break;
    9744             :       }
    9745             : 
    9746             :       case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: {
    9747           0 :         builder.Append("<?");
    9748           0 :         builder.Append(current->NodeName());
    9749           0 :         builder.Append(" ");
    9750           0 :         builder.Append(static_cast<nsIContent*>(current)->GetText());
    9751           0 :         builder.Append(">");
    9752           0 :         break;
    9753             :       }
    9754             :     }
    9755             : 
    9756             :     while (true) {
    9757           0 :       if (!isVoid && current->NodeType() == nsIDOMNode::ELEMENT_NODE) {
    9758           0 :         builder.Append("</");
    9759           0 :         nsIContent* elem = static_cast<nsIContent*>(current);
    9760           0 :         if (elem->IsHTMLElement() || elem->IsSVGElement() ||
    9761           0 :             elem->IsMathMLElement()) {
    9762           0 :           builder.Append(elem->NodeInfo()->NameAtom());
    9763             :         } else {
    9764           0 :           builder.Append(current->NodeName());
    9765             :         }
    9766           0 :         builder.Append(">");
    9767             :       }
    9768           0 :       isVoid = false;
    9769             : 
    9770           0 :       if (current == aRoot) {
    9771           0 :         return builder.ToString(aOut);
    9772             :       }
    9773             : 
    9774           0 :       if ((next = current->GetNextSibling())) {
    9775           0 :         current = next;
    9776           0 :         break;
    9777             :       }
    9778             : 
    9779           0 :       current = current->GetParentNode();
    9780             : 
    9781             :       // Handle template element. If the parent is a template's content,
    9782             :       // then adjust the parent to be the template element.
    9783           0 :       if (current != aRoot &&
    9784           0 :           current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    9785           0 :         DocumentFragment* frag = static_cast<DocumentFragment*>(current);
    9786           0 :         nsIContent* fragHost = frag->GetHost();
    9787           0 :         if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
    9788           0 :           current = fragHost;
    9789             :         }
    9790             :       }
    9791             : 
    9792           0 :       if (aDescendentsOnly && current == aRoot) {
    9793           0 :         return builder.ToString(aOut);
    9794             :       }
    9795           0 :     }
    9796           0 :   }
    9797             : }
    9798             : 
    9799             : bool
    9800           0 : nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri)
    9801             : {
    9802             :   // aUri must start with about: or this isn't the right function to be using.
    9803           0 :   MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
    9804             : 
    9805             :   // Make sure the global is a window
    9806           0 :   nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
    9807           0 :   if (!win) {
    9808           0 :     return false;
    9809             :   }
    9810             : 
    9811           0 :   nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
    9812           0 :   NS_ENSURE_TRUE(principal, false);
    9813           0 :   nsCOMPtr<nsIURI> uri;
    9814           0 :   principal->GetURI(getter_AddRefs(uri));
    9815           0 :   if (!uri) {
    9816           0 :     return false;
    9817             :   }
    9818             : 
    9819             :   // First check the scheme to avoid getting long specs in the common case.
    9820           0 :   bool isAbout = false;
    9821           0 :   uri->SchemeIs("about", &isAbout);
    9822           0 :   if (!isAbout) {
    9823           0 :     return false;
    9824             :   }
    9825             : 
    9826             :   // Now check the spec itself
    9827           0 :   nsAutoCString spec;
    9828           0 :   uri->GetSpecIgnoringRef(spec);
    9829           0 :   return spec.EqualsASCII(aUri);
    9830             : }
    9831             : 
    9832             : /* static */ void
    9833           1 : nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell, bool aVisible)
    9834             : {
    9835           2 :   nsCOMPtr<nsIScrollable> scroller = do_QueryInterface(aDocShell);
    9836             : 
    9837           1 :   if (scroller) {
    9838             :     int32_t prefValue;
    9839             : 
    9840           1 :     if (aVisible) {
    9841           1 :       prefValue = nsIScrollable::Scrollbar_Auto;
    9842             :     } else {
    9843           0 :       prefValue = nsIScrollable::Scrollbar_Never;
    9844             :     }
    9845             : 
    9846           1 :     scroller->SetDefaultScrollbarPreferences(
    9847           1 :                 nsIScrollable::ScrollOrientation_Y, prefValue);
    9848           1 :     scroller->SetDefaultScrollbarPreferences(
    9849           1 :                 nsIScrollable::ScrollOrientation_X, prefValue);
    9850             :   }
    9851           1 : }
    9852             : 
    9853             : /* static */ void
    9854           2 : nsContentUtils::GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl)
    9855             : {
    9856           2 :   MOZ_ASSERT(aDocShell);
    9857             : 
    9858             :   // Simulate receiver context for web platform test
    9859           2 :   if (Preferences::GetBool("dom.presentation.testing.simulate-receiver")) {
    9860           0 :     nsCOMPtr<nsIDocument> doc;
    9861             : 
    9862             :     nsCOMPtr<nsPIDOMWindowOuter> docShellWin =
    9863           0 :       do_QueryInterface(aDocShell->GetScriptGlobalObject());
    9864           0 :     if (docShellWin) {
    9865           0 :       doc = docShellWin->GetExtantDoc();
    9866             :     }
    9867             : 
    9868           0 :     if (NS_WARN_IF(!doc)) {
    9869           0 :       return;
    9870             :     }
    9871             : 
    9872           0 :     nsCOMPtr<nsIURI> uri = doc->GetDocumentURI();
    9873           0 :     if (NS_WARN_IF(!uri)) {
    9874           0 :       return;
    9875             :     }
    9876             : 
    9877           0 :     nsAutoCString uriStr;
    9878           0 :     uri->GetSpec(uriStr);
    9879           0 :     aPresentationUrl = NS_ConvertUTF8toUTF16(uriStr);
    9880           0 :     return;
    9881             :   }
    9882             : 
    9883           2 :   if (XRE_IsContentProcess()) {
    9884           0 :     nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
    9885           0 :     aDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
    9886           0 :     nsCOMPtr<nsIDocShellTreeItem> root;
    9887           0 :     aDocShell->GetRootTreeItem(getter_AddRefs(root));
    9888           0 :     if (sameTypeRoot.get() == root.get()) {
    9889             :       // presentation URL is stored in TabChild for the top most
    9890             :       // <iframe mozbrowser> in content process.
    9891           0 :       TabChild* tabChild = TabChild::GetFrom(aDocShell);
    9892           0 :       if (tabChild) {
    9893           0 :         aPresentationUrl = tabChild->PresentationURL();
    9894             :       }
    9895           0 :       return;
    9896             :     }
    9897             :   }
    9898             : 
    9899           3 :   nsCOMPtr<nsILoadContext> loadContext(do_QueryInterface(aDocShell));
    9900           3 :   nsCOMPtr<nsIDOMElement> topFrameElement;
    9901           2 :   loadContext->GetTopFrameElement(getter_AddRefs(topFrameElement));
    9902           2 :   if (!topFrameElement) {
    9903           1 :     return;
    9904             :   }
    9905             : 
    9906           1 :   topFrameElement->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
    9907             : }
    9908             : 
    9909             : /* static */ nsIDocShell*
    9910          87 : nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget)
    9911             : {
    9912         174 :   nsCOMPtr<nsPIDOMWindowInner> innerWindow;
    9913             : 
    9914         174 :   if (nsCOMPtr<nsINode> node = do_QueryInterface(aTarget)) {
    9915             :     bool ignore;
    9916             :     innerWindow =
    9917          29 :       do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
    9918          58 :   } else if ((innerWindow = do_QueryInterface(aTarget))) {
    9919             :     // Nothing else to do
    9920             :   } else {
    9921          80 :     nsCOMPtr<DOMEventTargetHelper> helper = do_QueryInterface(aTarget);
    9922          40 :     if (helper) {
    9923          40 :       innerWindow = helper->GetOwner();
    9924             :     }
    9925             :   }
    9926             : 
    9927          87 :   if (innerWindow) {
    9928          47 :     return innerWindow->GetDocShell();
    9929             :   }
    9930             : 
    9931          40 :   return nullptr;
    9932             : }
    9933             : 
    9934             : /*
    9935             :  * Note: this function only relates to figuring out HTTPS state, which is an
    9936             :  * input to the Secure Context algorithm.  We are not actually implementing any
    9937             :  * part of the Secure Context algorithm itself here.
    9938             :  *
    9939             :  * This is a bit of a hack.  Ideally we'd propagate HTTPS state through
    9940             :  * nsIChannel as described in the Fetch and HTML specs, but making channels
    9941             :  * know about whether they should inherit HTTPS state, propagating information
    9942             :  * about who the channel's "client" is, exposing GetHttpsState API on channels
    9943             :  * and modifying the various cache implementations to store and retrieve HTTPS
    9944             :  * state involves a huge amount of code (see bug 1220687).  We avoid that for
    9945             :  * now using this function.
    9946             :  *
    9947             :  * This function takes advantage of the observation that we can return true if
    9948             :  * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
    9949             :  * the document's origin (e.g. the origin has a scheme of 'https' or host
    9950             :  * 'localhost' etc.).  Since we generally propagate a creator document's origin
    9951             :  * onto data:, blob:, etc. documents, this works for them too.
    9952             :  *
    9953             :  * The scenario where this observation breaks down is sandboxing without the
    9954             :  * 'allow-same-origin' flag, since in this case a document is given a unique
    9955             :  * origin (IsOriginPotentiallyTrustworthy would return false).  We handle that
    9956             :  * by using the origin that the document would have had had it not been
    9957             :  * sandboxed.
    9958             :  *
    9959             :  * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
    9960             :  * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
    9961             :  * sandboxing is limited to the immediate sandbox.  In the case that aDocument
    9962             :  * should inherit its origin (e.g. data: URI) but its parent has ended up
    9963             :  * with a unique origin due to sandboxing further up the parent chain we may
    9964             :  * end up returning false when we would ideally return true (since we will
    9965             :  * examine the parent's origin for 'https' and not finding it.)  This means
    9966             :  * that we may restrict the privileges of some pages unnecessarily in this
    9967             :  * edge case.
    9968             :  */
    9969             : /* static */ bool
    9970           8 : nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
    9971             : {
    9972           8 :   if (!aDocument) {
    9973           0 :     return false;
    9974             :   }
    9975             : 
    9976          16 :   nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
    9977             : 
    9978           8 :   if (principal->GetIsSystemPrincipal()) {
    9979           0 :     return true;
    9980             :   }
    9981             : 
    9982             :   // If aDocument is sandboxed, try and get the principal that it would have
    9983             :   // been given had it not been sandboxed:
    9984          12 :   if (principal->GetIsNullPrincipal() &&
    9985           4 :       (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
    9986           0 :     nsIChannel* channel = aDocument->GetChannel();
    9987           0 :     if (channel) {
    9988             :       nsCOMPtr<nsIScriptSecurityManager> ssm =
    9989           0 :         nsContentUtils::GetSecurityManager();
    9990             :       nsresult rv =
    9991           0 :         ssm->GetChannelResultPrincipalIfNotSandboxed(channel,
    9992           0 :                                                      getter_AddRefs(principal));
    9993           0 :       if (NS_FAILED(rv)) {
    9994           0 :         return false;
    9995             :       }
    9996           0 :       if (principal->GetIsSystemPrincipal()) {
    9997             :         // If a document with the system principal is sandboxing a subdocument
    9998             :         // that would normally inherit the embedding element's principal (e.g.
    9999             :         // a srcdoc document) then the embedding document does not trust the
   10000             :         // content that is written to the embedded document.  Unlike when the
   10001             :         // embedding document is https, in this case we have no indication as
   10002             :         // to whether the embedded document's contents are delivered securely
   10003             :         // or not, and the sandboxing would possibly indicate that they were
   10004             :         // not.  To play it safe we return false here.  (See bug 1162772
   10005             :         // comment 73-80.)
   10006           0 :         return false;
   10007             :       }
   10008             :     }
   10009             :   }
   10010             : 
   10011           8 :   if (principal->GetIsNullPrincipal()) {
   10012           4 :     return false;
   10013             :   }
   10014             : 
   10015           4 :   MOZ_ASSERT(principal->GetIsCodebasePrincipal());
   10016             : 
   10017             :   nsCOMPtr<nsIContentSecurityManager> csm =
   10018           8 :     do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
   10019           4 :   NS_WARNING_ASSERTION(csm, "csm is null");
   10020           4 :   if (csm) {
   10021           4 :     bool isTrustworthyOrigin = false;
   10022           4 :     csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
   10023           4 :     if (isTrustworthyOrigin) {
   10024           4 :       return true;
   10025             :     }
   10026             :   }
   10027             : 
   10028           0 :   return false;
   10029             : }
   10030             : 
   10031             : /* static */ CustomElementDefinition*
   10032           0 : nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
   10033             :                                               const nsAString& aLocalName,
   10034             :                                               uint32_t aNameSpaceID,
   10035             :                                               const nsAString* aIs)
   10036             : {
   10037           0 :   MOZ_ASSERT(aDoc);
   10038             : 
   10039           0 :   if (aNameSpaceID != kNameSpaceID_XHTML ||
   10040           0 :       !aDoc->GetDocShell()) {
   10041           0 :     return nullptr;
   10042             :   }
   10043             : 
   10044           0 :   nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
   10045           0 :   if (!window) {
   10046           0 :     return nullptr;
   10047             :   }
   10048             : 
   10049           0 :   RefPtr<CustomElementRegistry> registry(window->CustomElements());
   10050           0 :   if (!registry) {
   10051           0 :     return nullptr;
   10052             :   }
   10053             : 
   10054           0 :   return registry->LookupCustomElementDefinition(aLocalName, aIs);
   10055             : }
   10056             : 
   10057             : /* static */ void
   10058           0 : nsContentUtils::SetupCustomElement(Element* aElement,
   10059             :                                    const nsAString* aTypeExtension)
   10060             : {
   10061           0 :   MOZ_ASSERT(aElement);
   10062             : 
   10063           0 :   nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
   10064             : 
   10065           0 :   if (!doc) {
   10066           0 :     return;
   10067             :   }
   10068             : 
   10069           0 :   if (aElement->GetNameSpaceID() != kNameSpaceID_XHTML ||
   10070           0 :       !doc->GetDocShell()) {
   10071           0 :     return;
   10072             :   }
   10073             : 
   10074           0 :   nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
   10075           0 :   if (!window) {
   10076           0 :     return;
   10077             :   }
   10078             : 
   10079           0 :   RefPtr<CustomElementRegistry> registry(window->CustomElements());
   10080           0 :   if (!registry) {
   10081           0 :     return;
   10082             :   }
   10083             : 
   10084           0 :   return registry->SetupCustomElement(aElement, aTypeExtension);
   10085             : }
   10086             : 
   10087             : /* static */ void
   10088           0 : nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
   10089             :                                          nsIDocument::ElementCallbackType aType,
   10090             :                                          Element* aCustomElement,
   10091             :                                          LifecycleCallbackArgs* aArgs,
   10092             :                                          CustomElementDefinition* aDefinition)
   10093             : {
   10094           0 :   MOZ_ASSERT(aDoc);
   10095             : 
   10096           0 :   if (!aDoc->GetDocShell()) {
   10097           0 :     return;
   10098             :   }
   10099             : 
   10100           0 :   nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
   10101           0 :   if (!window) {
   10102           0 :     return;
   10103             :   }
   10104             : 
   10105           0 :   RefPtr<CustomElementRegistry> registry(window->CustomElements());
   10106           0 :   if (!registry) {
   10107           0 :     return;
   10108             :   }
   10109             : 
   10110           0 :   registry->EnqueueLifecycleCallback(aType, aCustomElement, aArgs, aDefinition);
   10111             : }
   10112             : 
   10113             : /* static */ void
   10114           0 : nsContentUtils::GetCustomPrototype(nsIDocument* aDoc,
   10115             :                                    int32_t aNamespaceID,
   10116             :                                    nsIAtom* aAtom,
   10117             :                                    JS::MutableHandle<JSObject*> aPrototype)
   10118             : {
   10119           0 :   MOZ_ASSERT(aDoc);
   10120             : 
   10121           0 :   if (aNamespaceID != kNameSpaceID_XHTML ||
   10122           0 :       !aDoc->GetDocShell()) {
   10123           0 :     return;
   10124             :   }
   10125             : 
   10126           0 :   nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
   10127           0 :   if (!window) {
   10128           0 :     return;
   10129             :   }
   10130             : 
   10131           0 :   RefPtr<CustomElementRegistry> registry(window->CustomElements());
   10132           0 :   if (!registry) {
   10133           0 :     return;
   10134             :   }
   10135             : 
   10136           0 :   return registry->GetCustomPrototype(aAtom, aPrototype);
   10137             : }
   10138             : 
   10139             : /* static */ bool
   10140           0 : nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
   10141             : {
   10142           0 :   MOZ_ASSERT(aChannel);
   10143             : 
   10144           0 :   nsCOMPtr<nsILoadGroup> loadGroup;
   10145           0 :   nsresult rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
   10146           0 :   if (NS_WARN_IF(NS_FAILED(rv) || !loadGroup)) {
   10147           0 :     return false;
   10148             :   }
   10149             : 
   10150           0 :   nsCOMPtr<nsIInterfaceRequestor> callbacks;
   10151           0 :   rv = loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
   10152           0 :   if (NS_WARN_IF(NS_FAILED(rv) || !callbacks)) {
   10153           0 :     return false;
   10154             :   }
   10155             : 
   10156           0 :   nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
   10157           0 :   if (NS_WARN_IF(!loadContext)) {
   10158           0 :     return false;
   10159             :   }
   10160             : 
   10161           0 :   nsCOMPtr<mozIDOMWindowProxy> window;
   10162           0 :   rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
   10163           0 :   if (NS_WARN_IF(NS_FAILED(rv) || !window)) {
   10164           0 :     return false;
   10165             :   }
   10166             : 
   10167           0 :   nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(window);
   10168           0 :   if (NS_WARN_IF(!outer)) {
   10169           0 :     return false;
   10170             :   }
   10171             : 
   10172           0 :   if (!XRE_IsContentProcess()) {
   10173           0 :     outer->SetLargeAllocStatus(LargeAllocStatus::NON_E10S);
   10174           0 :     return false;
   10175             :   }
   10176             : 
   10177           0 :   nsIDocShell* docShell = outer->GetDocShell();
   10178           0 :   if (!docShell->GetIsOnlyToplevelInTabGroup()) {
   10179           0 :     outer->SetLargeAllocStatus(LargeAllocStatus::NOT_ONLY_TOPLEVEL_IN_TABGROUP);
   10180           0 :     return false;
   10181             :   }
   10182             : 
   10183             :   // Get the request method, and check if it is a GET request. If it is not GET,
   10184             :   // then we cannot perform a large allocation load.
   10185           0 :   nsAutoCString requestMethod;
   10186           0 :   rv = aChannel->GetRequestMethod(requestMethod);
   10187           0 :   NS_ENSURE_SUCCESS(rv, false);
   10188             : 
   10189           0 :   if (NS_WARN_IF(!requestMethod.LowerCaseEqualsLiteral("get"))) {
   10190           0 :     outer->SetLargeAllocStatus(LargeAllocStatus::NON_GET);
   10191           0 :     return false;
   10192             :   }
   10193             : 
   10194           0 :   TabChild* tabChild = TabChild::GetFrom(outer->AsOuter());
   10195           0 :   NS_ENSURE_TRUE(tabChild, false);
   10196             : 
   10197           0 :   if (tabChild->IsAwaitingLargeAlloc())  {
   10198           0 :     NS_WARNING("In a Large-Allocation TabChild, ignoring Large-Allocation header!");
   10199           0 :     tabChild->StopAwaitingLargeAlloc();
   10200           0 :     outer->SetLargeAllocStatus(LargeAllocStatus::SUCCESS);
   10201           0 :     return false;
   10202             :   }
   10203             : 
   10204             :   // On Win32 systems, we want to behave differently, so set the isWin32 bool to
   10205             :   // be true iff we are on win32.
   10206             : #if defined(XP_WIN) && defined(_X86_)
   10207             :   const bool isWin32 = true;
   10208             : #else
   10209           0 :   const bool isWin32 = false;
   10210             : #endif
   10211             : 
   10212             :   static bool sLargeAllocForceEnable = false;
   10213             :   static bool sCachedLargeAllocForceEnable = false;
   10214           0 :   if (!sCachedLargeAllocForceEnable) {
   10215           0 :     sCachedLargeAllocForceEnable = true;
   10216             :     mozilla::Preferences::AddBoolVarCache(&sLargeAllocForceEnable,
   10217           0 :                                           "dom.largeAllocation.forceEnable");
   10218             :   }
   10219             : 
   10220             :   // We want to enable the large allocation header on 32-bit windows machines,
   10221             :   // and disable it on other machines, while still printing diagnostic messages.
   10222             :   // dom.largeAllocation.forceEnable can allow you to enable the process
   10223             :   // switching behavior of the Large-Allocation header on non 32-bit windows
   10224             :   // machines.
   10225           0 :   bool largeAllocEnabled = isWin32 || sLargeAllocForceEnable;
   10226           0 :   if (!largeAllocEnabled) {
   10227             :     NS_WARNING("dom.largeAllocation.forceEnable not set - "
   10228           0 :                "ignoring otherwise successful Large-Allocation header.");
   10229             :     // On platforms which aren't WIN32, we don't activate the largeAllocation
   10230             :     // header, instead we simply emit diagnostics into the console.
   10231           0 :     outer->SetLargeAllocStatus(LargeAllocStatus::NON_WIN32);
   10232           0 :     return false;
   10233             :   }
   10234             : 
   10235             :   // At this point the fress process load should succeed! We just need to get
   10236             :   // ourselves a nsIWebBrowserChrome3 to ask to perform the reload. We should
   10237             :   // have one, as we have already confirmed that we are running in a content
   10238             :   // process.
   10239           0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   10240           0 :   docShell->GetTreeOwner(getter_AddRefs(treeOwner));
   10241           0 :   NS_ENSURE_TRUE(treeOwner, false);
   10242             : 
   10243           0 :   nsCOMPtr<nsIWebBrowserChrome3> wbc3 = do_GetInterface(treeOwner);
   10244           0 :   NS_ENSURE_TRUE(wbc3, false);
   10245             : 
   10246           0 :   nsCOMPtr<nsIURI> uri;
   10247           0 :   rv = aChannel->GetURI(getter_AddRefs(uri));
   10248           0 :   NS_ENSURE_SUCCESS(rv, false);
   10249           0 :   NS_ENSURE_TRUE(uri, false);
   10250             : 
   10251           0 :   nsCOMPtr<nsIURI> referrer;
   10252           0 :   rv = aChannel->GetReferrer(getter_AddRefs(referrer));
   10253           0 :   NS_ENSURE_SUCCESS(rv, false);
   10254             : 
   10255           0 :   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   10256           0 :   if (!loadInfo) {
   10257           0 :     return false;
   10258             :   }
   10259           0 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
   10260             : 
   10261             :   // Get the channel's load flags, and use them to generate nsIWebNavigation
   10262             :   // load flags. We want to make sure to propagate the refresh and cache busting
   10263             :   // flags.
   10264             :   nsLoadFlags channelLoadFlags;
   10265           0 :   aChannel->GetLoadFlags(&channelLoadFlags);
   10266             : 
   10267           0 :   uint32_t webnavLoadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
   10268           0 :   if (channelLoadFlags & nsIRequest::LOAD_BYPASS_CACHE) {
   10269           0 :     webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE;
   10270           0 :     webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
   10271           0 :   } else if (channelLoadFlags & nsIRequest::VALIDATE_ALWAYS) {
   10272           0 :     webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_IS_REFRESH;
   10273             :   }
   10274             : 
   10275             :   // Actually perform the cross process load
   10276           0 :   bool reloadSucceeded = false;
   10277           0 :   rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer,
   10278             :                                   triggeringPrincipal, webnavLoadFlags,
   10279           0 :                                   &reloadSucceeded);
   10280           0 :   NS_ENSURE_SUCCESS(rv, false);
   10281             : 
   10282           0 :   return reloadSucceeded;
   10283             : }
   10284             : 
   10285             : /* static */ void
   10286           0 : nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
   10287             :     nsIDocument* aDocument,
   10288             :     nsTArray<nsIContent*>& aElements)
   10289             : {
   10290           0 :   MOZ_ASSERT(aDocument);
   10291             : 
   10292           0 :   if (nsIPresShell* presShell = aDocument->GetShell()) {
   10293           0 :     if (nsIFrame* scrollFrame = presShell->GetRootScrollFrame()) {
   10294           0 :       nsIAnonymousContentCreator* creator = do_QueryFrame(scrollFrame);
   10295           0 :       MOZ_ASSERT(creator,
   10296             :                  "scroll frame should always implement nsIAnonymousContentCreator");
   10297           0 :       creator->AppendAnonymousContentTo(aElements, 0);
   10298             :     }
   10299             : 
   10300           0 :     if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
   10301           0 :       if (Element* container = canvasFrame->GetCustomContentContainer()) {
   10302           0 :         aElements.AppendElement(container);
   10303             :       }
   10304             :     }
   10305             :   }
   10306           0 : }
   10307             : 
   10308             : static void
   10309           0 : AppendNativeAnonymousChildrenFromFrame(
   10310             :     nsIFrame* aFrame,
   10311             :     nsTArray<nsIContent*>& aKids,
   10312             :     uint32_t aFlags)
   10313             : {
   10314           0 :   if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
   10315           0 :     ac->AppendAnonymousContentTo(aKids, aFlags);
   10316             :   }
   10317           0 : }
   10318             : 
   10319             : /* static */ void
   10320           0 : nsContentUtils::AppendNativeAnonymousChildren(
   10321             :     const nsIContent* aContent,
   10322             :     nsTArray<nsIContent*>& aKids,
   10323             :     uint32_t aFlags)
   10324             : {
   10325           0 :   if (aContent->MayHaveAnonymousChildren()) {
   10326           0 :     if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
   10327             :       // NAC created by the element's primary frame.
   10328           0 :       AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
   10329             : 
   10330             :       // NAC created by any other non-primary frames for the element.
   10331           0 :       AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
   10332           0 :       primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
   10333           0 :       for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
   10334           0 :         MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == aContent);
   10335           0 :         AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids, aFlags);
   10336             :       }
   10337             :     }
   10338             : 
   10339             :     // Get manually created NAC (editor resize handles, etc.).
   10340           0 :     if (auto nac = static_cast<ManualNAC*>(
   10341           0 :           aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
   10342           0 :       aKids.AppendElements(*nac);
   10343             :     }
   10344             :   }
   10345             : 
   10346             :   // The root scroll frame is not the primary frame of the root element.
   10347             :   // Detect and handle this case.
   10348           0 :   if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
   10349           0 :       aContent == aContent->OwnerDoc()->GetRootElement()) {
   10350           0 :     AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
   10351             :   }
   10352           0 : }
   10353             : 
   10354             : 
   10355             : /* static */ void
   10356           1 : nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode,
   10357             :                                                       nsIPrincipal** aLoadingPrincipal,
   10358             :                                                       nsContentPolicyType& aContentPolicyType)
   10359             : {
   10360             :   // Use the serialized loadingPrincipal from the image element. Fall back
   10361             :   // to mContent's principal (SystemPrincipal) if not available.
   10362           1 :   aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
   10363           2 :   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingNode->NodePrincipal();
   10364           2 :   nsAutoString imageLoadingPrincipal;
   10365             :   aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
   10366           1 :                         imageLoadingPrincipal);
   10367           1 :   if (!imageLoadingPrincipal.IsEmpty()) {
   10368           2 :     nsCOMPtr<nsISupports> serializedPrincipal;
   10369           2 :     NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal),
   10370           3 :                          getter_AddRefs(serializedPrincipal));
   10371           1 :     loadingPrincipal = do_QueryInterface(serializedPrincipal);
   10372             : 
   10373           1 :     if (loadingPrincipal) {
   10374             :       // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
   10375             :       // indicating it's a favicon loading.
   10376           1 :       aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
   10377             :     } else {
   10378             :       // Fallback if the deserialization is failed.
   10379           0 :       loadingPrincipal = aLoadingNode->NodePrincipal();
   10380             :     }
   10381             :   }
   10382           1 :   loadingPrincipal.forget(aLoadingPrincipal);
   10383           1 : }
   10384             : 
   10385             : /* static */ nsresult
   10386           1 : nsContentUtils::CreateJSValueFromSequenceOfObject(JSContext* aCx,
   10387             :                                                   const Sequence<JSObject*>& aTransfer,
   10388             :                                                   JS::MutableHandle<JS::Value> aValue)
   10389             : {
   10390           1 :   if (aTransfer.IsEmpty()) {
   10391           1 :     return NS_OK;
   10392             :   }
   10393             : 
   10394           0 :   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aTransfer.Length()));
   10395           0 :   if (!array) {
   10396           0 :     return NS_ERROR_OUT_OF_MEMORY;
   10397             :   }
   10398             : 
   10399           0 :   for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
   10400           0 :     JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
   10401           0 :     if (!object) {
   10402           0 :       continue;
   10403             :     }
   10404             : 
   10405           0 :     if (NS_WARN_IF(!JS_DefineElement(aCx, array, i, object,
   10406             :                                      JSPROP_ENUMERATE))) {
   10407           0 :       return NS_ERROR_OUT_OF_MEMORY;
   10408             :     }
   10409             :   }
   10410             : 
   10411           0 :   aValue.setObject(*array);
   10412           0 :   return NS_OK;
   10413             : }
   10414             : 
   10415             : /* static */ Element*
   10416          33 : nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement)
   10417             : {
   10418          33 :   MOZ_ASSERT(aElement);
   10419          33 :   MOZ_ASSERT(aElement->IsNativeAnonymous());
   10420             : 
   10421          33 :   Element* e = aElement;
   10422          99 :   while (e && e->IsNativeAnonymous()) {
   10423          33 :     e = e->GetParentElement();
   10424             :   }
   10425          33 :   return e;
   10426             : }
   10427             : 
   10428             : /**
   10429             :  * Checks whether the given type is a supported document type for
   10430             :  * loading within the nsObjectLoadingContent specified by aContent.
   10431             :  *
   10432             :  * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
   10433             :  * NOTE Does not take content policy or capabilities into account
   10434             :  */
   10435             : static bool
   10436           0 : HtmlObjectContentSupportsDocument(const nsCString& aMimeType,
   10437             :                                   nsIContent* aContent)
   10438             : {
   10439             :   nsCOMPtr<nsIWebNavigationInfo> info(
   10440           0 :     do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
   10441           0 :   if (!info) {
   10442           0 :     return false;
   10443             :   }
   10444             : 
   10445           0 :   nsCOMPtr<nsIWebNavigation> webNav;
   10446           0 :   if (aContent) {
   10447           0 :     nsIDocument* currentDoc = aContent->GetComposedDoc();
   10448           0 :     if (currentDoc) {
   10449           0 :       webNav = do_GetInterface(currentDoc->GetWindow());
   10450             :     }
   10451             :   }
   10452             : 
   10453             :   uint32_t supported;
   10454           0 :   nsresult rv = info->IsTypeSupported(aMimeType, webNav, &supported);
   10455             : 
   10456           0 :   if (NS_FAILED(rv)) {
   10457           0 :     return false;
   10458             :   }
   10459             : 
   10460           0 :   if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
   10461             :     // Don't want to support plugins as documents
   10462           0 :     return supported != nsIWebNavigationInfo::PLUGIN;
   10463             :   }
   10464             : 
   10465             :   // Try a stream converter
   10466             :   // NOTE: We treat any type we can convert from as a supported type. If a
   10467             :   // type is not actually supported, the URI loader will detect that and
   10468             :   // return an error, and we'll fallback.
   10469             :   nsCOMPtr<nsIStreamConverterService> convServ =
   10470           0 :     do_GetService("@mozilla.org/streamConverters;1");
   10471           0 :   bool canConvert = false;
   10472           0 :   if (convServ) {
   10473           0 :     rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
   10474             :   }
   10475           0 :   return NS_SUCCEEDED(rv) && canConvert;
   10476             : }
   10477             : 
   10478             : /* static */
   10479             : already_AddRefed<nsIPluginTag>
   10480           0 : nsContentUtils::PluginTagForType(const nsCString& aMIMEType, bool aNoFakePlugin)
   10481             : {
   10482           0 :   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
   10483           0 :   nsCOMPtr<nsIPluginTag> tag;
   10484           0 :   NS_ENSURE_TRUE(pluginHost, nullptr);
   10485             : 
   10486             :   // ShouldPlay will handle the case where the plugin is disabled
   10487           0 :   pluginHost->GetPluginTagForType(aMIMEType,
   10488             :                                   aNoFakePlugin ? nsPluginHost::eExcludeFake
   10489             :                                                 : nsPluginHost::eExcludeNone,
   10490           0 :                                   getter_AddRefs(tag));
   10491             : 
   10492           0 :   return tag.forget();
   10493             : }
   10494             : 
   10495             : /* static */ uint32_t
   10496           0 : nsContentUtils::HtmlObjectContentTypeForMIMEType(const nsCString& aMIMEType,
   10497             :                                                  bool aNoFakePlugin,
   10498             :                                                  nsIContent* aContent)
   10499             : {
   10500           0 :   if (aMIMEType.IsEmpty()) {
   10501           0 :     return nsIObjectLoadingContent::TYPE_NULL;
   10502             :   }
   10503             : 
   10504           0 :   if (imgLoader::SupportImageWithMimeType(aMIMEType.get())) {
   10505           0 :     return nsIObjectLoadingContent::TYPE_IMAGE;
   10506             :   }
   10507             : 
   10508             :   // Faking support of the PDF content as a document for EMBED tags
   10509             :   // when internal PDF viewer is enabled.
   10510           0 :   if (aMIMEType.LowerCaseEqualsLiteral("application/pdf") &&
   10511           0 :       IsPDFJSEnabled()) {
   10512           0 :     return nsIObjectLoadingContent::TYPE_DOCUMENT;
   10513             :   }
   10514             : 
   10515           0 :   if (HtmlObjectContentSupportsDocument(aMIMEType, aContent)) {
   10516           0 :     return nsIObjectLoadingContent::TYPE_DOCUMENT;
   10517             :   }
   10518             : 
   10519           0 :   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
   10520           0 :   if (pluginHost) {
   10521           0 :     nsCOMPtr<nsIPluginTag> tag = PluginTagForType(aMIMEType, aNoFakePlugin);
   10522           0 :     if (tag) {
   10523           0 :       if (!aNoFakePlugin &&
   10524           0 :           nsCOMPtr<nsIFakePluginTag>(do_QueryInterface(tag))) {
   10525           0 :         return nsIObjectLoadingContent::TYPE_FAKE_PLUGIN;
   10526             :       }
   10527             : 
   10528             :       // ShouldPlay will handle checking for disabled plugins
   10529           0 :       return nsIObjectLoadingContent::TYPE_PLUGIN;
   10530             :     }
   10531             :   }
   10532             : 
   10533           0 :   return nsIObjectLoadingContent::TYPE_NULL;
   10534             : }
   10535             : 
   10536             : /* static */ already_AddRefed<nsIEventTarget>
   10537        1252 : nsContentUtils::GetEventTargetByLoadInfo(nsILoadInfo* aLoadInfo, TaskCategory aCategory)
   10538             : {
   10539        1252 :   if (NS_WARN_IF(!aLoadInfo)) {
   10540           0 :     return nullptr;
   10541             :   }
   10542             : 
   10543        2504 :   nsCOMPtr<nsIDOMDocument> domDoc;
   10544        1252 :   aLoadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
   10545        2504 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   10546        2504 :   nsCOMPtr<nsIEventTarget> target;
   10547        1252 :   if (doc) {
   10548         105 :     if (DocGroup* group = doc->GetDocGroup()) {
   10549         105 :       target = group->EventTargetFor(aCategory);
   10550             :     }
   10551             :   } else {
   10552             :     // There's no document yet, but this might be a top-level load where we can
   10553             :     // find a TabGroup.
   10554             :     uint64_t outerWindowId;
   10555        1147 :     if (NS_FAILED(aLoadInfo->GetOuterWindowID(&outerWindowId))) {
   10556             :       // No window. This might be an add-on XHR, a service worker request, or
   10557             :       // something else.
   10558        1138 :       return nullptr;
   10559             :     }
   10560        1156 :     RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(outerWindowId);
   10561        1147 :     if (!window) {
   10562        1138 :       return nullptr;
   10563             :     }
   10564             : 
   10565           9 :     target = window->TabGroup()->EventTargetFor(aCategory);
   10566             :   }
   10567             : 
   10568         114 :   return target.forget();
   10569             : }
   10570             : 
   10571             : /* static */ bool
   10572          26 : nsContentUtils::IsLocalRefURL(const nsString& aString)
   10573             : {
   10574             :   // Find the first non-"C0 controls + space" character.
   10575          26 :   const char16_t* current = aString.get();
   10576          26 :   for (; *current != '\0'; current++) {
   10577          26 :     if (*current > 0x20) {
   10578             :       // if the first non-"C0 controls + space" character is '#', this is a
   10579             :       // local-ref URL.
   10580          26 :       return *current == '#';
   10581             :     }
   10582             :   }
   10583             : 
   10584           0 :   return false;
   10585             : }
   10586             : 
   10587             : // Tab ID is composed in a similar manner of Window ID.
   10588             : static uint64_t gNextTabId = 0;
   10589             : static const uint64_t kTabIdProcessBits = 32;
   10590             : static const uint64_t kTabIdTabBits = 64 - kTabIdProcessBits;
   10591             : 
   10592             : /* static */ uint64_t
   10593           1 : nsContentUtils::GenerateTabId()
   10594             : {
   10595           1 :   uint64_t processId = 0;
   10596           1 :   if (XRE_IsContentProcess()) {
   10597           0 :     ContentChild* cc = ContentChild::GetSingleton();
   10598           0 :     processId = cc->GetID();
   10599             :   }
   10600             : 
   10601           1 :   MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kTabIdProcessBits));
   10602           1 :   uint64_t processBits = processId & ((uint64_t(1) << kTabIdProcessBits) - 1);
   10603             : 
   10604           1 :   uint64_t tabId = ++gNextTabId;
   10605           1 :   MOZ_RELEASE_ASSERT(tabId < (uint64_t(1) << kTabIdTabBits));
   10606           1 :   uint64_t tabBits = tabId & ((uint64_t(1) << kTabIdTabBits) - 1);
   10607             : 
   10608           1 :   return (processBits << kTabIdTabBits) | tabBits;
   10609             : }
   10610             : 
   10611             : /* static */ bool
   10612           0 : nsContentUtils::GetUserIsInteracting()
   10613             : {
   10614           0 :   return UserInteractionObserver::sUserActive;
   10615             : }
   10616             : 
   10617             : /* static */ bool
   10618           2 : nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult)
   10619             : {
   10620           2 :   nsresult rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), aResult);
   10621           2 :   if (NS_FAILED(rv)) {
   10622           2 :     rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), aResult);
   10623             :   }
   10624           2 :   return NS_SUCCEEDED(rv);
   10625             : }
   10626             : 
   10627             : static const char* kUserInteractionInactive = "user-interaction-inactive";
   10628             : static const char* kUserInteractionActive = "user-interaction-active";
   10629             : 
   10630             : void
   10631           3 : nsContentUtils::UserInteractionObserver::Init()
   10632             : {
   10633             :   // Listen for the observer messages from EventStateManager which are telling
   10634             :   // us whether or not the user is interacting.
   10635           6 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   10636           3 :   obs->AddObserver(this, kUserInteractionInactive, false);
   10637           3 :   obs->AddObserver(this, kUserInteractionActive, false);
   10638             : 
   10639             :   // We can't register ourselves as an annotator yet, as the HangMonitor hasn't
   10640             :   // started yet. It will have started by the time we have the chance to spin
   10641             :   // the event loop.
   10642           6 :   RefPtr<UserInteractionObserver> self = this;
   10643           6 :   NS_DispatchToMainThread(
   10644           6 :     NS_NewRunnableFunction("nsContentUtils::UserInteractionObserver::Init",
   10645          15 :                            [=]() { HangMonitor::RegisterAnnotator(*self); }));
   10646           3 : }
   10647             : 
   10648             : void
   10649           0 : nsContentUtils::UserInteractionObserver::Shutdown()
   10650             : {
   10651           0 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   10652           0 :   if (obs) {
   10653           0 :     obs->RemoveObserver(this, kUserInteractionInactive);
   10654           0 :     obs->RemoveObserver(this, kUserInteractionActive);
   10655             :   }
   10656             : 
   10657           0 :   HangMonitor::UnregisterAnnotator(*this);
   10658           0 : }
   10659             : 
   10660             : /**
   10661             :  * NB: This function is always called by the HangMonitor thread.
   10662             :  *     Plan accordingly
   10663             :  */
   10664             : void
   10665           0 : nsContentUtils::UserInteractionObserver::AnnotateHang(HangMonitor::HangAnnotations& aAnnotations)
   10666             : {
   10667             :   // NOTE: Only annotate the hang report if the user is known to be interacting.
   10668           0 :   if (sUserActive) {
   10669           0 :     aAnnotations.AddAnnotation(NS_LITERAL_STRING("UserInteracting"), true);
   10670             :   }
   10671           0 : }
   10672             : 
   10673             : NS_IMETHODIMP
   10674           3 : nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
   10675             :                                                  const char* aTopic,
   10676             :                                                  const char16_t* aData)
   10677             : {
   10678           3 :   if (!strcmp(aTopic, kUserInteractionInactive)) {
   10679           2 :     sUserActive = false;
   10680           1 :   } else if (!strcmp(aTopic, kUserInteractionActive)) {
   10681           1 :     sUserActive = true;
   10682             :   } else {
   10683           0 :     NS_WARNING("Unexpected observer notification");
   10684             :   }
   10685           3 :   return NS_OK;
   10686             : }
   10687             : 
   10688             : Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
   10689          33 : NS_IMPL_ISUPPORTS(nsContentUtils::UserInteractionObserver, nsIObserver)
   10690             : 
   10691             : /* static */ bool
   10692           1 : nsContentUtils::IsOverridingWindowName(const nsAString& aName)
   10693             : {
   10694           1 :   return !aName.IsEmpty() &&
   10695           0 :     !aName.LowerCaseEqualsLiteral("_blank") &&
   10696           0 :     !aName.LowerCaseEqualsLiteral("_top") &&
   10697           1 :     !aName.LowerCaseEqualsLiteral("_parent") &&
   10698           1 :     !aName.LowerCaseEqualsLiteral("_self");
   10699             : }

Generated by: LCOV version 1.13