/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Chris Waterson * Dan Rosen * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef nsXULDocument_h__ #define nsXULDocument_h__ #include "nsCOMPtr.h" #include "nsXULPrototypeDocument.h" #include "nsXULPrototypeCache.h" #include "nsTArray.h" #include "nsXMLDocument.h" #include "nsForwardReference.h" #include "nsIContent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMXULCommandDispatcher.h" #include "nsIDOMXULDocument.h" #include "nsCOMArray.h" #include "nsIURI.h" #include "nsIXULDocument.h" #include "nsScriptLoader.h" #include "nsIStreamListener.h" #include "nsICSSLoaderObserver.h" class nsIRDFResource; class nsIRDFService; class nsIXULPrototypeCache; class nsPIWindowRoot; #if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript)) class nsIObjectInputStream; class nsIObjectOutputStream; class nsIXULPrototypeScript; #else #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" #include "nsXULElement.h" #endif #include "nsURIHashKey.h" #include "nsInterfaceHashtable.h" struct JSObject; struct PRLogModuleInfo; class nsRefMapEntry : public nsISupportsHashKey { public: nsRefMapEntry(const nsISupports* aKey) : nsISupportsHashKey(aKey) { } nsRefMapEntry(const nsRefMapEntry& aOther) : nsISupportsHashKey(GetKey()) { NS_ERROR("Should never be called"); } nsIContent* GetFirstContent(); void AppendAll(nsCOMArray* aElements); /** * @return true if aContent was added, false if we failed due to OOM */ PRBool AddContent(nsIContent* aContent); /** * @return true if aContent was removed and it was the last content for * this ref, so this entry should be removed from the map */ PRBool RemoveContent(nsIContent* aContent); private: nsSmallVoidArray mRefContentList; }; /** * The XUL document class */ class nsXULDocument : public nsXMLDocument, public nsIXULDocument, public nsIDOMXULDocument, public nsIStreamLoaderObserver, public nsICSSLoaderObserver { public: nsXULDocument(); virtual ~nsXULDocument(); // nsISupports interface NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSISTREAMLOADEROBSERVER // nsIDocument interface virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup); virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup, nsIPrincipal* aPrincipal); virtual nsresult StartDocumentLoad(const char* aCommand, nsIChannel *channel, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, PRBool aReset = PR_TRUE, nsIContentSink* aSink = nsnull); virtual void SetContentType(const nsAString& aContentType); virtual void EndLoad(); // nsIMutationObserver interface NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE // nsIXULDocument interface NS_IMETHOD AddElementForID(nsIContent* aElement); NS_IMETHOD GetElementsForID(const nsAString& aID, nsCOMArray& aElements); NS_IMETHOD GetScriptGlobalObjectOwner(nsIScriptGlobalObjectOwner** aGlobalOwner); NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement); NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement); NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder* aBuilder); NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder** aResult); NS_IMETHOD OnPrototypeLoadDone(PRBool aResumeWalk); PRBool OnDocumentParserError(); // nsIDOMNode interface overrides NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval); // nsIDOMDocument interface overrides NS_IMETHOD GetElementById(const nsAString & elementId, nsIDOMElement **_retval); // nsIDOMXULDocument interface NS_DECL_NSIDOMXULDOCUMENT // nsIDOMNSDocument NS_IMETHOD GetContentType(nsAString& aContentType); // nsICSSLoaderObserver NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet* aSheet, PRBool aWasAlternate, nsresult aStatus); virtual void EndUpdate(nsUpdateType aUpdateType); virtual PRBool IsDocumentRightToLeft(); virtual void ResetDocumentDirection(); virtual int GetDocumentLWTheme(); virtual void ResetDocumentLWTheme() { mDocLWTheme = Doc_Theme_Uninitialized; } static PRBool MatchAttribute(nsIContent* aContent, PRInt32 aNameSpaceID, nsIAtom* aAttrName, void* aData); NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULDocument, nsXMLDocument) protected: // Implementation methods friend nsresult NS_NewXULDocument(nsIXULDocument** aResult); nsresult Init(void); nsresult StartLayout(void); nsresult AddElementToRefMap(nsIContent* aElement); void RemoveElementFromRefMap(nsIContent* aElement); nsresult GetViewportSize(PRInt32* aWidth, PRInt32* aHeight); nsresult PrepareToLoad(nsISupports* aContainer, const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup, nsIParser** aResult); nsresult PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand, nsIPrincipal* aDocumentPrincipal, nsIParser** aResult); nsresult LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic, PRBool* aShouldReturn, PRBool* aFailureFromContent); nsresult ApplyPersistentAttributes(); nsresult ApplyPersistentAttributesInternal(); nsresult ApplyPersistentAttributesToElements(nsIRDFResource* aResource, nsCOMArray& aElements); nsresult AddElementToDocumentPre(nsIContent* aElement); nsresult AddElementToDocumentPost(nsIContent* aElement); nsresult ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, nsIDOMElement* aListener, nsIAtom* aAttr); already_AddRefed GetWindowRoot(); PRInt32 GetDefaultNamespaceID() const { return kNameSpaceID_XUL; } static NS_HIDDEN_(int) DirectionChanged(const char* aPrefName, void* aData); // pseudo constants static PRInt32 gRefCnt; static nsIAtom** kIdentityAttrs[]; static nsIRDFService* gRDFService; static nsIRDFResource* kNC_persist; static nsIRDFResource* kNC_attribute; static nsIRDFResource* kNC_value; static nsXULPrototypeCache* gXULCache; static PRLogModuleInfo* gXULLog; PRBool IsCapabilityEnabled(const char* aCapabilityLabel); nsresult Persist(nsIContent* aElement, PRInt32 aNameSpaceID, nsIAtom* aAttribute); // IMPORTANT: The ownership implicit in the following member // variables has been explicitly checked and set using nsCOMPtr // for owning pointers and raw COM interface pointers for weak // (ie, non owning) references. If you add any members to this // class, please make the ownership explicit (pinkerton, scc). // NOTE, THIS IS STILL IN PROGRESS, TALK TO PINK OR SCC BEFORE // CHANGING nsXULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr // Tracks elements with a 'ref' attribute, or an 'id' attribute where // the element's namespace has no registered ID attribute name. nsTHashtable mRefMap; nsCOMPtr mLocalStore; PRPackedBool mApplyingPersistedAttrs; PRPackedBool mIsWritingFastLoad; PRPackedBool mDocumentLoaded; /** * Since ResumeWalk is interruptible, it's possible that last * stylesheet finishes loading while the PD walk is still in * progress (waiting for an overlay to finish loading). * mStillWalking prevents DoneLoading (and StartLayout) from being * called in this situation. */ PRPackedBool mStillWalking; /** * An array of style sheets, that will be added (preserving order) to the * document after all of them are loaded (in DoneWalking). */ nsCOMArray mOverlaySheets; nsCOMPtr mCommandDispatcher; // [OWNER] of the focus tracker // Maintains the template builders that have been attached to // content elements typedef nsInterfaceHashtable BuilderTable; BuilderTable* mTemplateBuilderTable; PRUint32 mPendingSheets; /* * XXX dr * ------ * We used to have two pointers into the content model: mPopupNode and * mTooltipNode, which were used to retrieve the objects triggering a * popup or tooltip. You need that access because your reference has * disappeared by the time you click on a popup item or do whatever * with a tooltip. These were owning references (no cycles, as pinkerton * pointed out, since we're still parent-child). */ nsCOMPtr mTooltipNode; // [OWNER] element triggering the tooltip /** * document lightweight theme for use with :-moz-lwtheme, :-moz-lwtheme-brighttext * and :-moz-lwtheme-darktext */ DocumentTheme mDocLWTheme; /** * Context stack, which maintains the state of the Builder and allows * it to be interrupted. */ class ContextStack { protected: struct Entry { nsXULPrototypeElement* mPrototype; nsIContent* mElement; PRInt32 mIndex; Entry* mNext; }; Entry* mTop; PRInt32 mDepth; public: ContextStack(); ~ContextStack(); PRInt32 Depth() { return mDepth; } nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement); nsresult Pop(); nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement, PRInt32* aIndex); nsresult SetTopIndex(PRInt32 aIndex); PRBool IsInsideXULTemplate(); }; friend class ContextStack; ContextStack mContextStack; enum State { eState_Master, eState_Overlay }; State mState; /** * An array of overlay nsIURIs that have yet to be resolved. The * order of the array is significant: overlays at the _end_ of the * array are resolved before overlays earlier in the array (i.e., * it is a stack). * * In the current implementation the order the overlays are loaded * in is as follows: first overlays from xul-overlay PIs, in the * same order as in the document, then the overlays from the chrome * registry. */ nsCOMArray mUnloadedOverlays; /** * Load the transcluded script at the specified URI. If the * prototype construction must 'block' until the load has * completed, aBlock will be set to true. */ nsresult LoadScript(nsXULPrototypeScript *aScriptProto, PRBool* aBlock); /** * Execute the precompiled script object scoped by this XUL document's * containing window object, and using its associated script context. */ nsresult ExecuteScript(nsIScriptContext *aContext, void* aScriptObject); /** * Helper method for the above that uses aScript to find the appropriate * script context and object. */ nsresult ExecuteScript(nsXULPrototypeScript *aScript); /** * Create a delegate content model element from a prototype. * Note that the resulting content node is not bound to any tree */ nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, nsIContent** aResult); /** * Create a hook-up element to which content nodes can be attached for * later resolution. */ nsresult CreateOverlayElement(nsXULPrototypeElement* aPrototype, nsIContent** aResult); /** * Add attributes from the prototype to the element. */ nsresult AddAttributes(nsXULPrototypeElement* aPrototype, nsIContent* aElement); /** * The prototype-script of the current transcluded script that is being * loaded. For document.write('