1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/xul/document/src/XULDocument.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,790 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_dom_XULDocument_h 1.10 +#define mozilla_dom_XULDocument_h 1.11 + 1.12 +#include "nsCOMPtr.h" 1.13 +#include "nsXULPrototypeDocument.h" 1.14 +#include "nsXULPrototypeCache.h" 1.15 +#include "nsTArray.h" 1.16 + 1.17 +#include "mozilla/dom/XMLDocument.h" 1.18 +#include "nsForwardReference.h" 1.19 +#include "nsIContent.h" 1.20 +#include "nsIDOMXULCommandDispatcher.h" 1.21 +#include "nsIDOMXULDocument.h" 1.22 +#include "nsCOMArray.h" 1.23 +#include "nsIURI.h" 1.24 +#include "nsIXULDocument.h" 1.25 +#include "nsScriptLoader.h" 1.26 +#include "nsIStreamListener.h" 1.27 +#include "nsICSSLoaderObserver.h" 1.28 + 1.29 +#include "mozilla/Attributes.h" 1.30 + 1.31 +#include "js/TracingAPI.h" 1.32 +#include "js/TypeDecls.h" 1.33 + 1.34 +class nsIRDFResource; 1.35 +class nsIRDFService; 1.36 +class nsPIWindowRoot; 1.37 +#if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript)) 1.38 +class nsIObjectInputStream; 1.39 +class nsIObjectOutputStream; 1.40 +class nsIXULPrototypeScript; 1.41 +#else 1.42 +#include "nsIObjectInputStream.h" 1.43 +#include "nsIObjectOutputStream.h" 1.44 +#include "nsXULElement.h" 1.45 +#endif 1.46 +#include "nsURIHashKey.h" 1.47 +#include "nsInterfaceHashtable.h" 1.48 + 1.49 +struct PRLogModuleInfo; 1.50 + 1.51 +class nsRefMapEntry : public nsStringHashKey 1.52 +{ 1.53 +public: 1.54 + nsRefMapEntry(const nsAString& aKey) : 1.55 + nsStringHashKey(&aKey) 1.56 + { 1.57 + } 1.58 + nsRefMapEntry(const nsAString *aKey) : 1.59 + nsStringHashKey(aKey) 1.60 + { 1.61 + } 1.62 + nsRefMapEntry(const nsRefMapEntry& aOther) : 1.63 + nsStringHashKey(&aOther.GetKey()) 1.64 + { 1.65 + NS_ERROR("Should never be called"); 1.66 + } 1.67 + 1.68 + mozilla::dom::Element* GetFirstElement(); 1.69 + void AppendAll(nsCOMArray<nsIContent>* aElements); 1.70 + /** 1.71 + * @return true if aElement was added, false if we failed due to OOM 1.72 + */ 1.73 + bool AddElement(mozilla::dom::Element* aElement); 1.74 + /** 1.75 + * @return true if aElement was removed and it was the last content for 1.76 + * this ref, so this entry should be removed from the map 1.77 + */ 1.78 + bool RemoveElement(mozilla::dom::Element* aElement); 1.79 + 1.80 +private: 1.81 + nsSmallVoidArray mRefContentList; 1.82 +}; 1.83 + 1.84 +/** 1.85 + * The XUL document class 1.86 + */ 1.87 + 1.88 +namespace mozilla { 1.89 +namespace dom { 1.90 + 1.91 +class XULDocument MOZ_FINAL : public XMLDocument, 1.92 + public nsIXULDocument, 1.93 + public nsIDOMXULDocument, 1.94 + public nsIStreamLoaderObserver, 1.95 + public nsICSSLoaderObserver, 1.96 + public nsIOffThreadScriptReceiver 1.97 +{ 1.98 +public: 1.99 + XULDocument(); 1.100 + virtual ~XULDocument(); 1.101 + 1.102 + // nsISupports interface 1.103 + NS_DECL_ISUPPORTS_INHERITED 1.104 + NS_DECL_NSISTREAMLOADEROBSERVER 1.105 + 1.106 + // nsIDocument interface 1.107 + virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) MOZ_OVERRIDE; 1.108 + virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup, 1.109 + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; 1.110 + 1.111 + virtual nsresult StartDocumentLoad(const char* aCommand, 1.112 + nsIChannel *channel, 1.113 + nsILoadGroup* aLoadGroup, 1.114 + nsISupports* aContainer, 1.115 + nsIStreamListener **aDocListener, 1.116 + bool aReset = true, 1.117 + nsIContentSink* aSink = nullptr) MOZ_OVERRIDE; 1.118 + 1.119 + virtual void SetContentType(const nsAString& aContentType) MOZ_OVERRIDE; 1.120 + 1.121 + virtual void EndLoad() MOZ_OVERRIDE; 1.122 + 1.123 + // nsIMutationObserver interface 1.124 + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED 1.125 + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED 1.126 + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED 1.127 + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED 1.128 + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE 1.129 + 1.130 + // nsIXULDocument interface 1.131 + virtual void GetElementsForID(const nsAString& aID, 1.132 + nsCOMArray<nsIContent>& aElements) MOZ_OVERRIDE; 1.133 + 1.134 + NS_IMETHOD AddSubtreeToDocument(nsIContent* aContent) MOZ_OVERRIDE; 1.135 + NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent) MOZ_OVERRIDE; 1.136 + NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent, 1.137 + nsIXULTemplateBuilder* aBuilder) MOZ_OVERRIDE; 1.138 + NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent, 1.139 + nsIXULTemplateBuilder** aResult) MOZ_OVERRIDE; 1.140 + NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) MOZ_OVERRIDE; 1.141 + bool OnDocumentParserError() MOZ_OVERRIDE; 1.142 + 1.143 + // nsINode interface overrides 1.144 + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; 1.145 + 1.146 + // nsIDOMNode interface 1.147 + NS_FORWARD_NSIDOMNODE_TO_NSINODE 1.148 + 1.149 + // nsIDOMDocument interface 1.150 + using nsDocument::CreateElement; 1.151 + using nsDocument::CreateElementNS; 1.152 + NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::) 1.153 + // And explicitly import the things from nsDocument that we just shadowed 1.154 + using nsDocument::GetImplementation; 1.155 + using nsDocument::GetTitle; 1.156 + using nsDocument::SetTitle; 1.157 + using nsDocument::GetLastStyleSheetSet; 1.158 + using nsDocument::MozSetImageElement; 1.159 + using nsDocument::GetMozFullScreenElement; 1.160 + using nsIDocument::GetLocation; 1.161 + 1.162 + // nsDocument interface overrides 1.163 + virtual Element* GetElementById(const nsAString & elementId) MOZ_OVERRIDE; 1.164 + 1.165 + // nsIDOMXULDocument interface 1.166 + NS_DECL_NSIDOMXULDOCUMENT 1.167 + 1.168 + // nsICSSLoaderObserver 1.169 + NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, 1.170 + bool aWasAlternate, 1.171 + nsresult aStatus) MOZ_OVERRIDE; 1.172 + 1.173 + virtual void EndUpdate(nsUpdateType aUpdateType) MOZ_OVERRIDE; 1.174 + 1.175 + virtual bool IsDocumentRightToLeft() MOZ_OVERRIDE; 1.176 + 1.177 + virtual void ResetDocumentDirection() MOZ_OVERRIDE; 1.178 + 1.179 + virtual int GetDocumentLWTheme() MOZ_OVERRIDE; 1.180 + 1.181 + virtual void ResetDocumentLWTheme() MOZ_OVERRIDE { mDocLWTheme = Doc_Theme_Uninitialized; } 1.182 + 1.183 + NS_IMETHOD OnScriptCompileComplete(JSScript* aScript, nsresult aStatus) MOZ_OVERRIDE; 1.184 + 1.185 + static bool 1.186 + MatchAttribute(nsIContent* aContent, 1.187 + int32_t aNameSpaceID, 1.188 + nsIAtom* aAttrName, 1.189 + void* aData); 1.190 + 1.191 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULDocument, XMLDocument) 1.192 + 1.193 + void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber); 1.194 + 1.195 + // WebIDL API 1.196 + already_AddRefed<nsINode> GetPopupNode(); 1.197 + void SetPopupNode(nsINode* aNode); 1.198 + already_AddRefed<nsINode> GetPopupRangeParent(ErrorResult& aRv); 1.199 + int32_t GetPopupRangeOffset(ErrorResult& aRv); 1.200 + already_AddRefed<nsINode> GetTooltipNode(); 1.201 + void SetTooltipNode(nsINode* aNode) { /* do nothing */ } 1.202 + nsIDOMXULCommandDispatcher* GetCommandDispatcher() const 1.203 + { 1.204 + return mCommandDispatcher; 1.205 + } 1.206 + int32_t GetWidth(ErrorResult& aRv); 1.207 + int32_t GetHeight(ErrorResult& aRv); 1.208 + already_AddRefed<nsINodeList> 1.209 + GetElementsByAttribute(const nsAString& aAttribute, 1.210 + const nsAString& aValue); 1.211 + already_AddRefed<nsINodeList> 1.212 + GetElementsByAttributeNS(const nsAString& aNamespaceURI, 1.213 + const nsAString& aAttribute, 1.214 + const nsAString& aValue, 1.215 + ErrorResult& aRv); 1.216 + void AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener, 1.217 + const nsAString& aAttr, ErrorResult& aRv); 1.218 + void RemoveBroadcastListenerFor(Element& aBroadcaster, Element& aListener, 1.219 + const nsAString& aAttr); 1.220 + void Persist(const nsAString& aId, const nsAString& aAttr, ErrorResult& aRv) 1.221 + { 1.222 + aRv = Persist(aId, aAttr); 1.223 + } 1.224 + using nsDocument::GetBoxObjectFor; 1.225 + void LoadOverlay(const nsAString& aURL, nsIObserver* aObserver, 1.226 + ErrorResult& aRv) 1.227 + { 1.228 + aRv = LoadOverlay(aURL, aObserver); 1.229 + } 1.230 + 1.231 +protected: 1.232 + // Implementation methods 1.233 + friend nsresult 1.234 + (::NS_NewXULDocument(nsIXULDocument** aResult)); 1.235 + 1.236 + nsresult Init(void) MOZ_OVERRIDE; 1.237 + nsresult StartLayout(void); 1.238 + 1.239 + nsresult 1.240 + AddElementToRefMap(Element* aElement); 1.241 + void 1.242 + RemoveElementFromRefMap(Element* aElement); 1.243 + 1.244 + nsresult GetViewportSize(int32_t* aWidth, int32_t* aHeight); 1.245 + 1.246 + nsresult PrepareToLoad(nsISupports* aContainer, 1.247 + const char* aCommand, 1.248 + nsIChannel* aChannel, 1.249 + nsILoadGroup* aLoadGroup, 1.250 + nsIParser** aResult); 1.251 + 1.252 + nsresult 1.253 + PrepareToLoadPrototype(nsIURI* aURI, 1.254 + const char* aCommand, 1.255 + nsIPrincipal* aDocumentPrincipal, 1.256 + nsIParser** aResult); 1.257 + 1.258 + nsresult 1.259 + LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic, bool* aShouldReturn, 1.260 + bool* aFailureFromContent); 1.261 + 1.262 + nsresult ApplyPersistentAttributes(); 1.263 + nsresult ApplyPersistentAttributesInternal(); 1.264 + nsresult ApplyPersistentAttributesToElements(nsIRDFResource* aResource, 1.265 + nsCOMArray<nsIContent>& aElements); 1.266 + 1.267 + nsresult 1.268 + AddElementToDocumentPre(Element* aElement); 1.269 + 1.270 + nsresult 1.271 + AddElementToDocumentPost(Element* aElement); 1.272 + 1.273 + nsresult 1.274 + ExecuteOnBroadcastHandlerFor(Element* aBroadcaster, 1.275 + Element* aListener, 1.276 + nsIAtom* aAttr); 1.277 + 1.278 + nsresult 1.279 + BroadcastAttributeChangeFromOverlay(nsIContent* aNode, 1.280 + int32_t aNameSpaceID, 1.281 + nsIAtom* aAttribute, 1.282 + nsIAtom* aPrefix, 1.283 + const nsAString& aValue); 1.284 + 1.285 + already_AddRefed<nsPIWindowRoot> GetWindowRoot(); 1.286 + 1.287 + static NS_HIDDEN_(void) DirectionChanged(const char* aPrefName, void* aData); 1.288 + 1.289 + // pseudo constants 1.290 + static int32_t gRefCnt; 1.291 + 1.292 + static nsIAtom** kIdentityAttrs[]; 1.293 + 1.294 + static nsIRDFService* gRDFService; 1.295 + static nsIRDFResource* kNC_persist; 1.296 + static nsIRDFResource* kNC_attribute; 1.297 + static nsIRDFResource* kNC_value; 1.298 + 1.299 + static PRLogModuleInfo* gXULLog; 1.300 + 1.301 + nsresult 1.302 + Persist(nsIContent* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute); 1.303 + 1.304 + virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE; 1.305 + 1.306 + // IMPORTANT: The ownership implicit in the following member 1.307 + // variables has been explicitly checked and set using nsCOMPtr 1.308 + // for owning pointers and raw COM interface pointers for weak 1.309 + // (ie, non owning) references. If you add any members to this 1.310 + // class, please make the ownership explicit (pinkerton, scc). 1.311 + // NOTE, THIS IS STILL IN PROGRESS, TALK TO PINK OR SCC BEFORE 1.312 + // CHANGING 1.313 + 1.314 + XULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr 1.315 + 1.316 + // Tracks elements with a 'ref' attribute, or an 'id' attribute where 1.317 + // the element's namespace has no registered ID attribute name. 1.318 + nsTHashtable<nsRefMapEntry> mRefMap; 1.319 + nsCOMPtr<nsIRDFDataSource> mLocalStore; 1.320 + bool mApplyingPersistedAttrs; 1.321 + bool mIsWritingFastLoad; 1.322 + bool mDocumentLoaded; 1.323 + /** 1.324 + * Since ResumeWalk is interruptible, it's possible that last 1.325 + * stylesheet finishes loading while the PD walk is still in 1.326 + * progress (waiting for an overlay to finish loading). 1.327 + * mStillWalking prevents DoneLoading (and StartLayout) from being 1.328 + * called in this situation. 1.329 + */ 1.330 + bool mStillWalking; 1.331 + 1.332 + /** 1.333 + * These two values control where persistent attributes get applied. 1.334 + */ 1.335 + bool mRestrictPersistence; 1.336 + nsTHashtable<nsStringHashKey> mPersistenceIds; 1.337 + 1.338 + /** 1.339 + * An array of style sheets, that will be added (preserving order) to the 1.340 + * document after all of them are loaded (in DoneWalking). 1.341 + */ 1.342 + nsTArray<nsRefPtr<nsCSSStyleSheet> > mOverlaySheets; 1.343 + 1.344 + nsCOMPtr<nsIDOMXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker 1.345 + 1.346 + // Maintains the template builders that have been attached to 1.347 + // content elements 1.348 + typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXULTemplateBuilder> 1.349 + BuilderTable; 1.350 + BuilderTable* mTemplateBuilderTable; 1.351 + 1.352 + uint32_t mPendingSheets; 1.353 + 1.354 + /** 1.355 + * document lightweight theme for use with :-moz-lwtheme, :-moz-lwtheme-brighttext 1.356 + * and :-moz-lwtheme-darktext 1.357 + */ 1.358 + DocumentTheme mDocLWTheme; 1.359 + 1.360 + /** 1.361 + * Context stack, which maintains the state of the Builder and allows 1.362 + * it to be interrupted. 1.363 + */ 1.364 + class ContextStack { 1.365 + protected: 1.366 + struct Entry { 1.367 + nsXULPrototypeElement* mPrototype; 1.368 + nsIContent* mElement; 1.369 + int32_t mIndex; 1.370 + Entry* mNext; 1.371 + }; 1.372 + 1.373 + Entry* mTop; 1.374 + int32_t mDepth; 1.375 + 1.376 + public: 1.377 + ContextStack(); 1.378 + ~ContextStack(); 1.379 + 1.380 + int32_t Depth() { return mDepth; } 1.381 + 1.382 + nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement); 1.383 + nsresult Pop(); 1.384 + nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement, int32_t* aIndex); 1.385 + 1.386 + nsresult SetTopIndex(int32_t aIndex); 1.387 + }; 1.388 + 1.389 + friend class ContextStack; 1.390 + ContextStack mContextStack; 1.391 + 1.392 + enum State { eState_Master, eState_Overlay }; 1.393 + State mState; 1.394 + 1.395 + /** 1.396 + * An array of overlay nsIURIs that have yet to be resolved. The 1.397 + * order of the array is significant: overlays at the _end_ of the 1.398 + * array are resolved before overlays earlier in the array (i.e., 1.399 + * it is a stack). 1.400 + * 1.401 + * In the current implementation the order the overlays are loaded 1.402 + * in is as follows: first overlays from xul-overlay PIs, in the 1.403 + * same order as in the document, then the overlays from the chrome 1.404 + * registry. 1.405 + */ 1.406 + nsTArray<nsCOMPtr<nsIURI> > mUnloadedOverlays; 1.407 + 1.408 + /** 1.409 + * Load the transcluded script at the specified URI. If the 1.410 + * prototype construction must 'block' until the load has 1.411 + * completed, aBlock will be set to true. 1.412 + */ 1.413 + nsresult LoadScript(nsXULPrototypeScript *aScriptProto, bool* aBlock); 1.414 + 1.415 + /** 1.416 + * Execute the precompiled script object scoped by this XUL document's 1.417 + * containing window object, and using its associated script context. 1.418 + */ 1.419 + nsresult ExecuteScript(nsIScriptContext *aContext, 1.420 + JS::Handle<JSScript*> aScriptObject); 1.421 + 1.422 + /** 1.423 + * Helper method for the above that uses aScript to find the appropriate 1.424 + * script context and object. 1.425 + */ 1.426 + nsresult ExecuteScript(nsXULPrototypeScript *aScript); 1.427 + 1.428 + /** 1.429 + * Create a delegate content model element from a prototype. 1.430 + * Note that the resulting content node is not bound to any tree 1.431 + */ 1.432 + nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, 1.433 + Element** aResult, 1.434 + bool aIsRoot); 1.435 + 1.436 + /** 1.437 + * Create a hook-up element to which content nodes can be attached for 1.438 + * later resolution. 1.439 + */ 1.440 + nsresult CreateOverlayElement(nsXULPrototypeElement* aPrototype, 1.441 + Element** aResult); 1.442 + 1.443 + /** 1.444 + * Add attributes from the prototype to the element. 1.445 + */ 1.446 + nsresult AddAttributes(nsXULPrototypeElement* aPrototype, nsIContent* aElement); 1.447 + 1.448 + /** 1.449 + * The prototype-script of the current transcluded script that is being 1.450 + * loaded. For document.write('<script src="nestedwrite.js"><\/script>') 1.451 + * to work, these need to be in a stack element type, and we need to hold 1.452 + * the top of stack here. 1.453 + */ 1.454 + nsXULPrototypeScript* mCurrentScriptProto; 1.455 + 1.456 + /** 1.457 + * Whether the current transcluded script is being compiled off thread. 1.458 + * The load event is blocked while this is in progress. 1.459 + */ 1.460 + bool mOffThreadCompiling; 1.461 + 1.462 + /** 1.463 + * If the current transcluded script is being compiled off thread, the 1.464 + * source for that script. 1.465 + */ 1.466 + jschar* mOffThreadCompileStringBuf; 1.467 + size_t mOffThreadCompileStringLength; 1.468 + 1.469 + /** 1.470 + * Check if a XUL template builder has already been hooked up. 1.471 + */ 1.472 + static nsresult 1.473 + CheckTemplateBuilderHookup(nsIContent* aElement, bool* aNeedsHookup); 1.474 + 1.475 + /** 1.476 + * Create a XUL template builder on the specified node. 1.477 + */ 1.478 + static nsresult 1.479 + CreateTemplateBuilder(nsIContent* aElement); 1.480 + 1.481 + /** 1.482 + * Add the current prototype's style sheets (currently it's just 1.483 + * style overlays from the chrome registry) to the document. 1.484 + */ 1.485 + nsresult AddPrototypeSheets(); 1.486 + 1.487 + 1.488 +protected: 1.489 + /* Declarations related to forward references. 1.490 + * 1.491 + * Forward references are declarations which are added to the temporary 1.492 + * list (mForwardReferences) during the document (or overlay) load and 1.493 + * are resolved later, when the document loading is almost complete. 1.494 + */ 1.495 + 1.496 + /** 1.497 + * The list of different types of forward references to resolve. After 1.498 + * a reference is resolved, it is removed from this array (and 1.499 + * automatically deleted) 1.500 + */ 1.501 + nsTArray<nsAutoPtr<nsForwardReference> > mForwardReferences; 1.502 + 1.503 + /** Indicates what kind of forward references are still to be processed. */ 1.504 + nsForwardReference::Phase mResolutionPhase; 1.505 + 1.506 + /** 1.507 + * Adds aRef to the mForwardReferences array. Takes the ownership of aRef. 1.508 + */ 1.509 + nsresult AddForwardReference(nsForwardReference* aRef); 1.510 + 1.511 + /** 1.512 + * Resolve all of the document's forward references. 1.513 + */ 1.514 + nsresult ResolveForwardReferences(); 1.515 + 1.516 + /** 1.517 + * Used to resolve broadcaster references 1.518 + */ 1.519 + class BroadcasterHookup : public nsForwardReference 1.520 + { 1.521 + protected: 1.522 + XULDocument* mDocument; // [WEAK] 1.523 + nsRefPtr<Element> mObservesElement; // [OWNER] 1.524 + bool mResolved; 1.525 + 1.526 + public: 1.527 + BroadcasterHookup(XULDocument* aDocument, 1.528 + Element* aObservesElement) 1.529 + : mDocument(aDocument), 1.530 + mObservesElement(aObservesElement), 1.531 + mResolved(false) 1.532 + { 1.533 + } 1.534 + 1.535 + virtual ~BroadcasterHookup(); 1.536 + 1.537 + virtual Phase GetPhase() MOZ_OVERRIDE { return eHookup; } 1.538 + virtual Result Resolve() MOZ_OVERRIDE; 1.539 + }; 1.540 + 1.541 + friend class BroadcasterHookup; 1.542 + 1.543 + 1.544 + /** 1.545 + * Used to hook up overlays 1.546 + */ 1.547 + class OverlayForwardReference : public nsForwardReference 1.548 + { 1.549 + protected: 1.550 + XULDocument* mDocument; // [WEAK] 1.551 + nsCOMPtr<nsIContent> mOverlay; // [OWNER] 1.552 + bool mResolved; 1.553 + 1.554 + nsresult Merge(nsIContent* aTargetNode, nsIContent* aOverlayNode, bool aNotify); 1.555 + 1.556 + public: 1.557 + OverlayForwardReference(XULDocument* aDocument, nsIContent* aOverlay) 1.558 + : mDocument(aDocument), mOverlay(aOverlay), mResolved(false) {} 1.559 + 1.560 + virtual ~OverlayForwardReference(); 1.561 + 1.562 + virtual Phase GetPhase() MOZ_OVERRIDE { return eConstruction; } 1.563 + virtual Result Resolve() MOZ_OVERRIDE; 1.564 + }; 1.565 + 1.566 + friend class OverlayForwardReference; 1.567 + 1.568 + class TemplateBuilderHookup : public nsForwardReference 1.569 + { 1.570 + protected: 1.571 + nsCOMPtr<nsIContent> mElement; // [OWNER] 1.572 + 1.573 + public: 1.574 + TemplateBuilderHookup(nsIContent* aElement) 1.575 + : mElement(aElement) {} 1.576 + 1.577 + virtual Phase GetPhase() MOZ_OVERRIDE { return eHookup; } 1.578 + virtual Result Resolve() MOZ_OVERRIDE; 1.579 + }; 1.580 + 1.581 + friend class TemplateBuilderHookup; 1.582 + 1.583 + // The out params of FindBroadcaster only have values that make sense when 1.584 + // the method returns NS_FINDBROADCASTER_FOUND. In all other cases, the 1.585 + // values of the out params should not be relied on (though *aListener and 1.586 + // *aBroadcaster do need to be released if non-null, of course). 1.587 + nsresult 1.588 + FindBroadcaster(Element* aElement, 1.589 + Element** aListener, 1.590 + nsString& aBroadcasterID, 1.591 + nsString& aAttribute, 1.592 + Element** aBroadcaster); 1.593 + 1.594 + nsresult 1.595 + CheckBroadcasterHookup(Element* aElement, 1.596 + bool* aNeedsHookup, 1.597 + bool* aDidResolve); 1.598 + 1.599 + void 1.600 + SynchronizeBroadcastListener(Element *aBroadcaster, 1.601 + Element *aListener, 1.602 + const nsAString &aAttr); 1.603 + 1.604 + static 1.605 + nsresult 1.606 + InsertElement(nsINode* aParent, nsIContent* aChild, bool aNotify); 1.607 + 1.608 + static 1.609 + nsresult 1.610 + RemoveElement(nsINode* aParent, nsINode* aChild); 1.611 + 1.612 + /** 1.613 + * The current prototype that we are walking to construct the 1.614 + * content model. 1.615 + */ 1.616 + nsRefPtr<nsXULPrototypeDocument> mCurrentPrototype; 1.617 + 1.618 + /** 1.619 + * The master document (outermost, .xul) prototype, from which 1.620 + * all subdocuments get their security principals. 1.621 + */ 1.622 + nsRefPtr<nsXULPrototypeDocument> mMasterPrototype; 1.623 + 1.624 + /** 1.625 + * Owning references to all of the prototype documents that were 1.626 + * used to construct this document. 1.627 + */ 1.628 + nsTArray< nsRefPtr<nsXULPrototypeDocument> > mPrototypes; 1.629 + 1.630 + /** 1.631 + * Prepare to walk the current prototype. 1.632 + */ 1.633 + nsresult PrepareToWalk(); 1.634 + 1.635 + /** 1.636 + * Creates a processing instruction based on aProtoPI and inserts 1.637 + * it to the DOM (as the aIndex-th child of aParent). 1.638 + */ 1.639 + nsresult 1.640 + CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, 1.641 + nsINode* aParent, uint32_t aIndex); 1.642 + 1.643 + /** 1.644 + * Inserts the passed <?xml-stylesheet ?> PI at the specified 1.645 + * index. Loads and applies the associated stylesheet 1.646 + * asynchronously. 1.647 + * The prototype document walk can happen before the stylesheets 1.648 + * are loaded, but the final steps in the load process (see 1.649 + * DoneWalking()) are not run before all the stylesheets are done 1.650 + * loading. 1.651 + */ 1.652 + nsresult 1.653 + InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI, 1.654 + nsINode* aParent, 1.655 + uint32_t aIndex, 1.656 + nsIContent* aPINode); 1.657 + 1.658 + /** 1.659 + * Inserts the passed <?xul-overlay ?> PI at the specified index. 1.660 + * Schedules the referenced overlay URI for further processing. 1.661 + */ 1.662 + nsresult 1.663 + InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI, 1.664 + nsINode* aParent, 1.665 + uint32_t aIndex, 1.666 + nsIContent* aPINode); 1.667 + 1.668 + /** 1.669 + * Add overlays from the chrome registry to the set of unprocessed 1.670 + * overlays still to do. 1.671 + */ 1.672 + nsresult AddChromeOverlays(); 1.673 + 1.674 + /** 1.675 + * Resume (or initiate) an interrupted (or newly prepared) 1.676 + * prototype walk. 1.677 + */ 1.678 + nsresult ResumeWalk(); 1.679 + 1.680 + /** 1.681 + * Called at the end of ResumeWalk() and from StyleSheetLoaded(). 1.682 + * Expects that both the prototype document walk is complete and 1.683 + * all referenced stylesheets finished loading. 1.684 + */ 1.685 + nsresult DoneWalking(); 1.686 + 1.687 + /** 1.688 + * Report that an overlay failed to load 1.689 + * @param aURI the URI of the overlay that failed to load 1.690 + */ 1.691 + void ReportMissingOverlay(nsIURI* aURI); 1.692 + 1.693 + class CachedChromeStreamListener : public nsIStreamListener { 1.694 + protected: 1.695 + XULDocument* mDocument; 1.696 + bool mProtoLoaded; 1.697 + 1.698 + virtual ~CachedChromeStreamListener(); 1.699 + 1.700 + public: 1.701 + CachedChromeStreamListener(XULDocument* aDocument, 1.702 + bool aProtoLoaded); 1.703 + 1.704 + NS_DECL_ISUPPORTS 1.705 + NS_DECL_NSIREQUESTOBSERVER 1.706 + NS_DECL_NSISTREAMLISTENER 1.707 + }; 1.708 + 1.709 + friend class CachedChromeStreamListener; 1.710 + 1.711 + 1.712 + class ParserObserver : public nsIRequestObserver { 1.713 + protected: 1.714 + nsRefPtr<XULDocument> mDocument; 1.715 + nsRefPtr<nsXULPrototypeDocument> mPrototype; 1.716 + virtual ~ParserObserver(); 1.717 + 1.718 + public: 1.719 + ParserObserver(XULDocument* aDocument, 1.720 + nsXULPrototypeDocument* aPrototype); 1.721 + 1.722 + NS_DECL_ISUPPORTS 1.723 + NS_DECL_NSIREQUESTOBSERVER 1.724 + }; 1.725 + 1.726 + friend class ParserObserver; 1.727 + 1.728 + /** 1.729 + * A map from a broadcaster element to a list of listener elements. 1.730 + */ 1.731 + PLDHashTable* mBroadcasterMap; 1.732 + 1.733 + nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mOverlayLoadObservers; 1.734 + nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mPendingOverlayLoadNotifications; 1.735 + 1.736 + bool mInitialLayoutComplete; 1.737 + 1.738 + class nsDelayedBroadcastUpdate 1.739 + { 1.740 + public: 1.741 + nsDelayedBroadcastUpdate(Element* aBroadcaster, 1.742 + Element* aListener, 1.743 + const nsAString &aAttr) 1.744 + : mBroadcaster(aBroadcaster), mListener(aListener), mAttr(aAttr), 1.745 + mSetAttr(false), mNeedsAttrChange(false) {} 1.746 + 1.747 + nsDelayedBroadcastUpdate(Element* aBroadcaster, 1.748 + Element* aListener, 1.749 + nsIAtom* aAttrName, 1.750 + const nsAString &aAttr, 1.751 + bool aSetAttr, 1.752 + bool aNeedsAttrChange) 1.753 + : mBroadcaster(aBroadcaster), mListener(aListener), mAttr(aAttr), 1.754 + mAttrName(aAttrName), mSetAttr(aSetAttr), 1.755 + mNeedsAttrChange(aNeedsAttrChange) {} 1.756 + 1.757 + nsDelayedBroadcastUpdate(const nsDelayedBroadcastUpdate& aOther) 1.758 + : mBroadcaster(aOther.mBroadcaster), mListener(aOther.mListener), 1.759 + mAttr(aOther.mAttr), mAttrName(aOther.mAttrName), 1.760 + mSetAttr(aOther.mSetAttr), mNeedsAttrChange(aOther.mNeedsAttrChange) {} 1.761 + 1.762 + nsCOMPtr<Element> mBroadcaster; 1.763 + nsCOMPtr<Element> mListener; 1.764 + // Note if mAttrName isn't used, this is the name of the attr, otherwise 1.765 + // this is the value of the attribute. 1.766 + nsString mAttr; 1.767 + nsCOMPtr<nsIAtom> mAttrName; 1.768 + bool mSetAttr; 1.769 + bool mNeedsAttrChange; 1.770 + 1.771 + class Comparator { 1.772 + public: 1.773 + static bool Equals(const nsDelayedBroadcastUpdate& a, const nsDelayedBroadcastUpdate& b) { 1.774 + return a.mBroadcaster == b.mBroadcaster && a.mListener == b.mListener && a.mAttrName == b.mAttrName; 1.775 + } 1.776 + }; 1.777 + }; 1.778 + 1.779 + nsTArray<nsDelayedBroadcastUpdate> mDelayedBroadcasters; 1.780 + nsTArray<nsDelayedBroadcastUpdate> mDelayedAttrChangeBroadcasts; 1.781 + bool mHandlingDelayedAttrChange; 1.782 + bool mHandlingDelayedBroadcasters; 1.783 + 1.784 + void MaybeBroadcast(); 1.785 +private: 1.786 + // helpers 1.787 + 1.788 +}; 1.789 + 1.790 +} // namespace dom 1.791 +} // namespace mozilla 1.792 + 1.793 +#endif // mozilla_dom_XULDocument_h