diff -r 000000000000 -r 6474c204b198 content/base/src/nsDocument.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/base/src/nsDocument.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,1684 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et 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/. */ + +/* + * Base class for all our document implementations. + */ + +#ifndef nsDocument_h___ +#define nsDocument_h___ + +#include "nsIDocument.h" + +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsCRT.h" +#include "nsWeakReference.h" +#include "nsWeakPtr.h" +#include "nsVoidArray.h" +#include "nsTArray.h" +#include "nsIDOMXMLDocument.h" +#include "nsIDOMDocumentXBL.h" +#include "nsStubDocumentObserver.h" +#include "nsIScriptGlobalObject.h" +#include "nsIContent.h" +#include "nsIPrincipal.h" +#include "nsIParser.h" +#include "nsBindingManager.h" +#include "nsINodeInfo.h" +#include "nsInterfaceHashtable.h" +#include "nsJSThingHashtable.h" +#include "nsIBoxObject.h" +#include "nsPIBoxObject.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIURI.h" +#include "nsScriptLoader.h" +#include "nsIRadioGroupContainer.h" +#include "nsILayoutHistoryState.h" +#include "nsIRequest.h" +#include "nsILoadGroup.h" +#include "nsTObserverArray.h" +#include "nsStubMutationObserver.h" +#include "nsIChannel.h" +#include "nsCycleCollectionParticipant.h" +#include "nsContentList.h" +#include "nsGkAtoms.h" +#include "nsIApplicationCache.h" +#include "nsIApplicationCacheContainer.h" +#include "nsStyleSet.h" +#include "pldhash.h" +#include "nsAttrAndChildArray.h" +#include "nsDOMAttributeMap.h" +#include "nsIContentViewer.h" +#include "nsIDOMXPathNSResolver.h" +#include "nsIInterfaceRequestor.h" +#include "nsILoadContext.h" +#include "nsIProgressEventSink.h" +#include "nsISecurityEventSink.h" +#include "nsIChannelEventSink.h" +#include "imgIRequest.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/EventStates.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/dom/DOMImplementation.h" +#include "mozilla/dom/StyleSheetList.h" +#include "nsIDOMTouchEvent.h" +#include "nsDataHashtable.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Attributes.h" +#include "nsIDOMXPathEvaluator.h" +#include "jsfriendapi.h" + +#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0) +#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1) +#define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2) +#define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3) + + +class nsDOMStyleSheetSetList; +class nsIOutputStream; +class nsDocument; +class nsIDTD; +class nsIRadioVisitor; +class nsIFormControl; +struct nsRadioGroupStruct; +class nsOnloadBlocker; +class nsUnblockOnloadEvent; +class nsChildContentList; +class nsHTMLStyleSheet; +class nsHTMLCSSStyleSheet; +class nsDOMNavigationTiming; +class nsWindowSizes; +class nsHtml5TreeOpExecutor; +class nsDocumentOnStack; +class nsPointerLockPermissionRequest; +class nsISecurityConsoleMessage; + +namespace mozilla { +class EventChainPreVisitor; +namespace dom { +class UndoManager; +class LifecycleCallbacks; +class CallbackFunction; +} +} + +/** + * Right now our identifier map entries contain information for 'name' + * and 'id' mappings of a given string. This is so that + * nsHTMLDocument::ResolveName only has to do one hash lookup instead + * of two. It's not clear whether this still matters for performance. + * + * We also store the document.all result list here. This is mainly so that + * when all elements with the given ID are removed and we remove + * the ID's nsIdentifierMapEntry, the document.all result is released too. + * Perhaps the document.all results should have their own hashtable + * in nsHTMLDocument. + */ +class nsIdentifierMapEntry : public nsStringHashKey +{ +public: + typedef mozilla::dom::Element Element; + + nsIdentifierMapEntry(const nsAString& aKey) : + nsStringHashKey(&aKey), mNameContentList(nullptr) + { + } + nsIdentifierMapEntry(const nsAString *aKey) : + nsStringHashKey(aKey), mNameContentList(nullptr) + { + } + nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) : + nsStringHashKey(&aOther.GetKey()) + { + NS_ERROR("Should never be called"); + } + ~nsIdentifierMapEntry(); + + void AddNameElement(nsINode* aDocument, Element* aElement); + void RemoveNameElement(Element* aElement); + bool IsEmpty(); + nsBaseContentList* GetNameContentList() { + return mNameContentList; + } + bool HasNameElement() const { + return mNameContentList && mNameContentList->Length() != 0; + } + + /** + * Returns the element if we know the element associated with this + * id. Otherwise returns null. + */ + Element* GetIdElement(); + /** + * Returns the list of all elements associated with this id. + */ + const nsSmallVoidArray* GetIdElements() const { + return &mIdContentList; + } + /** + * If this entry has a non-null image element set (using SetImageElement), + * the image element will be returned, otherwise the same as GetIdElement(). + */ + Element* GetImageIdElement(); + /** + * Append all the elements with this id to aElements + */ + void AppendAllIdContent(nsCOMArray* aElements); + /** + * This can fire ID change callbacks. + * @return true if the content could be added, false if we failed due + * to OOM. + */ + bool AddIdElement(Element* aElement); + /** + * This can fire ID change callbacks. + */ + void RemoveIdElement(Element* aElement); + /** + * Set the image element override for this ID. This will be returned by + * GetIdElement(true) if non-null. + */ + void SetImageElement(Element* aElement); + bool HasIdElementExposedAsHTMLDocumentProperty(); + + bool HasContentChangeCallback() { return mChangeCallbacks != nullptr; } + void AddContentChangeCallback(nsIDocument::IDTargetObserver aCallback, + void* aData, bool aForImage); + void RemoveContentChangeCallback(nsIDocument::IDTargetObserver aCallback, + void* aData, bool aForImage); + + void Traverse(nsCycleCollectionTraversalCallback* aCallback); + + struct ChangeCallback { + nsIDocument::IDTargetObserver mCallback; + void* mData; + bool mForImage; + }; + + struct ChangeCallbackEntry : public PLDHashEntryHdr { + typedef const ChangeCallback KeyType; + typedef const ChangeCallback* KeyTypePointer; + + ChangeCallbackEntry(const ChangeCallback* key) : + mKey(*key) { } + ChangeCallbackEntry(const ChangeCallbackEntry& toCopy) : + mKey(toCopy.mKey) { } + + KeyType GetKey() const { return mKey; } + bool KeyEquals(KeyTypePointer aKey) const { + return aKey->mCallback == mKey.mCallback && + aKey->mData == mKey.mData && + aKey->mForImage == mKey.mForImage; + } + + static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey) + { + return mozilla::HashGeneric(aKey->mCallback, aKey->mData); + } + enum { ALLOW_MEMMOVE = true }; + + ChangeCallback mKey; + }; + + static size_t SizeOfExcludingThis(nsIdentifierMapEntry* aEntry, + mozilla::MallocSizeOf aMallocSizeOf, + void* aArg); + +private: + void FireChangeCallbacks(Element* aOldElement, Element* aNewElement, + bool aImageOnly = false); + + // empty if there are no elements with this ID. + // The elements are stored as weak pointers. + nsSmallVoidArray mIdContentList; + nsRefPtr mNameContentList; + nsAutoPtr > mChangeCallbacks; + nsRefPtr mImageElement; +}; + +namespace mozilla { +namespace dom { + +class CustomElementHashKey : public PLDHashEntryHdr +{ +public: + typedef CustomElementHashKey *KeyType; + typedef const CustomElementHashKey *KeyTypePointer; + + CustomElementHashKey(int32_t aNamespaceID, nsIAtom *aAtom) + : mNamespaceID(aNamespaceID), + mAtom(aAtom) + {} + CustomElementHashKey(const CustomElementHashKey *aKey) + : mNamespaceID(aKey->mNamespaceID), + mAtom(aKey->mAtom) + {} + ~CustomElementHashKey() + {} + + KeyType GetKey() const { return const_cast(this); } + bool KeyEquals(const KeyTypePointer aKey) const + { + MOZ_ASSERT(mNamespaceID != kNameSpaceID_Unknown, + "This equals method is not transitive, nor symmetric. " + "A key with a namespace of kNamespaceID_Unknown should " + "not be stored in a hashtable."); + return (kNameSpaceID_Unknown == aKey->mNamespaceID || + mNamespaceID == aKey->mNamespaceID) && + aKey->mAtom == mAtom; + } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; } + static PLDHashNumber HashKey(const KeyTypePointer aKey) + { + return aKey->mAtom->hash(); + } + enum { ALLOW_MEMMOVE = true }; + +private: + int32_t mNamespaceID; + nsCOMPtr mAtom; +}; + +struct LifecycleCallbackArgs +{ + nsString name; + nsString oldValue; + nsString newValue; +}; + +struct CustomElementData; + +class CustomElementCallback +{ +public: + CustomElementCallback(Element* aThisObject, + nsIDocument::ElementCallbackType aCallbackType, + mozilla::dom::CallbackFunction* aCallback, + CustomElementData* aOwnerData); + void Traverse(nsCycleCollectionTraversalCallback& aCb) const; + void Call(); + void SetArgs(LifecycleCallbackArgs& aArgs) + { + MOZ_ASSERT(mType == nsIDocument::eAttributeChanged, + "Arguments are only used by attribute changed callback."); + mArgs = aArgs; + } + +private: + // The this value to use for invocation of the callback. + nsRefPtr mThisObject; + nsRefPtr mCallback; + // The type of callback (eCreated, eAttached, etc.) + nsIDocument::ElementCallbackType mType; + // Arguments to be passed to the callback, + // used by the attribute changed callback. + LifecycleCallbackArgs mArgs; + // CustomElementData that contains this callback in the + // callback queue. + CustomElementData* mOwnerData; +}; + +// Each custom element has an associated callback queue and an element is +// being created flag. +struct CustomElementData +{ + CustomElementData(nsIAtom* aType); + // Objects in this array are transient and empty after each microtask + // checkpoint. + nsTArray> mCallbackQueue; + // Custom element type, for