diff options
Diffstat (limited to 'dom/base/nsContentUtils.h')
-rw-r--r-- | dom/base/nsContentUtils.h | 2963 |
1 files changed, 2963 insertions, 0 deletions
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h new file mode 100644 index 000000000..278fbd008 --- /dev/null +++ b/dom/base/nsContentUtils.h @@ -0,0 +1,2963 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* A namespace class for static content utilities. */ + +#ifndef nsContentUtils_h___ +#define nsContentUtils_h___ + +#if defined(XP_WIN) +#include <float.h> +#endif + +#if defined(SOLARIS) +#include <ieeefp.h> +#endif + +#include "js/TypeDecls.h" +#include "js/Value.h" +#include "js/RootingAPI.h" +#include "mozilla/EventForwards.h" +#include "mozilla/GuardObjects.h" +#include "mozilla/TimeStamp.h" +#include "nsContentListDeclarations.h" +#include "nsMathUtils.h" +#include "nsTArrayForwardDeclare.h" +#include "Units.h" +#include "mozilla/dom/AutocompleteInfoBinding.h" +#include "mozilla/dom/BindingDeclarations.h" // For CallerType +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/FloatingPoint.h" +#include "mozilla/net/ReferrerPolicy.h" +#include "mozilla/Logging.h" +#include "mozilla/NotNull.h" +#include "nsIContentPolicy.h" +#include "nsIDocument.h" +#include "nsPIDOMWindow.h" + +#if defined(XP_WIN) +// Undefine LoadImage to prevent naming conflict with Windows. +#undef LoadImage +#endif + +class imgICache; +class imgIContainer; +class imgINotificationObserver; +class imgIRequest; +class imgLoader; +class imgRequestProxy; +class nsAutoScriptBlockerSuppressNodeRemoved; +class nsHtml5StringParser; +class nsIChannel; +class nsIConsoleService; +class nsIContent; +class nsIContentPolicy; +class nsIContentSecurityPolicy; +class nsIDocShellTreeItem; +class nsIDocumentLoaderFactory; +class nsIDOMDocument; +class nsIDOMDocumentFragment; +class nsIDOMEvent; +class nsIDOMHTMLInputElement; +class nsIDOMKeyEvent; +class nsIDOMNode; +class nsIDragSession; +class nsIEditor; +class nsIFragmentContentSink; +class nsIFrame; +class nsIImageLoadingContent; +class nsIInterfaceRequestor; +class nsIIOService; +class nsILineBreaker; +class nsILoadGroup; +class nsIMessageBroadcaster; +class nsNameSpaceManager; +class nsIObserver; +class nsIParser; +class nsIParserService; +class nsIPresShell; +class nsIPrincipal; +class nsIRequest; +class nsIRunnable; +class nsIScriptContext; +class nsIScriptSecurityManager; +class nsIStringBundle; +class nsIStringBundleService; +class nsISupportsHashKey; +class nsIURI; +class nsIUUIDGenerator; +class nsIWidget; +class nsIWordBreaker; +class nsIXPConnect; +class nsNodeInfoManager; +class nsPIDOMWindowInner; +class nsPIDOMWindowOuter; +class nsPresContext; +class nsStringBuffer; +class nsStringHashKey; +class nsTextFragment; +class nsView; +class nsViewportInfo; +class nsWrapperCache; +class nsAttrValue; +class nsITransferable; +class nsPIWindowRoot; +class nsIWindowProvider; + +struct JSRuntime; + +template<class E> class nsCOMArray; +template<class K, class V> class nsDataHashtable; +template<class K, class V> class nsRefPtrHashtable; +template<class T> class nsReadingIterator; + +namespace mozilla { +class ErrorResult; +class EventListenerManager; + +namespace dom { +struct CustomElementDefinition; +class DocumentFragment; +class Element; +class EventTarget; +class IPCDataTransfer; +class IPCDataTransferItem; +struct LifecycleCallbackArgs; +class NodeInfo; +class nsIContentChild; +class nsIContentParent; +class TabChild; +class Selection; +class TabParent; +} // namespace dom + +namespace ipc { +class Shmem; +class IShmemAllocator; +} + +namespace gfx { +class DataSourceSurface; +} // namespace gfx + +namespace layers { +class LayerManager; +} // namespace layers + +} // namespace mozilla + +class nsIBidiKeyboard; + +extern const char kLoadAsData[]; + +// Stolen from nsReadableUtils, but that's OK, since we can declare the same +// name multiple times. +const nsAFlatString& EmptyString(); +const nsAFlatCString& EmptyCString(); + +enum EventNameType { + EventNameType_None = 0x0000, + EventNameType_HTML = 0x0001, + EventNameType_XUL = 0x0002, + EventNameType_SVGGraphic = 0x0004, // svg graphic elements + EventNameType_SVGSVG = 0x0008, // the svg element + EventNameType_SMIL = 0x0010, // smil elements + EventNameType_HTMLBodyOrFramesetOnly = 0x0020, + + EventNameType_HTMLXUL = 0x0003, + EventNameType_All = 0xFFFF +}; + +struct EventNameMapping +{ + // This holds pointers to nsGkAtoms members, and is therefore safe as a + // non-owning reference. + nsIAtom* MOZ_NON_OWNING_REF mAtom; + int32_t mType; + mozilla::EventMessage mMessage; + mozilla::EventClassID mEventClassID; + // True if mAtom is possibly used by special SVG/SMIL events, but + // mMessage is eUnidentifiedEvent. See EventNameList.h + bool mMaybeSpecialSVGorSMILEvent; +}; + +typedef bool (*CallOnRemoteChildFunction) (mozilla::dom::TabParent* aTabParent, + void* aArg); + +class nsContentUtils +{ + friend class nsAutoScriptBlockerSuppressNodeRemoved; + typedef mozilla::dom::Element Element; + typedef mozilla::TimeDuration TimeDuration; + +public: + static nsresult Init(); + + static bool IsCallerChrome(); + static bool ThreadsafeIsCallerChrome(); + static bool IsCallerContentXBL(); + + // In the traditional Gecko architecture, both C++ code and untrusted JS code + // needed to rely on the same XPCOM method/getter/setter to get work done. + // This required lots of security checks in the various exposed methods, which + // in turn created difficulty in determining whether the caller was script + // (whose access needed to be checked) and internal C++ platform code (whose + // access did not need to be checked). To address this problem, Gecko had a + // convention whereby the absence of script on the stack was interpretted as + // "System Caller" and always granted unfettered access. + // + // Unfortunately, this created a bunch of footguns. For example, when the + // implementation of a DOM method wanted to perform a privileged + // sub-operation, it needed to "hide" the presence of script on the stack in + // order for that sub-operation to be allowed. Additionally, if script could + // trigger an API entry point to be invoked in some asynchronous way without + // script on the stack, it could potentially perform privilege escalation. + // + // In the modern world, untrusted script should interact with the platform + // exclusively over WebIDL APIs, and platform code has a lot more flexibility + // in deciding whether or not to use XPCOM. This gives us the flexibility to + // do something better. + // + // Going forward, APIs should be designed such that any security checks that + // ask the question "is my caller allowed to do this?" should live in WebIDL + // API entry points, with a separate method provided for internal callers + // that just want to get the job done. + // + // To enforce this and catch bugs, nsContentUtils::SubjectPrincipal will crash + // if it is invoked without script on the stack. To land that transition, it + // was necessary to go through and whitelist a bunch of callers that were + // depending on the old behavior. Those callers should be fixed up, and these + // methods should not be used by new code without review from bholley or bz. + static bool LegacyIsCallerNativeCode() { return !GetCurrentJSContext(); } + static bool LegacyIsCallerChromeOrNativeCode() { return LegacyIsCallerNativeCode() || IsCallerChrome(); } + static nsIPrincipal* SubjectPrincipalOrSystemIfNativeCaller() + { + if (!GetCurrentJSContext()) { + return GetSystemPrincipal(); + } + return SubjectPrincipal(); + } + + static bool LookupBindingMember(JSContext* aCx, nsIContent *aContent, + JS::Handle<jsid> aId, + JS::MutableHandle<JS::PropertyDescriptor> aDesc); + + // Check whether we should avoid leaking distinguishing information to JS/CSS. + static bool ShouldResistFingerprinting(nsIDocShell* aDocShell); + + /** + * Returns the parent node of aChild crossing document boundaries. + * Uses the parent node in the composed document. + */ + static nsINode* GetCrossDocParentNode(nsINode* aChild); + + /** + * Do not ever pass null pointers to this method. If one of your + * nsIContents is null, you have to decide for yourself what + * "IsDescendantOf" really means. + * + * @param aPossibleDescendant node to test for being a descendant of + * aPossibleAncestor + * @param aPossibleAncestor node to test for being an ancestor of + * aPossibleDescendant + * @return true if aPossibleDescendant is a descendant of + * aPossibleAncestor (or is aPossibleAncestor). false + * otherwise. + */ + static bool ContentIsDescendantOf(const nsINode* aPossibleDescendant, + const nsINode* aPossibleAncestor); + + /** + * Similar to ContentIsDescendantOf, except will treat an HTMLTemplateElement + * or ShadowRoot as an ancestor of things in the corresponding DocumentFragment. + * See the concept of "host-including inclusive ancestor" in the DOM + * specification. + */ + static bool ContentIsHostIncludingDescendantOf( + const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor); + + /** + * Similar to ContentIsDescendantOf except it crosses document boundaries, + * this function uses ancestor/descendant relations in the composed document + * (see shadow DOM spec). + */ + static bool ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant, + nsINode* aPossibleAncestor); + + /* + * This method fills the |aArray| with all ancestor nodes of |aNode| + * including |aNode| at the zero index. + */ + static nsresult GetAncestors(nsINode* aNode, + nsTArray<nsINode*>& aArray); + + /* + * This method fills |aAncestorNodes| with all ancestor nodes of |aNode| + * including |aNode| (QI'd to nsIContent) at the zero index. + * For each ancestor, there is a corresponding element in |aAncestorOffsets| + * which is the IndexOf the child in relation to its parent. + * + * This method just sucks. + */ + static nsresult GetAncestorsAndOffsets(nsIDOMNode* aNode, + int32_t aOffset, + nsTArray<nsIContent*>* aAncestorNodes, + nsTArray<int32_t>* aAncestorOffsets); + + /* + * The out parameter, |aCommonAncestor| will be the closest node, if any, + * to both |aNode| and |aOther| which is also an ancestor of each. + * Returns an error if the two nodes are disconnected and don't have + * a common ancestor. + */ + static nsresult GetCommonAncestor(nsIDOMNode *aNode, + nsIDOMNode *aOther, + nsIDOMNode** aCommonAncestor); + + /** + * Returns the common ancestor, if any, for two nodes. Returns null if the + * nodes are disconnected. + */ + static nsINode* GetCommonAncestor(nsINode* aNode1, + nsINode* aNode2); + + /** + * Returns true if aNode1 is before aNode2 in the same connected + * tree. + */ + static bool PositionIsBefore(nsINode* aNode1, nsINode* aNode2); + + /** + * Utility routine to compare two "points", where a point is a + * node/offset pair + * Returns -1 if point1 < point2, 1, if point1 > point2, + * 0 if error or if point1 == point2. + * NOTE! If the two nodes aren't in the same connected subtree, + * the result is 1, and the optional aDisconnected parameter + * is set to true. + */ + static int32_t ComparePoints(nsINode* aParent1, int32_t aOffset1, + nsINode* aParent2, int32_t aOffset2, + bool* aDisconnected = nullptr); + static int32_t ComparePoints(nsIDOMNode* aParent1, int32_t aOffset1, + nsIDOMNode* aParent2, int32_t aOffset2, + bool* aDisconnected = nullptr); + + /** + * Brute-force search of the element subtree rooted at aContent for + * an element with the given id. aId must be nonempty, otherwise + * this method may return nodes even if they have no id! + */ + static Element* MatchElementId(nsIContent *aContent, const nsAString& aId); + + /** + * Similar to above, but to be used if one already has an atom for the ID + */ + static Element* MatchElementId(nsIContent *aContent, const nsIAtom* aId); + + /** + * Reverses the document position flags passed in. + * + * @param aDocumentPosition The document position flags to be reversed. + * + * @return The reversed document position flags. + * + * @see nsIDOMNode + */ + static uint16_t ReverseDocumentPosition(uint16_t aDocumentPosition); + + /** + * Returns a subdocument for aDocument with a particular outer window ID. + * + * @param aDocument + * The document whose subdocuments will be searched. + * @param aOuterWindowID + * The outer window ID for the subdocument to be found. This must + * be a value greater than 0. + * @return nsIDocument* + * A pointer to the found nsIDocument. nullptr if the subdocument + * cannot be found, or if either aDocument or aOuterWindowId were + * invalid. If the outer window ID belongs to aDocument itself, this + * will return a pointer to aDocument. + */ + static nsIDocument* GetSubdocumentWithOuterWindowId(nsIDocument *aDocument, + uint64_t aOuterWindowId); + + static uint32_t CopyNewlineNormalizedUnicodeTo(const nsAString& aSource, + uint32_t aSrcOffset, + char16_t* aDest, + uint32_t aLength, + bool& aLastCharCR); + + static uint32_t CopyNewlineNormalizedUnicodeTo(nsReadingIterator<char16_t>& aSrcStart, const nsReadingIterator<char16_t>& aSrcEnd, nsAString& aDest); + + static const nsDependentSubstring TrimCharsInSet(const char* aSet, + const nsAString& aValue); + + template<bool IsWhitespace(char16_t)> + static const nsDependentSubstring TrimWhitespace(const nsAString& aStr, + bool aTrimTrailing = true); + + /** + * Returns true if aChar is of class Ps, Pi, Po, Pf, or Pe. + */ + static bool IsFirstLetterPunctuation(uint32_t aChar); + static bool IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, uint32_t aOffset); + + /** + * Returns true if aChar is of class Lu, Ll, Lt, Lm, Lo, Nd, Nl or No + */ + static bool IsAlphanumeric(uint32_t aChar); + static bool IsAlphanumericAt(const nsTextFragment* aFrag, uint32_t aOffset); + + /* + * Is the character an HTML whitespace character? + * + * We define whitespace using the list in HTML5 and css3-selectors: + * U+0009, U+000A, U+000C, U+000D, U+0020 + * + * HTML 4.01 also lists U+200B (zero-width space). + */ + static bool IsHTMLWhitespace(char16_t aChar); + + /* + * Returns whether the character is an HTML whitespace (see IsHTMLWhitespace) + * or a nbsp character (U+00A0). + */ + static bool IsHTMLWhitespaceOrNBSP(char16_t aChar); + + /** + * Is the HTML local name a block element? + */ + static bool IsHTMLBlock(nsIContent* aContent); + + enum ParseHTMLIntegerResultFlags { + eParseHTMLInteger_NoFlags = 0, + eParseHTMLInteger_IsPercent = 1 << 0, + // eParseHTMLInteger_NonStandard is set if the string representation of the + // integer was not the canonical one (e.g. had extra leading '+' or '0'). + eParseHTMLInteger_NonStandard = 1 << 1, + eParseHTMLInteger_DidNotConsumeAllInput = 1 << 2, + // Set if one or more error flags were set. + eParseHTMLInteger_Error = 1 << 3, + eParseHTMLInteger_ErrorNoValue = 1 << 4, + eParseHTMLInteger_ErrorOverflow = 1 << 5 + }; + static int32_t ParseHTMLInteger(const nsAString& aValue, + ParseHTMLIntegerResultFlags *aResult); + + /** + * Parse a margin string of format 'top, right, bottom, left' into + * an nsIntMargin. + * + * @param aString the string to parse + * @param aResult the resulting integer + * @return whether the value could be parsed + */ + static bool ParseIntMarginValue(const nsAString& aString, nsIntMargin& aResult); + + /** + * Parse the value of the <font size=""> attribute according to the HTML5 + * spec as of April 16, 2012. + * + * @param aValue the value to parse + * @return 1 to 7, or 0 if the value couldn't be parsed + */ + static int32_t ParseLegacyFontSize(const nsAString& aValue); + + static void Shutdown(); + + /** + * Checks whether two nodes come from the same origin. + */ + static nsresult CheckSameOrigin(const nsINode* aTrustedNode, + nsIDOMNode* aUnTrustedNode); + static nsresult CheckSameOrigin(const nsINode* aTrustedNode, + const nsINode* unTrustedNode); + + // Check if the (JS) caller can access aNode. + static bool CanCallerAccess(nsIDOMNode *aNode); + static bool CanCallerAccess(nsINode* aNode); + + // Check if the (JS) caller can access aWindow. + // aWindow can be either outer or inner window. + static bool CanCallerAccess(nsPIDOMWindowInner* aWindow); + + /** + * GetDocumentFromCaller gets its document by looking at the last called + * function and finding the document that the function itself relates to. + * For example, consider two windows A and B in the same origin. B has a + * function which does something that ends up needing the current document. + * If a script in window A were to call B's function, GetDocumentFromCaller + * would find that function (in B) and return B's document. + * + * @return The document or null if no JS Context. + */ + static nsIDocument* GetDocumentFromCaller(); + + // Check if a node is in the document prolog, i.e. before the document + // element. + static bool InProlog(nsINode *aNode); + + static nsIParserService* GetParserService(); + + static nsNameSpaceManager* NameSpaceManager() + { + return sNameSpaceManager; + } + + static nsIIOService* GetIOService() + { + return sIOService; + } + + static nsIBidiKeyboard* GetBidiKeyboard(); + + /** + * Get the cache security manager service. Can return null if the layout + * module has been shut down. + */ + static nsIScriptSecurityManager* GetSecurityManager() + { + return sSecurityManager; + } + + // Returns the subject principal. Guaranteed to return non-null. May only + // be called when nsContentUtils is initialized. + static nsIPrincipal* SubjectPrincipal(); + + // Returns the prinipal of the given JS object. This may only be called on + // the main thread for objects from the main thread's JSRuntime. + static nsIPrincipal* ObjectPrincipal(JSObject* aObj); + + static nsresult GenerateStateKey(nsIContent* aContent, + const nsIDocument* aDocument, + nsACString& aKey); + + /** + * Create a new nsIURI from aSpec, using aBaseURI as the base. The + * origin charset of the new nsIURI will be the document charset of + * aDocument. + */ + static nsresult NewURIWithDocumentCharset(nsIURI** aResult, + const nsAString& aSpec, + nsIDocument* aDocument, + nsIURI* aBaseURI); + + /** + * Convert aInput (in encoding aEncoding) to UTF16 in aOutput. + * + * @param aEncoding the Gecko-canonical name of the encoding or the empty + * string (meaning UTF-8) + */ + static nsresult ConvertStringFromEncoding(const nsACString& aEncoding, + const nsACString& aInput, + nsAString& aOutput); + + /** + * Determine whether a buffer begins with a BOM for UTF-8, UTF-16LE, + * UTF-16BE + * + * @param aBuffer the buffer to check + * @param aLength the length of the buffer + * @param aCharset empty if not found + * @return boolean indicating whether a BOM was detected. + */ + static bool CheckForBOM(const unsigned char* aBuffer, uint32_t aLength, + nsACString& aCharset); + + /** + * Returns true if |aName| is a valid name to be registered via + * document.registerElement. + */ + static bool IsCustomElementName(nsIAtom* aName); + + static nsresult CheckQName(const nsAString& aQualifiedName, + bool aNamespaceAware = true, + const char16_t** aColon = nullptr); + + static nsresult SplitQName(const nsIContent* aNamespaceResolver, + const nsAFlatString& aQName, + int32_t *aNamespace, nsIAtom **aLocalName); + + static nsresult GetNodeInfoFromQName(const nsAString& aNamespaceURI, + const nsAString& aQualifiedName, + nsNodeInfoManager* aNodeInfoManager, + uint16_t aNodeType, + mozilla::dom::NodeInfo** aNodeInfo); + + static void SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix, + nsIAtom **aTagName, int32_t *aNameSpaceID); + + // Get a permission-manager setting for the given principal and type. + // If the pref doesn't exist or if it isn't ALLOW_ACTION, false is + // returned, otherwise true is returned. Always returns true for the + // system principal, and false for a null principal. + static bool IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType); + + // Get a permission-manager setting for the given principal and type. + // If the pref doesn't exist or if it isn't DENY_ACTION, false is + // returned, otherwise true is returned. Always returns false for the + // system principal, and true for a null principal. + static bool IsSitePermDeny(nsIPrincipal* aPrincipal, const char* aType); + + // Get a permission-manager setting for the given principal and type. + // If the pref doesn't exist or if it isn't ALLOW_ACTION, false is + // returned, otherwise true is returned. Always returns true for the + // system principal, and false for a null principal. + // This version checks the permission for an exact host match on + // the principal + static bool IsExactSitePermAllow(nsIPrincipal* aPrincipal, const char* aType); + + // Get a permission-manager setting for the given principal and type. + // If the pref doesn't exist or if it isn't DENY_ACTION, false is + // returned, otherwise true is returned. Always returns false for the + // system principal, and true for a null principal. + // This version checks the permission for an exact host match on + // the principal + static bool IsExactSitePermDeny(nsIPrincipal* aPrincipal, const char* aType); + + // Returns true if aDoc1 and aDoc2 have equal NodePrincipal()s. + static bool HaveEqualPrincipals(nsIDocument* aDoc1, nsIDocument* aDoc2); + + static nsILineBreaker* LineBreaker() + { + return sLineBreaker; + } + + static nsIWordBreaker* WordBreaker() + { + return sWordBreaker; + } + + /** + * Regster aObserver as a shutdown observer. A strong reference is held + * to aObserver until UnregisterShutdownObserver is called. + */ + static void RegisterShutdownObserver(nsIObserver* aObserver); + static void UnregisterShutdownObserver(nsIObserver* aObserver); + + /** + * @return true if aContent has an attribute aName in namespace aNameSpaceID, + * and the attribute value is non-empty. + */ + static bool HasNonEmptyAttr(const nsIContent* aContent, int32_t aNameSpaceID, + nsIAtom* aName); + + /** + * Method that gets the primary presContext for the node. + * + * @param aContent The content node. + * @return the presContext, or nullptr if the content is not in a document + * (if GetCurrentDoc returns nullptr) + */ + static nsPresContext* GetContextForContent(const nsIContent* aContent); + + /** + * Method to do security and content policy checks on the image URI + * + * @param aURI uri of the image to be loaded + * @param aContext the context the image is loaded in (eg an element) + * @param aLoadingDocument the document we belong to + * @param aLoadingPrincipal the principal doing the load + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) + * The CP content type to use + * @param aImageBlockingStatus the nsIContentPolicy blocking status for this + * image. This will be set even if a security check fails for the + * image, to some reasonable REJECT_* value. This out param will only + * be set if it's non-null. + * @return true if the load can proceed, or false if it is blocked. + * Note that aImageBlockingStatus, if set will always be an ACCEPT + * status if true is returned and always be a REJECT_* status if + * false is returned. + */ + static bool CanLoadImage(nsIURI* aURI, + nsISupports* aContext, + nsIDocument* aLoadingDocument, + nsIPrincipal* aLoadingPrincipal, + int16_t* aImageBlockingStatus = nullptr, + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); + + /** + * Returns true if objects in aDocument shouldn't initiate image loads. + */ + static bool DocumentInactiveForImageLoads(nsIDocument* aDocument); + + /** + * Method to start an image load. This does not do any security checks. + * This method will attempt to make aURI immutable; a caller that wants to + * keep a mutable version around should pass in a clone. + * + * @param aURI uri of the image to be loaded + * @param aContext element of document where the result of this request + * will be used. + * @param aLoadingDocument the document we belong to + * @param aLoadingPrincipal the principal doing the load + * @param aReferrer the referrer URI + * @param aReferrerPolicy the referrer-sending policy to use on channel + * creation + * @param aObserver the observer for the image load + * @param aLoadFlags the load flags to use. See nsIRequest + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) + * The CP content type to use + * @return the imgIRequest for the image load + */ + static nsresult LoadImage(nsIURI* aURI, + nsINode* aContext, + nsIDocument* aLoadingDocument, + nsIPrincipal* aLoadingPrincipal, + nsIURI* aReferrer, + mozilla::net::ReferrerPolicy aReferrerPolicy, + imgINotificationObserver* aObserver, + int32_t aLoadFlags, + const nsAString& initiatorType, + imgRequestProxy** aRequest, + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); + + /** + * Obtain an image loader that respects the given document/channel's privacy status. + * Null document/channel arguments return the public image loader. + */ + static imgLoader* GetImgLoaderForDocument(nsIDocument* aDoc); + static imgLoader* GetImgLoaderForChannel(nsIChannel* aChannel, + nsIDocument* aContext); + + /** + * Returns whether the given URI is in the image cache. + */ + static bool IsImageInCache(nsIURI* aURI, nsIDocument* aDocument); + + /** + * Method to get an imgIContainer from an image loading content + * + * @param aContent The image loading content. Must not be null. + * @param aRequest The image request [out] + * @return the imgIContainer corresponding to the first frame of the image + */ + static already_AddRefed<imgIContainer> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nullptr); + + /** + * Helper method to call imgIRequest::GetStaticRequest. + */ + static already_AddRefed<imgRequestProxy> GetStaticRequest(imgRequestProxy* aRequest); + + /** + * Method that decides whether a content node is draggable + * + * @param aContent The content node to test. + * @return whether it's draggable + */ + static bool ContentIsDraggable(nsIContent* aContent); + + /** + * Method that decides whether a content node is a draggable image + * + * @param aContent The content node to test. + * @return whether it's a draggable image + */ + static bool IsDraggableImage(nsIContent* aContent); + + /** + * Method that decides whether a content node is a draggable link + * + * @param aContent The content node to test. + * @return whether it's a draggable link + */ + static bool IsDraggableLink(const nsIContent* aContent); + + /** + * Convenience method to create a new nodeinfo that differs only by name + * from aNodeInfo. + */ + static nsresult NameChanged(mozilla::dom::NodeInfo* aNodeInfo, nsIAtom* aName, + mozilla::dom::NodeInfo** aResult); + + /** + * Returns the appropriate event argument names for the specified + * namespace and event name. Added because we need to switch between + * SVG's "evt" and the rest of the world's "event", and because onerror + * on window takes 5 args. + */ + static void GetEventArgNames(int32_t aNameSpaceID, nsIAtom *aEventName, + bool aIsForWindow, + uint32_t *aArgCount, const char*** aArgNames); + + /** + * Returns origin attributes of the document. + **/ + static mozilla::PrincipalOriginAttributes + GetOriginAttributes(nsIDocument* aDoc); + + /** + * Returns origin attributes of the load group. + **/ + static mozilla::PrincipalOriginAttributes + GetOriginAttributes(nsILoadGroup* aLoadGroup); + + /** + * Returns true if this document is in a Private Browsing window. + */ + static bool IsInPrivateBrowsing(nsIDocument* aDoc); + + /** + * Returns true if this loadGroup uses Private Browsing. + */ + static bool IsInPrivateBrowsing(nsILoadGroup* aLoadGroup); + + /** + * If aNode is not an element, return true exactly when aContent's binding + * parent is null. + * + * If aNode is an element, return true exactly when aContent's binding parent + * is the same as aNode's. + * + * This method is particularly useful for callers who are trying to ensure + * that they are working with a non-anonymous descendant of a given node. If + * aContent is a descendant of aNode, a return value of false from this + * method means that it's an anonymous descendant from aNode's point of view. + * + * Both arguments to this method must be non-null. + */ + static bool IsInSameAnonymousTree(const nsINode* aNode, const nsIContent* aContent); + + /** + * Return the nsIXPConnect service. + */ + static nsIXPConnect *XPConnect() + { + return sXPConnect; + } + + /** + * Report simple error message to the browser console + * @param aErrorText the error message + * @param classification Name of the module reporting error + */ + static void LogSimpleConsoleError(const nsAString& aErrorText, + const char * classification); + + /** + * Report a non-localized error message to the error console. + * @param aErrorText the error message + * @param aErrorFlags See nsIScriptError. + * @param aCategory Name of module reporting error. + * @param aDocument Reference to the document which triggered the message. + * @param [aURI=nullptr] (Optional) URI of resource containing error. + * @param [aSourceLine=EmptyString()] (Optional) The text of the line that + contains the error (may be empty). + * @param [aLineNumber=0] (Optional) Line number within resource + containing error. + * @param [aColumnNumber=0] (Optional) Column number within resource + containing error. + If aURI is null, then aDocument->GetDocumentURI() is used. + * @param [aLocationMode] (Optional) Specifies the behavior if + error location information is omitted. + */ + enum MissingErrorLocationMode { + // Don't show location information in the error console. + eOMIT_LOCATION, + // Get location information from the currently executing script. + eUSE_CALLING_LOCATION + }; + static nsresult ReportToConsoleNonLocalized(const nsAString& aErrorText, + uint32_t aErrorFlags, + const nsACString& aCategory, + const nsIDocument* aDocument, + nsIURI* aURI = nullptr, + const nsAFlatString& aSourceLine + = EmptyString(), + uint32_t aLineNumber = 0, + uint32_t aColumnNumber = 0, + MissingErrorLocationMode aLocationMode + = eUSE_CALLING_LOCATION); + + /** + * Report a localized error message to the error console. + * @param aErrorFlags See nsIScriptError. + * @param aCategory Name of module reporting error. + * @param aDocument Reference to the document which triggered the message. + * @param aFile Properties file containing localized message. + * @param aMessageName Name of localized message. + * @param [aParams=nullptr] (Optional) Parameters to be substituted into + localized message. + * @param [aParamsLength=0] (Optional) Length of aParams. + * @param [aURI=nullptr] (Optional) URI of resource containing error. + * @param [aSourceLine=EmptyString()] (Optional) The text of the line that + contains the error (may be empty). + * @param [aLineNumber=0] (Optional) Line number within resource + containing error. + * @param [aColumnNumber=0] (Optional) Column number within resource + containing error. + If aURI is null, then aDocument->GetDocumentURI() is used. + */ + enum PropertiesFile { + eCSS_PROPERTIES, + eXBL_PROPERTIES, + eXUL_PROPERTIES, + eLAYOUT_PROPERTIES, + eFORMS_PROPERTIES, + ePRINTING_PROPERTIES, + eDOM_PROPERTIES, + eHTMLPARSER_PROPERTIES, + eSVG_PROPERTIES, + eBRAND_PROPERTIES, + eCOMMON_DIALOG_PROPERTIES, + eMATHML_PROPERTIES, + eSECURITY_PROPERTIES, + eNECKO_PROPERTIES, + PropertiesFile_COUNT + }; + static nsresult ReportToConsole(uint32_t aErrorFlags, + const nsACString& aCategory, + const nsIDocument* aDocument, + PropertiesFile aFile, + const char *aMessageName, + const char16_t **aParams = nullptr, + uint32_t aParamsLength = 0, + nsIURI* aURI = nullptr, + const nsAFlatString& aSourceLine + = EmptyString(), + uint32_t aLineNumber = 0, + uint32_t aColumnNumber = 0); + + static void LogMessageToConsole(const char* aMsg); + + /** + * Get the localized string named |aKey| in properties file |aFile|. + */ + static nsresult GetLocalizedString(PropertiesFile aFile, + const char* aKey, + nsXPIDLString& aResult); + + /** + * A helper function that parses a sandbox attribute (of an <iframe> or a CSP + * directive) and converts it to the set of flags used internally. + * + * @param aSandboxAttr the sandbox attribute + * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is + * null) + */ + static uint32_t ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr); + + /** + * A helper function that checks if a string matches a valid sandbox flag. + * + * @param aFlag the potential sandbox flag. + * @return true if the flag is a sandbox flag. + */ + static bool IsValidSandboxFlag(const nsAString& aFlag); + + /** + * A helper function that returns a string attribute corresponding to the + * sandbox flags. + * + * @param aFlags the sandbox flags + * @param aString the attribute corresponding to the flags (null if aFlags + * is zero) + */ + static void SandboxFlagsToString(uint32_t aFlags, nsAString& aString); + + /** + * Helper function that generates a UUID. + */ + static nsresult GenerateUUIDInPlace(nsID& aUUID); + + static bool PrefetchEnabled(nsIDocShell* aDocShell); + + /** + * Fill (with the parameters given) the localized string named |aKey| in + * properties file |aFile|. + */ +private: + static nsresult FormatLocalizedString(PropertiesFile aFile, + const char* aKey, + const char16_t** aParams, + uint32_t aParamsLength, + nsXPIDLString& aResult); + +public: + template<uint32_t N> + static nsresult FormatLocalizedString(PropertiesFile aFile, + const char* aKey, + const char16_t* (&aParams)[N], + nsXPIDLString& aResult) + { + return FormatLocalizedString(aFile, aKey, aParams, N, aResult); + } + + /** + * Fill (with the parameters given) the localized string named |aKey| in + * properties file |aFile| consuming an nsTArray of nsString parameters rather + * than a char16_t** for the sake of avoiding use-after-free errors involving + * temporaries. + */ + static nsresult FormatLocalizedString(PropertiesFile aFile, + const char* aKey, + const nsTArray<nsString>& aParamArray, + nsXPIDLString& aResult); + + /** + * Returns true if aDocument is a chrome document + */ + static bool IsChromeDoc(nsIDocument *aDocument); + + /** + * Returns true if aDocument is in a docshell whose parent is the same type + */ + static bool IsChildOfSameType(nsIDocument* aDoc); + + /** + '* Returns true if the content-type is any of the supported script types. + */ + static bool IsScriptType(const nsACString& aContentType); + + /** + '* Returns true if the content-type will be rendered as plain-text. + */ + static bool IsPlainTextType(const nsACString& aContentType); + + /** + * Get the script file name to use when compiling the script + * referenced by aURI. In cases where there's no need for any extra + * security wrapper automation the script file name that's returned + * will be the spec in aURI, else it will be the spec in aDocument's + * URI followed by aURI's spec, separated by " -> ". Returns true + * if the script file name was modified, false if it's aURI's + * spec. + */ + static bool GetWrapperSafeScriptFilename(nsIDocument *aDocument, + nsIURI *aURI, + nsACString& aScriptURI, + nsresult* aRv); + + + /** + * Returns true if aDocument belongs to a chrome docshell for + * display purposes. Returns false for null documents or documents + * which do not belong to a docshell. + */ + static bool IsInChromeDocshell(nsIDocument *aDocument); + + /** + * Return the content policy service + */ + static nsIContentPolicy *GetContentPolicy(); + + /** + * Map internal content policy types to external ones. + */ + static nsContentPolicyType InternalContentPolicyTypeToExternal(nsContentPolicyType aType); + + /** + * Map internal content policy types to external ones or preload types: + * * TYPE_INTERNAL_SCRIPT_PRELOAD + * * TYPE_INTERNAL_IMAGE_PRELOAD + * * TYPE_INTERNAL_STYLESHEET_PRELOAD + * + * Note: DO NOT call this function unless you know what you're doing! + */ + static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType); + + /** + * Map internal content policy types to external ones, worker, or preload types: + * * TYPE_INTERNAL_WORKER + * * TYPE_INTERNAL_SHARED_WORKER + * * TYPE_INTERNAL_SERVICE_WORKER + * + * Note: DO NOT call this function unless you know what you're doing! + */ + static nsContentPolicyType InternalContentPolicyTypeToExternalOrWorker(nsContentPolicyType aType); + + /** + * Returns true if the content policy type is any of: + * * TYPE_INTERNAL_SCRIPT_PRELOAD + * * TYPE_INTERNAL_IMAGE_PRELOAD + * * TYPE_INTERNAL_STYLESHEET_PRELOAD + */ + static bool IsPreloadType(nsContentPolicyType aType); + + /** + * Quick helper to determine whether there are any mutation listeners + * of a given type that apply to this content or any of its ancestors. + * The method has the side effect to call document's MayDispatchMutationEvent + * using aTargetForSubtreeModified as the parameter. + * + * @param aNode The node to search for listeners + * @param aType The type of listener (NS_EVENT_BITS_MUTATION_*) + * @param aTargetForSubtreeModified The node which is the target of the + * possible DOMSubtreeModified event. + * + * @return true if there are mutation listeners of the specified type + */ + static bool HasMutationListeners(nsINode* aNode, + uint32_t aType, + nsINode* aTargetForSubtreeModified); + + /** + * Quick helper to determine whether there are any mutation listeners + * of a given type that apply to any content in this document. It is valid + * to pass null for aDocument here, in which case this function always + * returns true. + * + * @param aDocument The document to search for listeners + * @param aType The type of listener (NS_EVENT_BITS_MUTATION_*) + * + * @return true if there are mutation listeners of the specified type + */ + static bool HasMutationListeners(nsIDocument* aDocument, + uint32_t aType); + /** + * Synchronously fire DOMNodeRemoved on aChild. Only fires the event if + * there really are listeners by checking using the HasMutationListeners + * function above. The function makes sure to hold the relevant objects alive + * for the duration of the event firing. However there are no guarantees + * that any of the objects are alive by the time the function returns. + * If you depend on that you need to hold references yourself. + * + * @param aChild The node to fire DOMNodeRemoved at. + * @param aParent The parent of aChild. + * @param aOwnerDoc The ownerDocument of aChild. + */ + static void MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent, + nsIDocument* aOwnerDoc); + + /** + * This method creates and dispatches a trusted event. + * Works only with events which can be created by calling + * nsIDOMDocument::CreateEvent() with parameter "Events". + * @param aDoc The document which will be used to create the event. + * @param aTarget The target of the event, should be QIable to + * nsIDOMEventTarget. + * @param aEventName The name of the event. + * @param aCanBubble Whether the event can bubble. + * @param aCancelable Is the event cancelable. + * @param aDefaultAction Set to true if default action should be taken, + * see nsIDOMEventTarget::DispatchEvent. + */ + static nsresult DispatchTrustedEvent(nsIDocument* aDoc, + nsISupports* aTarget, + const nsAString& aEventName, + bool aCanBubble, + bool aCancelable, + bool *aDefaultAction = nullptr); + + /** + * This method creates and dispatches a untrusted event. + * Works only with events which can be created by calling + * nsIDOMDocument::CreateEvent() with parameter "Events". + * @param aDoc The document which will be used to create the event. + * @param aTarget The target of the event, should be QIable to + * nsIDOMEventTarget. + * @param aEventName The name of the event. + * @param aCanBubble Whether the event can bubble. + * @param aCancelable Is the event cancelable. + * @param aDefaultAction Set to true if default action should be taken, + * see nsIDOMEventTarget::DispatchEvent. + */ + static nsresult DispatchUntrustedEvent(nsIDocument* aDoc, + nsISupports* aTarget, + const nsAString& aEventName, + bool aCanBubble, + bool aCancelable, + bool *aDefaultAction = nullptr); + + /** + * This method creates and dispatches a trusted event to the chrome + * event handler (the parent object of the DOM Window in the event target + * chain). Note, chrome event handler is used even if aTarget is a chrome + * object. Use DispatchEventOnlyToChrome if the normal event dispatching is + * wanted in case aTarget is a chrome object. + * Works only with events which can be created by calling + * nsIDOMDocument::CreateEvent() with parameter "Events". + * @param aDocument The document which will be used to create the event, + * and whose window's chrome handler will be used to + * dispatch the event. + * @param aTarget The target of the event, used for event->SetTarget() + * @param aEventName The name of the event. + * @param aCanBubble Whether the event can bubble. + * @param aCancelable Is the event cancelable. + * @param aDefaultAction Set to true if default action should be taken, + * see nsIDOMEventTarget::DispatchEvent. + */ + static nsresult DispatchChromeEvent(nsIDocument* aDoc, + nsISupports* aTarget, + const nsAString& aEventName, + bool aCanBubble, + bool aCancelable, + bool *aDefaultAction = nullptr); + + /** + * Helper function for dispatching a "DOMServiceWorkerFocusClient" event to + * the chrome event handler of the given DOM Window. This has the effect + * of focusing the corresponding tab and bringing the browser window + * to the foreground. + */ + static nsresult DispatchFocusChromeEvent(nsPIDOMWindowOuter* aWindow); + + /** + * This method creates and dispatches a trusted event. + * If aTarget is not a chrome object, the nearest chrome object in the + * propagation path will be used as the start of the event target chain. + * This method is different than DispatchChromeEvent, which always dispatches + * events to chrome event handler. DispatchEventOnlyToChrome works like + * DispatchTrustedEvent in the case aTarget is a chrome object. + * Works only with events which can be created by calling + * nsIDOMDocument::CreateEvent() with parameter "Events". + * @param aDoc The document which will be used to create the event. + * @param aTarget The target of the event, should be QIable to + * nsIDOMEventTarget. + * @param aEventName The name of the event. + * @param aCanBubble Whether the event can bubble. + * @param aCancelable Is the event cancelable. + * @param aDefaultAction Set to true if default action should be taken, + * see nsIDOMEventTarget::DispatchEvent. + */ + static nsresult DispatchEventOnlyToChrome(nsIDocument* aDoc, + nsISupports* aTarget, + const nsAString& aEventName, + bool aCanBubble, + bool aCancelable, + bool *aDefaultAction = nullptr); + + /** + * Determines if an event attribute name (such as onclick) is valid for + * a given element type. Types are from the EventNameType enumeration + * defined above. + * + * @param aName the event name to look up + * @param aType the type of content + */ + static bool IsEventAttributeName(nsIAtom* aName, int32_t aType); + + /** + * Return the event message for the event with the given name. The name is + * the event name with the 'on' prefix. Returns eUnidentifiedEvent if the + * event doesn't match a known event name. + * + * @param aName the event name to look up + */ + static mozilla::EventMessage GetEventMessage(nsIAtom* aName); + + /** + * Returns the EventMessage and nsIAtom to be used for event listener + * registration. + */ + static mozilla::EventMessage + GetEventMessageAndAtomForListener(const nsAString& aName, nsIAtom** aOnName); + + /** + * Return the EventClassID for the event with the given name. The name is the + * event name *without* the 'on' prefix. Returns eBasicEventClass if the event + * is not known to be of any particular event class. + * + * @param aName the event name to look up + */ + static mozilla::EventClassID GetEventClassID(const nsAString& aName); + + /** + * Return the event message and atom for the event with the given name. + * The name is the event name *without* the 'on' prefix. + * Returns eUnidentifiedEvent on the aEventID if the + * event doesn't match a known event name in the category. + * + * @param aName the event name to look up + * @param aEventClassID only return event id for aEventClassID + */ + static nsIAtom* GetEventMessageAndAtom(const nsAString& aName, + mozilla::EventClassID aEventClassID, + mozilla::EventMessage* aEventMessage); + + /** + * Used only during traversal of the XPCOM graph by the cycle + * collector: push a pointer to the listener manager onto the + * children deque, if it exists. Do nothing if there is no listener + * manager. + * + * Crucially: does not perform any refcounting operations. + * + * @param aNode The node to traverse. + * @param children The buffer to push a listener manager pointer into. + */ + static void TraverseListenerManager(nsINode *aNode, + nsCycleCollectionTraversalCallback &cb); + + /** + * Get the eventlistener manager for aNode, creating it if it does not + * already exist. + * + * @param aNode The node for which to get the eventlistener manager. + */ + static mozilla::EventListenerManager* + GetListenerManagerForNode(nsINode* aNode); + /** + * Get the eventlistener manager for aNode, returning null if it does not + * already exist. + * + * @param aNode The node for which to get the eventlistener manager. + */ + static mozilla::EventListenerManager* + GetExistingListenerManagerForNode(const nsINode* aNode); + + static void UnmarkGrayJSListenersInCCGenerationDocuments(); + + /** + * Remove the eventlistener manager for aNode. + * + * @param aNode The node for which to remove the eventlistener manager. + */ + static void RemoveListenerManager(nsINode *aNode); + + static bool IsInitialized() + { + return sInitialized; + } + + /** + * Checks if the localname/prefix/namespace triple is valid wrt prefix + * and namespace according to the Namespaces in XML and DOM Code + * specfications. + * + * @param aLocalname localname of the node + * @param aPrefix prefix of the node + * @param aNamespaceID namespace of the node + */ + static bool IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix, + int32_t aNamespaceID); + + /** + * Creates a DocumentFragment from text using a context node to resolve + * namespaces. + * + * Note! In the HTML case with the HTML5 parser enabled, this is only called + * from Range.createContextualFragment() and the implementation here is + * quirky accordingly (html context node behaves like a body context node). + * If you don't want that quirky behavior, don't use this method as-is! + * + * @param aContextNode the node which is used to resolve namespaces + * @param aFragment the string which is parsed to a DocumentFragment + * @param aReturn the resulting fragment + * @param aPreventScriptExecution whether to mark scripts as already started + */ + static nsresult CreateContextualFragment(nsINode* aContextNode, + const nsAString& aFragment, + bool aPreventScriptExecution, + nsIDOMDocumentFragment** aReturn); + static already_AddRefed<mozilla::dom::DocumentFragment> + CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment, + bool aPreventScriptExecution, + mozilla::ErrorResult& aRv); + + /** + * Invoke the fragment parsing algorithm (innerHTML) using the HTML parser. + * + * @param aSourceBuffer the string being set as innerHTML + * @param aTargetNode the target container + * @param aContextLocalName local name of context node + * @param aContextNamespace namespace of context node + * @param aQuirks true to make <table> not close <p> + * @param aPreventScriptExecution true to prevent scripts from executing; + * don't set to false when parsing into a target node that has been + * bound to tree. + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too + * long and NS_OK otherwise. + */ + static nsresult ParseFragmentHTML(const nsAString& aSourceBuffer, + nsIContent* aTargetNode, + nsIAtom* aContextLocalName, + int32_t aContextNamespace, + bool aQuirks, + bool aPreventScriptExecution); + + /** + * Invoke the fragment parsing algorithm (innerHTML) using the XML parser. + * + * @param aSourceBuffer the string being set as innerHTML + * @param aTargetNode the target container + * @param aTagStack the namespace mapping context + * @param aPreventExecution whether to mark scripts as already started + * @param aReturn the result fragment + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made, a return code from the XML parser. + */ + static nsresult ParseFragmentXML(const nsAString& aSourceBuffer, + nsIDocument* aDocument, + nsTArray<nsString>& aTagStack, + bool aPreventScriptExecution, + nsIDOMDocumentFragment** aReturn); + + /** + * Parse a string into a document using the HTML parser. + * Script elements are marked unexecutable. + * + * @param aSourceBuffer the string to parse as an HTML document + * @param aTargetDocument the document object to parse into. Must not have + * child nodes. + * @param aScriptingEnabledForNoscriptParsing whether <noscript> is parsed + * as if scripting was enabled + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too + * long and NS_OK otherwise. + */ + static nsresult ParseDocumentHTML(const nsAString& aSourceBuffer, + nsIDocument* aTargetDocument, + bool aScriptingEnabledForNoscriptParsing); + + /** + * Converts HTML source to plain text by parsing the source and using the + * plain text serializer on the resulting tree. + * + * @param aSourceBuffer the string to parse as an HTML document + * @param aResultBuffer the string where the plain text result appears; + * may be the same string as aSourceBuffer + * @param aFlags Flags from nsIDocumentEncoder. + * @param aWrapCol Number of columns after which to line wrap; 0 for no + * auto-wrapping + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too + * long and NS_OK otherwise. + */ + static nsresult ConvertToPlainText(const nsAString& aSourceBuffer, + nsAString& aResultBuffer, + uint32_t aFlags, + uint32_t aWrapCol); + + /** + * Sets the text contents of a node by replacing all existing children + * with a single text child. + * + * The function always notifies. + * + * Will reuse the first text child if one is available. Will not reuse + * existing cdata children. + * + * @param aContent Node to set contents of. + * @param aValue Value to set contents to. + * @param aTryReuse When true, the function will try to reuse an existing + * textnodes rather than always creating a new one. + */ + static nsresult SetNodeTextContent(nsIContent* aContent, + const nsAString& aValue, + bool aTryReuse); + + /** + * Get the textual contents of a node. This is a concatenation of all + * textnodes that are direct or (depending on aDeep) indirect children + * of the node. + * + * NOTE! No serialization takes place and <br> elements + * are not converted into newlines. Only textnodes and cdata nodes are + * added to the result. + * + * @see nsLayoutUtils::GetFrameTextContent + * + * @param aNode Node to get textual contents of. + * @param aDeep If true child elements of aNode are recursivly descended + * into to find text children. + * @param aResult the result. Out param. + * @return false on out of memory errors, true otherwise. + */ + MOZ_MUST_USE + static bool GetNodeTextContent(nsINode* aNode, bool aDeep, + nsAString& aResult, const mozilla::fallible_t&); + + static void GetNodeTextContent(nsINode* aNode, bool aDeep, + nsAString& aResult); + + /** + * Same as GetNodeTextContents but appends the result rather than sets it. + */ + static bool AppendNodeTextContent(nsINode* aNode, bool aDeep, + nsAString& aResult, const mozilla::fallible_t&); + + /** + * Utility method that checks if a given node has any non-empty children. This + * method does not descend recursively into children by default. + * + * @param aDiscoverMode Set to eRecurseIntoChildren to descend recursively + * into children. + */ + enum TextContentDiscoverMode : uint8_t { + eRecurseIntoChildren, eDontRecurseIntoChildren + }; + + static bool HasNonEmptyTextContent( + nsINode* aNode, + TextContentDiscoverMode aDiscoverMode = eDontRecurseIntoChildren); + + /** + * Delete strings allocated for nsContentList matches + */ + static void DestroyMatchString(void* aData); + + /** + * Unbinds the content from the tree and nulls it out if it's not null. + */ + static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent); + static void DestroyAnonymousContent(nsCOMPtr<Element>* aElement); + + /* + * Notify when the first XUL menu is opened and when the all XUL menus are + * closed. At opening, aInstalling should be TRUE, otherwise, it should be + * FALSE. + */ + static void NotifyInstalledMenuKeyboardListener(bool aInstalling); + + /** + * Returns true if aPrincipal is the system principal. + */ + static bool IsSystemPrincipal(nsIPrincipal* aPrincipal); + + /** + * Returns true if aPrincipal is an nsExpandedPrincipal. + */ + static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal); + + /** + * Returns true if aPrincipal is the system or an nsExpandedPrincipal. + */ + static bool IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) + { + return IsSystemPrincipal(aPrincipal) || IsExpandedPrincipal(aPrincipal); + } + + /** + * Gets the system principal from the security manager. + */ + static nsIPrincipal* GetSystemPrincipal(); + + /** + * Gets the null subject principal singleton. This is only useful for + * assertions. + */ + static nsIPrincipal* GetNullSubjectPrincipal() { return sNullSubjectPrincipal; } + + /** + * *aResourcePrincipal is a principal describing who may access the contents + * of a resource. The resource can only be consumed by a principal that + * subsumes *aResourcePrincipal. MAKE SURE THAT NOTHING EVER ACTS WITH THE + * AUTHORITY OF *aResourcePrincipal. + * It may be null to indicate that the resource has no data from any origin + * in it yet and anything may access the resource. + * Additional data is being mixed into the resource from aExtraPrincipal + * (which may be null; if null, no data is being mixed in and this function + * will do nothing). Update *aResourcePrincipal to reflect the new data. + * If *aResourcePrincipal subsumes aExtraPrincipal, nothing needs to change, + * otherwise *aResourcePrincipal is replaced with the system principal. + * Returns true if *aResourcePrincipal changed. + */ + static bool CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrincipal, + nsIPrincipal* aExtraPrincipal); + + /** + * Trigger a link with uri aLinkURI. If aClick is false, this triggers a + * mouseover on the link, otherwise it triggers a load after doing a + * security check using aContent's principal. + * + * @param aContent the node on which a link was triggered. + * @param aPresContext the pres context, must be non-null. + * @param aLinkURI the URI of the link, must be non-null. + * @param aTargetSpec the target (like target=, may be empty). + * @param aClick whether this was a click or not (if false, this method + * assumes you just hovered over the link). + * @param aIsUserTriggered whether the user triggered the link. This would be + * false for loads from auto XLinks or from the + * click() method if we ever implement it. + * @param aIsTrusted If false, JS Context will be pushed to stack + * when the link is triggered. + */ + static void TriggerLink(nsIContent *aContent, nsPresContext *aPresContext, + nsIURI *aLinkURI, const nsString& aTargetSpec, + bool aClick, bool aIsUserTriggered, + bool aIsTrusted); + + /** + * Get the link location. + */ + static void GetLinkLocation(mozilla::dom::Element* aElement, + nsString& aLocationString); + + /** + * Return top-level widget in the parent chain. + */ + static nsIWidget* GetTopLevelWidget(nsIWidget* aWidget); + + /** + * Return the localized ellipsis for UI. + */ + static const nsDependentString GetLocalizedEllipsis(); + + /** + * Hide any XUL popups associated with aDocument, including any documents + * displayed in child frames. Does nothing if aDocument is null. + */ + static void HidePopupsInDocument(nsIDocument* aDocument); + + /** + * Retrieve the current drag session, or null if no drag is currently occuring + */ + static already_AddRefed<nsIDragSession> GetDragSession(); + + /* + * Initialize and set the dataTransfer field of an WidgetDragEvent. + */ + static nsresult SetDataTransferInEvent(mozilla::WidgetDragEvent* aDragEvent); + + // filters the drag and drop action to fit within the effects allowed and + // returns it. + static uint32_t FilterDropEffect(uint32_t aAction, uint32_t aEffectAllowed); + + /* + * Return true if the target of a drop event is a content document that is + * an ancestor of the document for the source of the drag. + */ + static bool CheckForSubFrameDrop(nsIDragSession* aDragSession, + mozilla::WidgetDragEvent* aDropEvent); + + /** + * Return true if aURI is a local file URI (i.e. file://). + */ + static bool URIIsLocalFile(nsIURI *aURI); + + /** + * Get the application manifest URI for this document. The manifest URI + * is specified in the manifest= attribute of the root element of the + * document. + * + * @param aDocument The document that lists the manifest. + * @param aURI The manifest URI. + */ + static void GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI); + + /** + * Check whether an application should be allowed to use offline APIs. + */ + static bool OfflineAppAllowed(nsIURI *aURI); + + /** + * Check whether an application should be allowed to use offline APIs. + */ + static bool OfflineAppAllowed(nsIPrincipal *aPrincipal); + + /** + * If offline-apps.allow_by_default is true, we set offline-app permission + * for the principal and return true. Otherwise false. + */ + static bool MaybeAllowOfflineAppByDefault(nsIPrincipal *aPrincipal); + + /** + * Increases the count of blockers preventing scripts from running. + * NOTE: You might want to use nsAutoScriptBlocker rather than calling + * this directly + */ + static void AddScriptBlocker(); + + /** + * Decreases the count of blockers preventing scripts from running. + * NOTE: You might want to use nsAutoScriptBlocker rather than calling + * this directly + * + * WARNING! Calling this function could synchronously execute scripts. + */ + static void RemoveScriptBlocker(); + + /** + * Add a runnable that is to be executed as soon as it's safe to execute + * scripts. + * NOTE: If it's currently safe to execute scripts, aRunnable will be run + * synchronously before the function returns. + * + * @param aRunnable The nsIRunnable to run as soon as it's safe to execute + * scripts. Passing null is allowed and results in nothing + * happening. It is also allowed to pass an object that + * has not yet been AddRefed. + */ + static void AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable); + static void AddScriptRunner(nsIRunnable* aRunnable); + + /** + * Returns true if it's safe to execute content script and false otherwise. + * + * The only known case where this lies is mutation events. They run, and can + * run anything else, when this function returns false, but this is ok. + */ + static bool IsSafeToRunScript() { + return sScriptBlockerCount == 0; + } + + // XXXcatalinb: workaround for weird include error when trying to reference + // ipdl types in WindowWatcher. + static nsIWindowProvider* + GetWindowProviderForContentProcess(); + + // Returns the browser window with the most recent time stamp that is + // not in private browsing mode. + static already_AddRefed<nsPIDOMWindowOuter> + GetMostRecentNonPBWindow(); + + /** + * Call this function if !IsSafeToRunScript() and we fail to run the script + * (rather than using AddScriptRunner as we usually do). |aDocument| is + * optional as it is only used for showing the URL in the console. + */ + static void WarnScriptWasIgnored(nsIDocument* aDocument); + + /** + * Add a "synchronous section", in the form of an nsIRunnable run once the + * event loop has reached a "stable state". |aRunnable| must not cause any + * queued events to be processed (i.e. must not spin the event loop). + * We've reached a stable state when the currently executing task/event has + * finished, see + * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section + * In practice this runs aRunnable once the currently executing event + * finishes. If called multiple times per task/event, all the runnables will + * be executed, in the order in which RunInStableState() was called. + */ + static void RunInStableState(already_AddRefed<nsIRunnable> aRunnable); + + /* Add a "synchronous section", in the form of an nsIRunnable run once the + * event loop has reached a "metastable state". |aRunnable| must not cause any + * queued events to be processed (i.e. must not spin the event loop). + * We've reached a metastable state when the currently executing task or + * microtask has finished. This is not specced at this time. + * In practice this runs aRunnable once the currently executing task or + * microtask finishes. If called multiple times per microtask, all the + * runnables will be executed, in the order in which RunInMetastableState() + * was called + */ + static void RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable); + + // Call EnterMicroTask when you're entering JS execution. + // Usually the best way to do this is to use nsAutoMicroTask. + static void EnterMicroTask(); + static void LeaveMicroTask(); + + static bool IsInMicroTask(); + static uint32_t MicroTaskLevel(); + static void SetMicroTaskLevel(uint32_t aLevel); + + static void PerformMainThreadMicroTaskCheckpoint(); + + /* Process viewport META data. This gives us information for the scale + * and zoom of a page on mobile devices. We stick the information in + * the document header and use it later on after rendering. + * + * See Bug #436083 + */ + static nsresult ProcessViewportInfo(nsIDocument *aDocument, + const nsAString &viewportInfo); + + static nsIScriptContext* GetContextForEventHandlers(nsINode* aNode, + nsresult* aRv); + + static JSContext *GetCurrentJSContext(); + static JSContext *GetCurrentJSContextForThread(); + + /** + * Case insensitive comparison between two strings. However it only ignores + * case for ASCII characters a-z. + */ + static bool EqualsIgnoreASCIICase(const nsAString& aStr1, + const nsAString& aStr2); + + /** + * Convert ASCII A-Z to a-z. + */ + static void ASCIIToLower(nsAString& aStr); + static void ASCIIToLower(nsACString& aStr); + static void ASCIIToLower(const nsAString& aSource, nsAString& aDest); + static void ASCIIToLower(const nsACString& aSource, nsACString& aDest); + + /** + * Convert ASCII a-z to A-Z. + */ + static void ASCIIToUpper(nsAString& aStr); + static void ASCIIToUpper(nsACString& aStr); + static void ASCIIToUpper(const nsAString& aSource, nsAString& aDest); + static void ASCIIToUpper(const nsACString& aSource, nsACString& aDest); + + /** + * Return whether aStr contains an ASCII uppercase character. + */ + static bool StringContainsASCIIUpper(const nsAString& aStr); + + // Returns NS_OK for same origin, error (NS_ERROR_DOM_BAD_URI) if not. + static nsresult CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel); + static nsIInterfaceRequestor* SameOriginChecker(); + + /** + * Get the Origin of the passed in nsIPrincipal or nsIURI. If the passed in + * nsIURI or the URI of the passed in nsIPrincipal does not have a host, the + * origin is set to 'null'. + * + * The ASCII versions return a ASCII strings that are puny-code encoded, + * suitable for, for example, header values. The UTF versions return strings + * containing international characters. + * + * @pre aPrincipal/aOrigin must not be null. + * + * @note this should be used for HTML5 origin determination. + */ + static nsresult GetASCIIOrigin(nsIPrincipal* aPrincipal, + nsACString& aOrigin); + static nsresult GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin); + static nsresult GetUTFOrigin(nsIPrincipal* aPrincipal, + nsAString& aOrigin); + static nsresult GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin); + + /** + * This method creates and dispatches "command" event, which implements + * nsIDOMXULCommandEvent. + * If aShell is not null, dispatching goes via + * nsIPresShell::HandleDOMEventWithTarget. + */ + static nsresult DispatchXULCommand(nsIContent* aTarget, + bool aTrusted, + nsIDOMEvent* aSourceEvent = nullptr, + nsIPresShell* aShell = nullptr, + bool aCtrl = false, + bool aAlt = false, + bool aShift = false, + bool aMeta = false); + + static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal); + + /** + * The method checks whether the caller can access native anonymous content. + * If there is no JS in the stack or privileged JS is running, this + * method returns true, otherwise false. + */ + static bool CanAccessNativeAnon(); + + MOZ_MUST_USE + static nsresult WrapNative(JSContext *cx, nsISupports *native, + const nsIID* aIID, JS::MutableHandle<JS::Value> vp, + bool aAllowWrapping = true) + { + return WrapNative(cx, native, nullptr, aIID, vp, aAllowWrapping); + } + + // Same as the WrapNative above, but use this one if aIID is nsISupports' IID. + MOZ_MUST_USE + static nsresult WrapNative(JSContext *cx, nsISupports *native, + JS::MutableHandle<JS::Value> vp, + bool aAllowWrapping = true) + { + return WrapNative(cx, native, nullptr, nullptr, vp, aAllowWrapping); + } + + MOZ_MUST_USE + static nsresult WrapNative(JSContext *cx, nsISupports *native, + nsWrapperCache *cache, + JS::MutableHandle<JS::Value> vp, + bool aAllowWrapping = true) + { + return WrapNative(cx, native, cache, nullptr, vp, aAllowWrapping); + } + + /** + * Creates an arraybuffer from a binary string. + */ + static nsresult CreateArrayBuffer(JSContext *aCx, const nsACString& aData, + JSObject** aResult); + + static void StripNullChars(const nsAString& aInStr, nsAString& aOutStr); + + /** + * Strip all \n, \r and nulls from the given string + * @param aString the string to remove newlines from [in/out] + */ + static void RemoveNewlines(nsString &aString); + + /** + * Convert Windows and Mac platform linebreaks to \n. + * @param aString the string to convert the newlines inside [in/out] + */ + static void PlatformToDOMLineBreaks(nsString &aString); + MOZ_MUST_USE + static bool PlatformToDOMLineBreaks(nsString &aString, + const mozilla::fallible_t&); + + /** + * Populates aResultString with the contents of the string-buffer aBuf, up + * to aBuf's null-terminator. aBuf must not be null. Ownership of the string + * is not transferred. + */ + static void PopulateStringFromStringBuffer(nsStringBuffer* aBuf, + nsAString& aResultString); + + static bool IsHandlingKeyBoardEvent() + { + return sIsHandlingKeyBoardEvent; + } + + static void SetIsHandlingKeyBoardEvent(bool aHandling) + { + sIsHandlingKeyBoardEvent = aHandling; + } + + /** + * Utility method for getElementsByClassName. aRootNode is the node (either + * document or element), which getElementsByClassName was called on. + */ + static already_AddRefed<nsContentList> + GetElementsByClassName(nsINode* aRootNode, const nsAString& aClasses) + { + NS_PRECONDITION(aRootNode, "Must have root node"); + + return NS_GetFuncStringHTMLCollection(aRootNode, MatchClassNames, + DestroyClassNameArray, + AllocClassMatchingInfo, + aClasses); + } + + /** + * Returns a presshell for this document, if there is one. This will be + * aDoc's direct presshell if there is one, otherwise we'll look at all + * ancestor documents to try to find a presshell, so for example this can + * still find a presshell for documents in display:none frames that have + * no presentation. So you have to be careful how you use this presshell --- + * getting generic data like a device context or widget from it is OK, but it + * might not be this document's actual presentation. + */ + static nsIPresShell* FindPresShellForDocument(const nsIDocument* aDoc); + + /** + * Returns the widget for this document if there is one. Looks at all ancestor + * documents to try to find a widget, so for example this can still find a + * widget for documents in display:none frames that have no presentation. + */ + static nsIWidget* WidgetForDocument(const nsIDocument* aDoc); + + /** + * Returns a layer manager to use for the given document. Basically we + * look up the document hierarchy for the first document which has + * a presentation with an associated widget, and use that widget's + * layer manager. + * + * @param aDoc the document for which to return a layer manager. + * @param aAllowRetaining an outparam that states whether the returned + * layer manager should be used for retained layers + */ + static already_AddRefed<mozilla::layers::LayerManager> + LayerManagerForDocument(const nsIDocument *aDoc); + + /** + * Returns a layer manager to use for the given document. Basically we + * look up the document hierarchy for the first document which has + * a presentation with an associated widget, and use that widget's + * layer manager. In addition to the normal layer manager lookup this will + * specifically request a persistent layer manager. This means that the layer + * manager is expected to remain the layer manager for the document in the + * forseeable future. This function should be used carefully as it may change + * the document's layer manager. + * + * @param aDoc the document for which to return a layer manager. + * @param aAllowRetaining an outparam that states whether the returned + * layer manager should be used for retained layers + */ + static already_AddRefed<mozilla::layers::LayerManager> + PersistentLayerManagerForDocument(nsIDocument *aDoc); + + /** + * Determine whether a content node is focused or not, + * + * @param aContent the content node to check + * @return true if the content node is focused, false otherwise. + */ + static bool IsFocusedContent(const nsIContent *aContent); + + /** + * Returns true if the DOM full-screen API is enabled. + */ + static bool IsFullScreenApiEnabled(); + + /** + * Returns true if the unprefixed fullscreen API is enabled. + */ + static bool IsUnprefixedFullscreenApiEnabled() + { return sIsUnprefixedFullscreenApiEnabled; } + + /** + * Returns true if requests for full-screen are allowed in the current + * context. Requests are only allowed if the user initiated them (like with + * a mouse-click or key press), unless this check has been disabled by + * setting the pref "full-screen-api.allow-trusted-requests-only" to false. + */ + static bool IsRequestFullScreenAllowed(); + + /** + * Returns true if calling execCommand with 'cut' or 'copy' arguments + * is restricted to chrome code. + */ + static bool IsCutCopyRestricted() + { + return !sIsCutCopyAllowed; + } + + /** + * Returns true if calling execCommand with 'cut' or 'copy' arguments is + * allowed in the current context. These are only allowed if the user initiated + * them (like with a mouse-click or key press). + */ + static bool IsCutCopyAllowed(); + + /* + * Returns true if the performance timing APIs are enabled. + */ + static bool IsPerformanceTimingEnabled() + { + return sIsPerformanceTimingEnabled; + } + + /* + * Returns true if user timing API should print to console. + */ + static bool IsUserTimingLoggingEnabled() + { + return sIsUserTimingLoggingEnabled; + } + + /* + * Returns true if the performance timing APIs are enabled. + */ + static bool IsResourceTimingEnabled() + { + return sIsResourceTimingEnabled; + } + + /* + * Returns true if notification should be sent for peformance timing events. + */ + static bool SendPerformanceTimingNotifications() + { + return sSendPerformanceTimingNotifications; + } + + /* + * Returns true if the frame timing APIs are enabled. + */ + static bool IsFrameTimingEnabled(); + + /* + * Returns true if URL setters should percent encode the Hash/Ref segment + * and getters should return the percent decoded value of the segment + */ + static bool EncodeDecodeURLHash() + { + return sEncodeDecodeURLHash; + } + + /* + * Returns true if URL getters should percent decode the value of the segment + */ + static bool GettersDecodeURLHash() + { + return sGettersDecodeURLHash && sEncodeDecodeURLHash; + } + + /* + * Returns true if the browser should attempt to prevent content scripts + * from collecting distinctive information about the browser that could + * be used to "fingerprint" and track the user across websites. + */ + static bool ResistFingerprinting() + { + return sPrivacyResistFingerprinting; + } + + /* + * Returns true if the browser should attempt to prevent the given caller type + * from collecting distinctive information about the browser that could + * be used to "fingerprint" and track the user across websites. + */ + static bool ResistFingerprinting(mozilla::dom::CallerType aCallerType) + { + return aCallerType != mozilla::dom::CallerType::System && + ResistFingerprinting(); + } + + /** + * Returns true if the browser should show busy cursor when loading page. + */ + static bool UseActivityCursor() + { + return sUseActivityCursor; + } + + /** + * Return true if this doc is controlled by a ServiceWorker. + */ + static bool IsControlledByServiceWorker(nsIDocument* aDocument); + + /** + * Fire mutation events for changes caused by parsing directly into a + * context node. + * + * @param aDoc the document of the node + * @param aDest the destination node that got stuff appended to it + * @param aOldChildCount the number of children the node had before parsing + */ + static void FireMutationEventsForDirectParsing(nsIDocument* aDoc, + nsIContent* aDest, + int32_t aOldChildCount); + + /** + * Returns true if the content is in a document and contains a plugin + * which we don't control event dispatch for, i.e. do any plugins in this + * doc tree receive key events outside of our control? This always returns + * false on MacOSX. + */ + static bool HasPluginWithUncontrolledEventDispatch(nsIContent* aContent); + + /** + * Returns the root document in a document hierarchy. Normally this + * will be the chrome document. + */ + static nsIDocument* GetRootDocument(nsIDocument* aDoc); + + /** + * Returns true if aWin and the current pointer lock document + * have common scriptable top window. + */ + static bool IsInPointerLockContext(nsPIDOMWindowOuter* aWin); + + /** + * Returns the time limit on handling user input before + * EventStateManager::IsHandlingUserInput() stops returning true. + * This enables us to detect long running user-generated event handlers. + */ + static TimeDuration HandlingUserInputTimeout(); + + static void GetShiftText(nsAString& text); + static void GetControlText(nsAString& text); + static void GetMetaText(nsAString& text); + static void GetOSText(nsAString& text); + static void GetAltText(nsAString& text); + static void GetModifierSeparatorText(nsAString& text); + + /** + * Returns if aContent has a tabbable subdocument. + * A sub document isn't tabbable when it's a zombie document. + * + * @param aElement element to test. + * + * @return Whether the subdocument is tabbable. + */ + static bool IsSubDocumentTabbable(nsIContent* aContent); + + /** + * Returns if aNode ignores user focus. + * + * @param aNode node to test + * + * @return Whether the node ignores user focus. + */ + static bool IsUserFocusIgnored(nsINode* aNode); + + /** + * Returns if aContent has the 'scrollgrab' property. + * aContent may be null (in this case false is returned). + */ + static bool HasScrollgrab(nsIContent* aContent); + + /** + * Flushes the layout tree (recursively) + * + * @param aWindow the window the flush should start at + * + */ + static void FlushLayoutForTree(nsPIDOMWindowOuter* aWindow); + + /** + * Returns true if content with the given principal is allowed to use XUL + * and XBL and false otherwise. + */ + static bool AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal); + + /** + * Perform cleanup that's appropriate for XPCOM shutdown. + */ + static void XPCOMShutdown(); + + /** + * Checks if internal PDF viewer is enabled. + */ + static bool IsPDFJSEnabled(); + + /** + * Checks if internal SWF player is enabled. + */ + static bool IsSWFPlayerEnabled(); + + enum ContentViewerType + { + TYPE_UNSUPPORTED, + TYPE_CONTENT, + TYPE_PLUGIN, + TYPE_UNKNOWN + }; + + static already_AddRefed<nsIDocumentLoaderFactory> + FindInternalContentViewer(const nsACString& aType, + ContentViewerType* aLoaderType = nullptr); + + /** + * This helper method returns true if the aPattern pattern matches aValue. + * aPattern should not contain leading and trailing slashes (/). + * The pattern has to match the entire value not just a subset. + * aDocument must be a valid pointer (not null). + * + * This is following the HTML5 specification: + * http://dev.w3.org/html5/spec/forms.html#attr-input-pattern + * + * WARNING: This method mutates aPattern and aValue! + * + * @param aValue the string to check. + * @param aPattern the string defining the pattern. + * @param aDocument the owner document of the element. + * @result whether the given string is matches the pattern. + */ + static bool IsPatternMatching(nsAString& aValue, nsAString& aPattern, + nsIDocument* aDocument); + + /** + * Calling this adds support for + * ontouch* event handler DOM attributes. + */ + static void InitializeTouchEventTable(); + + /** + * Test whether the given URI always inherits a security context + * from the document it comes from. + */ + static nsresult URIInheritsSecurityContext(nsIURI *aURI, bool *aResult); + + /** + * Called before a channel is created to query whether the new + * channel should inherit the principal. + * + * The argument aLoadingPrincipal must not be null. The argument + * aURI must be the URI of the new channel. If aInheritForAboutBlank + * is true, then about:blank will be told to inherit the principal. + * If aForceInherit is true, the new channel will be told to inherit + * the principal no matter what. + * + * The return value is whether the new channel should inherit + * the principal. + */ + static bool ChannelShouldInheritPrincipal(nsIPrincipal* aLoadingPrincipal, + nsIURI* aURI, + bool aInheritForAboutBlank, + bool aForceInherit); + + static nsresult Btoa(const nsAString& aBinaryData, + nsAString& aAsciiBase64String); + + static nsresult Atob(const nsAString& aAsciiString, + nsAString& aBinaryData); + + /** + * Returns whether the input element passed in parameter has the autocomplete + * functionality enabled. It is taking into account the form owner. + * NOTE: the caller has to make sure autocomplete makes sense for the + * element's type. + * + * @param aInput the input element to check. NOTE: aInput can't be null. + * @return whether the input element has autocomplete enabled. + */ + static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput); + + enum AutocompleteAttrState : uint8_t + { + eAutocompleteAttrState_Unknown = 1, + eAutocompleteAttrState_Invalid, + eAutocompleteAttrState_Valid, + }; + /** + * Parses the value of the autocomplete attribute into aResult, ensuring it's + * composed of valid tokens, otherwise the value "" is used. + * Note that this method is used for form fields, not on a <form> itself. + * + * @return whether aAttr was valid and can be cached. + */ + static AutocompleteAttrState + SerializeAutocompleteAttribute(const nsAttrValue* aAttr, + nsAString& aResult, + AutocompleteAttrState aCachedState = + eAutocompleteAttrState_Unknown); + + /* Variation that is used to retrieve a dictionary of the parts of the + * autocomplete attribute. + * + * @return whether aAttr was valid and can be cached. + */ + static AutocompleteAttrState + SerializeAutocompleteAttribute(const nsAttrValue* aAttr, + mozilla::dom::AutocompleteInfo& aInfo, + AutocompleteAttrState aCachedState = + eAutocompleteAttrState_Unknown); + + /** + * This will parse aSource, to extract the value of the pseudo attribute + * with the name specified in aName. See + * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification + * which is used to parse aSource. + * + * @param aSource the string to parse + * @param aName the name of the attribute to get the value for + * @param aValue [out] the value for the attribute with name specified in + * aAttribute. Empty if the attribute isn't present. + * @return true if the attribute exists and was successfully parsed. + * false if the attribute doesn't exist, or has a malformed + * value, such as an unknown or unterminated entity. + */ + static bool GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName, + nsAString& aValue); + + /** + * Returns true if the language name is a version of JavaScript and + * false otherwise + */ + static bool IsJavaScriptLanguage(const nsString& aName); + + /** + * Returns the JSVersion for a string of the form '1.n', n = 0, ..., 8, and + * JSVERSION_UNKNOWN for other strings. + */ + static JSVersion ParseJavascriptVersion(const nsAString& aVersionStr); + + static bool IsJavascriptMIMEType(const nsAString& aMIMEType); + + static void SplitMimeType(const nsAString& aValue, nsString& aType, + nsString& aParams); + + /** + * Function checks if the user is idle. + * + * @param aRequestedIdleTimeInMS The idle observer's requested idle time. + * @param aUserIsIdle boolean indicating if the user + * is currently idle or not. * + * @return NS_OK NS_OK returned if the requested idle service and + * the current idle time were successfully obtained. + * NS_ERROR_FAILURE returned if the the requested + * idle service or the current idle were not obtained. + */ + static nsresult IsUserIdle(uint32_t aRequestedIdleTimeInMS, bool* aUserIsIdle); + + /** + * Takes a selection, and a text control element (<input> or <textarea>), and + * returns the offsets in the text content corresponding to the selection. + * The selection's anchor and focus must both be in the root node passed or a + * descendant. + * + * @param aSelection Selection to check + * @param aRoot Root <input> or <textarea> element + * @param aOutStartOffset Output start offset + * @param aOutEndOffset Output end offset + */ + static void GetSelectionInTextControl(mozilla::dom::Selection* aSelection, + Element* aRoot, + int32_t& aOutStartOffset, + int32_t& aOutEndOffset); + + /** + * Takes a frame for anonymous content within a text control (<input> or + * <textarea>), and returns an offset in the text content, adjusted for a + * trailing <br> frame. + * + * @param aOffsetFrame Frame for the text content in which the offset + * lies + * @param aOffset Offset as calculated by GetContentOffsetsFromPoint + * @param aOutOffset Output adjusted offset + * + * @see GetSelectionInTextControl for the original basis of this function. + */ + static int32_t GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame, + int32_t aOffset); + + static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext); + + /** + * Returns true if the browser.dom.window.dump.enabled pref is set. + */ + static bool DOMWindowDumpEnabled(); + + /** + * Returns true if the privacy.donottrackheader.enabled pref is set. + */ + static bool DoNotTrackEnabled(); + + /** + * Returns a LogModule that dump calls from content script are logged to. + * This can be enabled with the 'Dump' module, and is useful for synchronizing + * content JS to other logging modules. + */ + static mozilla::LogModule* DOMDumpLog(); + + /** + * Returns whether a content is an insertion point for XBL + * bindings or web components ShadowRoot. In web components, + * this corresponds to a <content> element that participates + * in node distribution. In XBL this corresponds to an + * <xbl:children> element in anonymous content. + * + * @param aContent The content to test for being an insertion point. + */ + static bool IsContentInsertionPoint(nsIContent* aContent); + + + /** + * Returns whether the children of the provided content are + * nodes that are distributed to Shadow DOM insertion points. + */ + static bool HasDistributedChildren(nsIContent* aContent); + + /** + * Returns whether a given header is forbidden for an XHR or fetch + * request. + */ + static bool IsForbiddenRequestHeader(const nsACString& aHeader); + + /** + * Returns whether a given header is forbidden for a system XHR + * request. + */ + static bool IsForbiddenSystemRequestHeader(const nsACString& aHeader); + + /** + * Returns whether a given Content-Type header value is allowed + * for a non-CORS XHR or fetch request. + */ + static bool IsAllowedNonCorsContentType(const nsACString& aHeaderValue); + + /** + * Returns whether a given header is forbidden for an XHR or fetch + * response. + */ + static bool IsForbiddenResponseHeader(const nsACString& aHeader); + + /** + * Returns the inner window ID for the window associated with a request, + */ + static uint64_t GetInnerWindowID(nsIRequest* aRequest); + + /** + * If the hostname for aURI is an IPv6 it encloses it in brackets, + * otherwise it just outputs the hostname in aHost. + */ + static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost); + static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost); + + /* + * Call the given callback on all remote children of the given top-level + * window. Return true from the callback to stop calling further children. + */ + static void CallOnAllRemoteChildren(nsPIDOMWindowOuter* aWindow, + CallOnRemoteChildFunction aCallback, + void* aArg); + + /* + * Call nsPIDOMWindow::SetKeyboardIndicators all all remote children. This is + * in here rather than nsGlobalWindow because TabParent indirectly includes + * Windows headers which aren't allowed there. + */ + static void SetKeyboardIndicatorsOnRemoteChildren(nsPIDOMWindowOuter* aWindow, + UIStateChangeType aShowAccelerators, + UIStateChangeType aShowFocusRings); + + /** + * Given an nsIFile, attempts to read it into aString. + * + * Note: Use sparingly! This causes main-thread I/O, which causes jank and all + * other bad things. + */ + static nsresult SlurpFileToString(nsIFile* aFile, nsACString& aString); + + /** + * Returns true if the mime service thinks this file contains an image. + * + * The content type is returned in aType. + */ + static bool IsFileImage(nsIFile* aFile, nsACString& aType); + + /** + * Given an IPCDataTransferItem that has a flavor for which IsFlavorImage + * returns true and whose IPCDataTransferData is of type nsCString (raw image + * data), construct an imgIContainer for the image encoded by the transfer + * item. + */ + static nsresult DataTransferItemToImage(const mozilla::dom::IPCDataTransferItem& aItem, + imgIContainer** aContainer); + + /** + * Given a flavor obtained from an IPCDataTransferItem or nsITransferable, + * returns true if we should treat the data as an image. + */ + static bool IsFlavorImage(const nsACString& aFlavor); + + static nsresult IPCTransferableToTransferable(const mozilla::dom::IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + nsIPrincipal* aRequestingPrincipal, + nsITransferable* aTransferable, + mozilla::dom::nsIContentParent* aContentParent, + mozilla::dom::TabChild* aTabChild); + + static void TransferablesToIPCTransferables(nsIArray* aTransferables, + nsTArray<mozilla::dom::IPCDataTransfer>& aIPC, + bool aInSyncMessage, + mozilla::dom::nsIContentChild* aChild, + mozilla::dom::nsIContentParent* aParent); + + static void TransferableToIPCTransferable(nsITransferable* aTransferable, + mozilla::dom::IPCDataTransfer* aIPCDataTransfer, + bool aInSyncMessage, + mozilla::dom::nsIContentChild* aChild, + mozilla::dom::nsIContentParent* aParent); + + /* + * Get the pixel data from the given source surface and return it as a buffer. + * The length and stride will be assigned from the surface. + */ + static mozilla::UniquePtr<char[]> GetSurfaceData( + mozilla::NotNull<mozilla::gfx::DataSourceSurface*> aSurface, + size_t* aLength, int32_t* aStride); + + /* + * Get the pixel data from the given source surface and fill it in Shmem. + * The length and stride will be assigned from the surface. + */ + static void GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface, + size_t* aLength, int32_t* aStride, + mozilla::ipc::IShmemAllocator* aAlloc, + mozilla::ipc::Shmem *aOutShmem); + + // Helpers shared by the implementations of nsContentUtils methods and + // nsIDOMWindowUtils methods. + static mozilla::Modifiers GetWidgetModifiers(int32_t aModifiers); + static nsIWidget* GetWidget(nsIPresShell* aPresShell, nsPoint* aOffset); + static int16_t GetButtonsFlagForButton(int32_t aButton); + static mozilla::LayoutDeviceIntPoint ToWidgetPoint(const mozilla::CSSPoint& aPoint, + const nsPoint& aOffset, + nsPresContext* aPresContext); + static nsView* GetViewToDispatchEvent(nsPresContext* aPresContext, + nsIPresShell** aPresShell); + + /** + * Synthesize a key event to the given widget + * (see nsIDOMWindowUtils.sendKeyEvent). + */ + static nsresult SendKeyEvent(nsIWidget* aWidget, + const nsAString& aType, + int32_t aKeyCode, + int32_t aCharCode, + int32_t aModifiers, + uint32_t aAdditionalFlags, + bool* aDefaultActionTaken); + + /** + * Synthesize a mouse event to the given widget + * (see nsIDOMWindowUtils.sendMouseEvent). + */ + static nsresult SendMouseEvent(nsCOMPtr<nsIPresShell> aPresShell, + const nsAString& aType, + float aX, + float aY, + int32_t aButton, + int32_t aButtons, + int32_t aClickCount, + int32_t aModifiers, + bool aIgnoreRootScrollFrame, + float aPressure, + unsigned short aInputSourceArg, + bool aToWindow, + bool *aPreventDefault, + bool aIsDOMEventSynthesized, + bool aIsWidgetEventSynthesized); + + static void FirePageShowEvent(nsIDocShellTreeItem* aItem, + mozilla::dom::EventTarget* aChromeEventHandler, + bool aFireIfShowing); + + static void FirePageHideEvent(nsIDocShellTreeItem* aItem, + mozilla::dom::EventTarget* aChromeEventHandler); + + static already_AddRefed<nsPIWindowRoot> GetWindowRoot(nsIDocument* aDoc); + + /* + * Implements step 3.1 and 3.3 of the Determine request's Referrer algorithm + * from the Referrer Policy specification. + * + * The referrer policy of the document is applied by Necko when using + * channels. + * + * For documents representing an iframe srcdoc attribute, the document sets + * its own URI correctly, so this method simply uses the document's original + * or current URI as appropriate. + * + * aDoc may be null. + * + * https://w3c.github.io/webappsec/specs/referrer-policy/#determine-requests-referrer + */ + static nsresult SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal, + nsIDocument* aDoc, + nsIHttpChannel* aChannel, + mozilla::net::ReferrerPolicy aReferrerPolicy); + + /* + * Parse a referrer policy from a Referrer-Policy header + * https://www.w3.org/TR/referrer-policy/#parse-referrer-policy-from-header + * + * @param aHeader the response's Referrer-Policy header to parse + * @return referrer policy from the response header. + */ + static mozilla::net::ReferrerPolicy GetReferrerPolicyFromHeader(const nsAString& aHeader); + + static bool PushEnabled(JSContext* aCx, JSObject* aObj); + + static bool IsNonSubresourceRequest(nsIChannel* aChannel); + + static uint32_t CookiesBehavior() + { + return sCookiesBehavior; + } + + // The order of these entries matters, as we use std::min for total ordering + // of permissions. Private Browsing is considered to be more limiting + // then session scoping + enum class StorageAccess { + // Don't allow access to the storage + eDeny = 0, + // Allow access to the storage, but only if it is secure to do so in a + // private browsing context. + ePrivateBrowsing = 1, + // Allow access to the storage, but only persist it for the current session + eSessionScoped = 2, + // Allow access to the storage + eAllow = 3, + }; + + /* + * Checks if storage for the given window is permitted by a combination of + * the user's preferences, and whether the window is a third-party iframe. + * + * This logic is intended to be shared between the different forms of + * persistent storage which are available to web pages. Cookies don't use + * this logic, and security logic related to them must be updated separately. + */ + static StorageAccess StorageAllowedForWindow(nsPIDOMWindowInner* aWindow); + + /* + * Checks if storage for the given principal is permitted by the user's + * preferences. The caller is assumed to not be a third-party iframe. + * (if that is possible, the caller should use StorageAllowedForWindow) + */ + static StorageAccess StorageAllowedForPrincipal(nsIPrincipal* aPrincipal); + + /* + * Serializes a HTML nsINode into its markup representation. + */ + static bool SerializeNodeToMarkup(nsINode* aRoot, + bool aDescendentsOnly, + nsAString& aOut); + + /* + * Returns true iff the provided JSObject is a global, and its URI matches + * the provided about: URI. + * @param aGlobal the JSObject whose URI to check, if it is a global. + * @param aUri the URI to match, e.g. "about:feeds" + */ + static bool IsSpecificAboutPage(JSObject* aGlobal, const char* aUri); + + static void SetScrollbarsVisibility(nsIDocShell* aDocShell, bool aVisible); + + /* + * Return the associated presentation URL of the presented content. + * Will return empty string if the docshell is not in a presented content. + */ + static void GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl); + + /* + * Try to find the docshell corresponding to the given event target. + */ + static nsIDocShell* GetDocShellForEventTarget(mozilla::dom::EventTarget* aTarget); + + /** + * Returns true if the "HTTPS state" of the document should be "modern". See: + * + * https://html.spec.whatwg.org/#concept-document-https-state + * https://fetch.spec.whatwg.org/#concept-response-https-state + */ + static bool HttpsStateIsModern(nsIDocument* aDocument); + + /** + * Looking up a custom element definition. + * https://html.spec.whatwg.org/#look-up-a-custom-element-definition + */ + static mozilla::dom::CustomElementDefinition* + LookupCustomElementDefinition(nsIDocument* aDoc, + const nsAString& aLocalName, + uint32_t aNameSpaceID, + const nsAString* aIs = nullptr); + + static void SetupCustomElement(Element* aElement, + const nsAString* aTypeExtension = nullptr); + + static void EnqueueLifecycleCallback(nsIDocument* aDoc, + nsIDocument::ElementCallbackType aType, + Element* aCustomElement, + mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr, + mozilla::dom::CustomElementDefinition* aDefinition = nullptr); + + static void GetCustomPrototype(nsIDocument* aDoc, + int32_t aNamespaceID, + nsIAtom* aAtom, + JS::MutableHandle<JSObject*> prototype); + + static bool AttemptLargeAllocationLoad(nsIHttpChannel* aChannel); + +private: + static bool InitializeEventTable(); + + static nsresult EnsureStringBundle(PropertiesFile aFile); + + static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal, + nsIPrincipal* aPrincipal); + + static nsresult WrapNative(JSContext *cx, nsISupports *native, + nsWrapperCache *cache, const nsIID* aIID, + JS::MutableHandle<JS::Value> vp, + bool aAllowWrapping); + + static nsresult DispatchEvent(nsIDocument* aDoc, + nsISupports* aTarget, + const nsAString& aEventName, + bool aCanBubble, + bool aCancelable, + bool aTrusted, + bool *aDefaultAction = nullptr, + bool aOnlyChromeDispatch = false); + + static void InitializeModifierStrings(); + + static void DropFragmentParsers(); + + static bool MatchClassNames(nsIContent* aContent, int32_t aNamespaceID, + nsIAtom* aAtom, void* aData); + static void DestroyClassNameArray(void* aData); + static void* AllocClassMatchingInfo(nsINode* aRootNode, + const nsString* aClasses); + + // Fills in aInfo with the tokens from the supplied autocomplete attribute. + static AutocompleteAttrState InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal, + mozilla::dom::AutocompleteInfo& aInfo); + + static bool CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager, + CallOnRemoteChildFunction aCallback, + void* aArg); + + /* + * Checks if storage for a given principal is permitted by the user's + * preferences. If aWindow is non-null, its principal must be passed as + * aPrincipal, and the third-party iframe and sandboxing status of the window + * are also checked. + * + * Used in the implementation of StorageAllowedForWindow and + * StorageAllowedForPrincipal. + */ + static StorageAccess InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal, + nsPIDOMWindowInner* aWindow); + + static nsIXPConnect *sXPConnect; + + static nsIScriptSecurityManager *sSecurityManager; + static nsIPrincipal *sSystemPrincipal; + static nsIPrincipal *sNullSubjectPrincipal; + + static nsIParserService *sParserService; + + static nsNameSpaceManager *sNameSpaceManager; + + static nsIIOService *sIOService; + static nsIUUIDGenerator *sUUIDGenerator; + + static nsIConsoleService* sConsoleService; + + static nsDataHashtable<nsISupportsHashKey, EventNameMapping>* sAtomEventTable; + static nsDataHashtable<nsStringHashKey, EventNameMapping>* sStringEventTable; + static nsCOMArray<nsIAtom>* sUserDefinedEvents; + + static nsIStringBundleService* sStringBundleService; + static nsIStringBundle* sStringBundles[PropertiesFile_COUNT]; + + static nsIContentPolicy* sContentPolicyService; + static bool sTriedToGetContentPolicy; + + static nsILineBreaker* sLineBreaker; + static nsIWordBreaker* sWordBreaker; + + static nsIBidiKeyboard* sBidiKeyboard; + + static bool sInitialized; + static uint32_t sScriptBlockerCount; + static uint32_t sDOMNodeRemovedSuppressCount; + static uint32_t sMicroTaskLevel; + // Not an nsCOMArray because removing elements from those is slower + static AutoTArray<nsCOMPtr<nsIRunnable>, 8>* sBlockedScriptRunners; + static uint32_t sRunnersCountAtFirstBlocker; + static uint32_t sScriptBlockerCountWhereRunnersPrevented; + + static nsIInterfaceRequestor* sSameOriginChecker; + + static bool sIsHandlingKeyBoardEvent; + static bool sAllowXULXBL_for_file; + static bool sIsFullScreenApiEnabled; + static bool sIsUnprefixedFullscreenApiEnabled; + static bool sTrustedFullScreenOnly; + static bool sIsCutCopyAllowed; + static uint32_t sHandlingInputTimeout; + static bool sIsPerformanceTimingEnabled; + static bool sIsResourceTimingEnabled; + static bool sIsUserTimingLoggingEnabled; + static bool sIsFrameTimingPrefEnabled; + static bool sIsExperimentalAutocompleteEnabled; + static bool sEncodeDecodeURLHash; + static bool sGettersDecodeURLHash; + static bool sPrivacyResistFingerprinting; + static bool sSendPerformanceTimingNotifications; + static bool sUseActivityCursor; + static uint32_t sCookiesLifetimePolicy; + static uint32_t sCookiesBehavior; + + static nsHtml5StringParser* sHTMLFragmentParser; + static nsIParser* sXMLFragmentParser; + static nsIFragmentContentSink* sXMLFragmentSink; + + /** + * True if there's a fragment parser activation on the stack. + */ + static bool sFragmentParsingActive; + + static nsString* sShiftText; + static nsString* sControlText; + static nsString* sMetaText; + static nsString* sOSText; + static nsString* sAltText; + static nsString* sModifierSeparator; + +#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)) + static bool sDOMWindowDumpEnabled; +#endif + static bool sDoNotTrackEnabled; + static mozilla::LazyLogModule sDOMDumpLog; +}; + +class MOZ_RAII nsAutoScriptBlocker { +public: + explicit nsAutoScriptBlocker(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + nsContentUtils::AddScriptBlocker(); + } + ~nsAutoScriptBlocker() { + nsContentUtils::RemoveScriptBlocker(); + } +private: + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class MOZ_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved : + public nsAutoScriptBlocker { +public: + nsAutoScriptBlockerSuppressNodeRemoved() { + ++nsContentUtils::sDOMNodeRemovedSuppressCount; + } + ~nsAutoScriptBlockerSuppressNodeRemoved() { + --nsContentUtils::sDOMNodeRemovedSuppressCount; + } +}; + +class MOZ_STACK_CLASS nsAutoMicroTask +{ +public: + nsAutoMicroTask() + { + nsContentUtils::EnterMicroTask(); + } + ~nsAutoMicroTask() + { + nsContentUtils::LeaveMicroTask(); + } +}; + +namespace mozilla { +namespace dom { + +class TreeOrderComparator { +public: + bool Equals(nsINode* aElem1, nsINode* aElem2) const { + return aElem1 == aElem2; + } + bool LessThan(nsINode* aElem1, nsINode* aElem2) const { + return nsContentUtils::PositionIsBefore(aElem1, aElem2); + } +}; + +} // namespace dom +} // namespace mozilla + +#define NS_INTERFACE_MAP_ENTRY_TEAROFF(_interface, _allocator) \ + if (aIID.Equals(NS_GET_IID(_interface))) { \ + foundInterface = static_cast<_interface *>(_allocator); \ + if (!foundInterface) { \ + *aInstancePtr = nullptr; \ + return NS_ERROR_OUT_OF_MEMORY; \ + } \ + } else + +/* + * In the following helper macros we exploit the fact that the result of a + * series of additions will not be finite if any one of the operands in the + * series is not finite. + */ +#define NS_ENSURE_FINITE(f, rv) \ + if (!mozilla::IsFinite(f)) { \ + return (rv); \ + } + +#define NS_ENSURE_FINITE2(f1, f2, rv) \ + if (!mozilla::IsFinite((f1)+(f2))) { \ + return (rv); \ + } + +#define NS_ENSURE_FINITE4(f1, f2, f3, f4, rv) \ + if (!mozilla::IsFinite((f1)+(f2)+(f3)+(f4))) { \ + return (rv); \ + } + +#define NS_ENSURE_FINITE5(f1, f2, f3, f4, f5, rv) \ + if (!mozilla::IsFinite((f1)+(f2)+(f3)+(f4)+(f5))) { \ + return (rv); \ + } + +#define NS_ENSURE_FINITE6(f1, f2, f3, f4, f5, f6, rv) \ + if (!mozilla::IsFinite((f1)+(f2)+(f3)+(f4)+(f5)+(f6))) { \ + return (rv); \ + } + +// Deletes a linked list iteratively to avoid blowing up the stack (bug 460444). +#define NS_CONTENT_DELETE_LIST_MEMBER(type_, ptr_, member_) \ + { \ + type_ *cur = (ptr_)->member_; \ + (ptr_)->member_ = nullptr; \ + while (cur) { \ + type_ *next = cur->member_; \ + cur->member_ = nullptr; \ + delete cur; \ + cur = next; \ + } \ + } + +#endif /* nsContentUtils_h___ */ |