Back to index

lightning-sunbird  0.9+nobinonly
nsXULDocument.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim: set ts=4 sw=4 et tw=78: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Chris Waterson <waterson@netscape.com>
00025  *   Dan Rosen <dr@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #ifndef nsXULDocument_h__
00042 #define nsXULDocument_h__
00043 
00044 #include "nsCOMPtr.h"
00045 #include "nsXMLDocument.h"
00046 #include "nsElementMap.h"
00047 #include "nsForwardReference.h"
00048 #include "nsIContent.h"
00049 #include "nsIDOMEventReceiver.h"
00050 #include "nsXULCommandDispatcher.h"
00051 #include "nsIDOMXULDocument.h"
00052 #include "nsISupportsArray.h"
00053 #include "nsCOMArray.h"
00054 #include "nsIURI.h"
00055 #include "nsIXULDocument.h"
00056 #include "nsIXULPrototypeDocument.h"
00057 #include "nsScriptLoader.h"
00058 #include "nsIStreamListener.h"
00059 
00060 class nsIRDFResource;
00061 class nsIRDFService;
00062 class nsIXULPrototypeCache;
00063 class nsIFocusController;
00064 #if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript))
00065 class nsIObjectInputStream;
00066 class nsIObjectOutputStream;
00067 class nsIXULPrototypeScript;
00068 #else
00069 #include "nsIObjectInputStream.h"
00070 #include "nsIObjectOutputStream.h"
00071 #include "nsXULElement.h"
00072 #endif
00073 #include "nsURIHashKey.h"
00074 #include "nsInterfaceHashtable.h"
00075  
00076 struct JSObject;
00077 struct PRLogModuleInfo;
00078 
00079 #include "nsIFastLoadService.h"         // XXXbe temporary?
00080 
00084 class nsXULDocument : public nsXMLDocument,
00085                       public nsIXULDocument,
00086                       public nsIDOMXULDocument2,
00087                       public nsIDOMXULDocument_MOZILLA_1_8_BRANCH,
00088                       public nsIStreamLoaderObserver
00089 {
00090 public:
00091     nsXULDocument();
00092     virtual ~nsXULDocument();
00093 
00094     // nsISupports interface
00095     NS_DECL_ISUPPORTS_INHERITED
00096     NS_DECL_NSISTREAMLOADEROBSERVER
00097 
00098     // nsIDocument interface
00099     virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
00100     virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup);
00101 
00102     virtual nsresult StartDocumentLoad(const char* aCommand,
00103                                        nsIChannel *channel,
00104                                        nsILoadGroup* aLoadGroup,
00105                                        nsISupports* aContainer,
00106                                        nsIStreamListener **aDocListener,
00107                                        PRBool aReset = PR_TRUE,
00108                                        nsIContentSink* aSink = nsnull);
00109 
00110     virtual nsIPrincipal* GetPrincipal();
00111 
00112     virtual void SetPrincipal(nsIPrincipal *aPrincipal);
00113 
00114     virtual void SetContentType(const nsAString& aContentType);
00115 
00116     virtual void EndLoad();
00117 
00118     virtual void ContentAppended(nsIContent* aContainer,
00119                                  PRInt32 aNewIndexInContainer);
00120 
00121     virtual void ContentInserted(nsIContent* aContainer,
00122                                  nsIContent* aChild,
00123                                  PRInt32 aIndexInContainer);
00124 
00125     virtual void ContentRemoved(nsIContent* aContainer,
00126                                 nsIContent* aChild,
00127                                 PRInt32 aIndexInContainer);
00128 
00129     virtual void AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
00130                                   nsIAtom* aAttribute, PRInt32 aModType);
00131 
00132     virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
00133                                     nsEvent* aEvent,
00134                                     nsIDOMEvent** aDOMEvent,
00135                                     PRUint32 aFlags,
00136                                     nsEventStatus* aEventStatus);
00137 
00138     // nsIXULDocument interface
00139     NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement);
00140     NS_IMETHOD RemoveElementForID(const nsAString& aID, nsIContent* aElement);
00141     NS_IMETHOD GetElementsForID(const nsAString& aID,
00142                                 nsISupportsArray* aElements);
00143     NS_IMETHOD AddForwardReference(nsForwardReference* aRef);
00144     NS_IMETHOD ResolveForwardReferences();
00145     NS_IMETHOD SetMasterPrototype(nsIXULPrototypeDocument* aDocument);
00146     NS_IMETHOD GetMasterPrototype(nsIXULPrototypeDocument** aDocument);
00147     NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument);
00148     NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement);
00149     NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement);
00150     NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent,
00151                                      nsIXULTemplateBuilder* aBuilder);
00152     NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent,
00153                                      nsIXULTemplateBuilder** aResult);
00154     NS_IMETHOD OnPrototypeLoadDone();
00155     NS_IMETHOD OnHide();
00156 
00157     // nsIDOMNode interface overrides
00158     NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval);
00159 
00160     // nsIDOMDocument interface overrides
00161     NS_IMETHOD GetElementById(const nsAString & elementId,
00162                               nsIDOMElement **_retval); 
00163 
00164     // nsIDOMXULDocument interface
00165     NS_DECL_NSIDOMXULDOCUMENT
00166     NS_DECL_NSIDOMXULDOCUMENT2
00167     NS_DECL_NSIDOMXULDOCUMENT_MOZILLA_1_8_BRANCH
00168 
00169     // nsIDOMNSDocument
00170     NS_IMETHOD GetContentType(nsAString& aContentType);
00171 
00172     static PRBool
00173     MatchAttribute(nsIContent* aContent,
00174                    PRInt32 aNameSpaceID,
00175                    nsIAtom* aAttrName,
00176                    const nsAString& aValue);
00177 
00178 protected:
00179     // Implementation methods
00180     friend nsresult
00181     NS_NewXULDocument(nsIXULDocument** aResult);
00182 
00183     nsresult Init(void);
00184     nsresult StartLayout(void);
00185 
00186     nsresult
00187     AddElementToMap(nsIContent* aElement);
00188 
00189     nsresult
00190     RemoveElementFromMap(nsIContent* aElement);
00191 
00192     nsresult GetPixelDimensions(nsIPresShell* aShell, PRInt32* aWidth,
00193                                 PRInt32* aHeight);
00194 
00195     static PRIntn
00196     RemoveElementsFromMapByContent(const PRUnichar* aID,
00197                                    nsIContent* aElement,
00198                                    void* aClosure);
00199 
00200     void SetIsPopup(PRBool isPopup) { mIsPopup = isPopup; };
00201 
00202     nsresult PrepareToLoad(nsISupports* aContainer,
00203                            const char* aCommand,
00204                            nsIChannel* aChannel,
00205                            nsILoadGroup* aLoadGroup,
00206                            nsIParser** aResult);
00207 
00208     nsresult
00209     PrepareToLoadPrototype(nsIURI* aURI,
00210                            const char* aCommand,
00211                            nsIPrincipal* aDocumentPrincipal,
00212                            nsIParser** aResult);
00213 
00214     nsresult 
00215     LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic, PRBool* aShouldReturn);
00216 
00217     nsresult ApplyPersistentAttributes();
00218     nsresult ApplyPersistentAttributesToElements(nsIRDFResource* aResource,
00219                                                  nsISupportsArray* aElements);
00220 
00221     nsresult
00222     AddElementToDocumentPre(nsIContent* aElement);
00223 
00224     nsresult
00225     AddElementToDocumentPost(nsIContent* aElement);
00226 
00227     nsresult
00228     ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
00229                                  nsIDOMElement* aListener,
00230                                  nsIAtom* aAttr);
00231 
00232     void GetFocusController(nsIFocusController** aFocusController);
00233 
00234     PRInt32 GetDefaultNamespaceID() const
00235     {
00236         return kNameSpaceID_XUL;
00237     };
00238 
00239 protected:
00240     // pseudo constants
00241     static PRInt32 gRefCnt;
00242 
00243     static nsIAtom** kIdentityAttrs[];
00244 
00245     static nsIRDFService* gRDFService;
00246     static nsIRDFResource* kNC_persist;
00247     static nsIRDFResource* kNC_attribute;
00248     static nsIRDFResource* kNC_value;
00249 
00250     static nsIXULPrototypeCache* gXULCache;
00251 
00252     static PRLogModuleInfo* gXULLog;
00253 
00254     nsresult
00255     Persist(nsIContent* aElement, PRInt32 aNameSpaceID, nsIAtom* aAttribute);
00256 
00257     nsresult
00258     DestroyForwardReferences();
00259 
00260     // IMPORTANT: The ownership implicit in the following member
00261     // variables has been explicitly checked and set using nsCOMPtr
00262     // for owning pointers and raw COM interface pointers for weak
00263     // (ie, non owning) references. If you add any members to this
00264     // class, please make the ownership explicit (pinkerton, scc).
00265     // NOTE, THIS IS STILL IN PROGRESS, TALK TO PINK OR SCC BEFORE
00266     // CHANGING
00267 
00268     nsXULDocument*             mNextSrcLoadWaiter;  // [OWNER] but not COMPtr
00269 
00270     nsElementMap               mElementMap;
00271     nsCOMPtr<nsIRDFDataSource> mLocalStore;
00272     PRPackedBool               mIsPopup;
00273     PRPackedBool               mIsFastLoad;
00274     PRPackedBool               mApplyingPersistedAttrs;
00275     PRPackedBool               mIsWritingFastLoad;
00276     PRPackedBool               mDocumentLoaded;
00277     nsRefPtr<nsXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker
00278 
00279     // Maintains the template builders that have been attached to
00280     // content elements
00281     nsSupportsHashtable* mTemplateBuilderTable;
00282     
00283     nsVoidArray mForwardReferences;
00284     nsForwardReference::Phase mResolutionPhase;
00285 
00286     /*
00287      * XXX dr
00288      * ------
00289      * We used to have two pointers into the content model: mPopupNode and
00290      * mTooltipNode, which were used to retrieve the objects triggering a
00291      * popup or tooltip. You need that access because your reference has
00292      * disappeared by the time you click on a popup item or do whatever
00293      * with a tooltip. These were owning references (no cycles, as pinkerton
00294      * pointed out, since we're still parent-child).
00295      *
00296      * We still have mTooltipNode, but mPopupNode has moved to the
00297      * FocusController. The APIs (IDL attributes popupNode and tooltipNode)
00298      * are still here for compatibility and ease of use, but we should
00299      * probably move the mTooltipNode over to FocusController at some point
00300      * as well, for consistency.
00301      */
00302 
00303     nsCOMPtr<nsIDOMNode>    mTooltipNode;          // [OWNER] element triggering the tooltip
00304 
00309     class ContextStack {
00310     protected:
00311         struct Entry {
00312             nsXULPrototypeElement* mPrototype;
00313             nsIContent*            mElement;
00314             PRInt32                mIndex;
00315             Entry*                 mNext;
00316         };
00317 
00318         Entry* mTop;
00319         PRInt32 mDepth;
00320 
00321     public:
00322         ContextStack();
00323         ~ContextStack();
00324 
00325         PRInt32 Depth() { return mDepth; }
00326 
00327         nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement);
00328         nsresult Pop();
00329         nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement, PRInt32* aIndex);
00330 
00331         nsresult SetTopIndex(PRInt32 aIndex);
00332 
00333         PRBool IsInsideXULTemplate();
00334     };
00335 
00336     friend class ContextStack;
00337     ContextStack mContextStack;
00338 
00339     enum State { eState_Master, eState_Overlay };
00340     State mState;
00341 
00348     nsCOMPtr<nsISupportsArray> mUnloadedOverlays;
00349 
00355     nsresult LoadScript(nsXULPrototypeScript *aScriptProto, PRBool* aBlock);
00356 
00361     nsresult ExecuteScript(JSObject* aScriptObject);
00362 
00367     nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
00368                                         nsIContent** aResult);
00369 
00374     nsresult CreateOverlayElement(nsXULPrototypeElement* aPrototype, nsIContent** aResult);
00375 
00379     nsresult AddAttributes(nsXULPrototypeElement* aPrototype, nsIContent* aElement);
00380 
00387     nsXULPrototypeScript* mCurrentScriptProto;
00388 
00393     nsCOMPtr<nsIRequest> mPlaceHolderRequest;
00394         
00398     static nsresult
00399     CheckTemplateBuilderHookup(nsIContent* aElement, PRBool* aNeedsHookup);
00400 
00404     static nsresult
00405     CreateTemplateBuilder(nsIContent* aElement);
00406 
00410     nsresult HookupObserver(nsIContent* aElement);
00411 
00415     nsresult AddPrototypeSheets();
00416 
00420     class BroadcasterHookup : public nsForwardReference
00421     {
00422     protected:
00423         nsXULDocument* mDocument;              // [WEAK]
00424         nsCOMPtr<nsIContent> mObservesElement; // [OWNER]
00425         PRBool mResolved;
00426 
00427     public:
00428         BroadcasterHookup(nsXULDocument* aDocument,
00429                           nsIContent* aObservesElement)
00430             : mDocument(aDocument),
00431               mObservesElement(aObservesElement),
00432               mResolved(PR_FALSE)
00433         {
00434         }
00435 
00436         virtual ~BroadcasterHookup();
00437 
00438         virtual Phase GetPhase() { return eHookup; }
00439         virtual Result Resolve();
00440     };
00441 
00442     friend class BroadcasterHookup;
00443 
00444 
00448     class OverlayForwardReference : public nsForwardReference
00449     {
00450     protected:
00451         nsXULDocument* mDocument;      // [WEAK]
00452         nsCOMPtr<nsIContent> mOverlay; // [OWNER]
00453         PRBool mResolved;
00454 
00455         nsresult Merge(nsIContent* aTargetNode, nsIContent* aOverlayNode, PRBool aNotify);
00456 
00457     public:
00458         OverlayForwardReference(nsXULDocument* aDocument, nsIContent* aOverlay)
00459             : mDocument(aDocument), mOverlay(aOverlay), mResolved(PR_FALSE) {}
00460 
00461         virtual ~OverlayForwardReference();
00462 
00463         virtual Phase GetPhase() { return eConstruction; }
00464         virtual Result Resolve();
00465     };
00466 
00467     friend class OverlayForwardReference;
00468 
00469     class TemplateBuilderHookup : public nsForwardReference
00470     {
00471     protected:
00472         nsCOMPtr<nsIContent> mElement; // [OWNER]
00473 
00474     public:
00475         TemplateBuilderHookup(nsIContent* aElement)
00476             : mElement(aElement) {}
00477 
00478         virtual Phase GetPhase() { return eHookup; }
00479         virtual Result Resolve();
00480     };
00481 
00482     friend class TemplateBuilderHookup;
00483 
00484     // The out params of FindBroadcaster only have values that make sense when
00485     // the method returns NS_FINDBROADCASTER_FOUND.  In all other cases, the
00486     // values of the out params should not be relied on (though *aListener and
00487     // *aBroadcaster do need to be released if non-null, of course).
00488     nsresult
00489     FindBroadcaster(nsIContent* aElement,
00490                     nsIDOMElement** aListener,
00491                     nsString& aBroadcasterID,
00492                     nsString& aAttribute,
00493                     nsIDOMElement** aBroadcaster);
00494 
00495     nsresult
00496     CheckBroadcasterHookup(nsIContent* aElement,
00497                            PRBool* aNeedsHookup,
00498                            PRBool* aDidResolve);
00499 
00500     void
00501     SynchronizeBroadcastListener(nsIDOMElement   *aBroadcaster,
00502                                  nsIDOMElement   *aListener,
00503                                  const nsAString &aAttr);
00504 
00505     static
00506     nsresult
00507     InsertElement(nsIContent* aParent, nsIContent* aChild, PRBool aNotify);
00508 
00509     static 
00510     nsresult
00511     RemoveElement(nsIContent* aParent, nsIContent* aChild);
00512 
00517     nsCOMPtr<nsIXULPrototypeDocument> mCurrentPrototype;
00518 
00523     nsCOMPtr<nsIXULPrototypeDocument> mMasterPrototype;
00524 
00529     nsCOMArray<nsIXULPrototypeDocument> mPrototypes;
00530 
00534     nsresult PrepareToWalk();
00535 
00540     nsresult AddChromeOverlays();
00541 
00546     nsresult ResumeWalk();
00547 
00552     void ReportMissingOverlay(nsIURI* aURI);
00553     
00554 #if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
00555     // timing
00556     nsTime mLoadStart;
00557 #endif
00558 
00559     class CachedChromeStreamListener : public nsIStreamListener {
00560     protected:
00561         nsXULDocument* mDocument;
00562         PRPackedBool   mProtoLoaded;
00563 
00564         virtual ~CachedChromeStreamListener();
00565 
00566     public:
00567         CachedChromeStreamListener(nsXULDocument* aDocument,
00568                                    PRBool aProtoLoaded);
00569 
00570         NS_DECL_ISUPPORTS
00571         NS_DECL_NSIREQUESTOBSERVER
00572         NS_DECL_NSISTREAMLISTENER
00573     };
00574 
00575     friend class CachedChromeStreamListener;
00576 
00577 
00578     class ParserObserver : public nsIRequestObserver {
00579     protected:
00580         nsXULDocument* mDocument;
00581         virtual ~ParserObserver();
00582 
00583     public:
00584         ParserObserver(nsXULDocument* aDocument);
00585 
00586         NS_DECL_ISUPPORTS
00587         NS_DECL_NSIREQUESTOBSERVER
00588     };
00589 
00590     friend class ParserObserver;
00591 
00595     PLDHashTable* mBroadcasterMap;
00596 
00597     nsInterfaceHashtable<nsURIHashKey,nsIObserver> mOverlayLoadObservers;
00598     nsInterfaceHashtable<nsURIHashKey,nsIObserver> mPendingOverlayLoadNotifications;
00599     
00600     PRBool mInitialLayoutComplete;
00601 private:
00602     // helpers
00603 
00604 };
00605 
00606 #endif // nsXULDocument_h__