1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_dom_XULDocument_h 7 #define mozilla_dom_XULDocument_h 8 9 #include "nsAutoPtr.h" 10 #include "nsCOMPtr.h" 11 #include "nsXULPrototypeDocument.h" 12 #include "nsXULPrototypeCache.h" 13 #include "nsTArray.h" 14 15 #include "mozilla/dom/XMLDocument.h" 16 #include "mozilla/StyleSheet.h" 17 #include "nsForwardReference.h" 18 #include "nsIContent.h" 19 #include "nsIDOMXULCommandDispatcher.h" 20 #include "nsIDOMXULDocument.h" 21 #include "nsCOMArray.h" 22 #include "nsIURI.h" 23 #include "nsIXULDocument.h" 24 #include "nsScriptLoader.h" 25 #include "nsIStreamListener.h" 26 #include "nsIStreamLoader.h" 27 #include "nsICSSLoaderObserver.h" 28 #include "nsIXULStore.h" 29 30 #include "mozilla/Attributes.h" 31 32 #include "js/TracingAPI.h" 33 #include "js/TypeDecls.h" 34 35 class nsIRDFResource; 36 class nsIRDFService; 37 class nsPIWindowRoot; 38 #if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript)) 39 class nsIObjectInputStream; 40 class nsIObjectOutputStream; 41 #else 42 #include "nsIObjectInputStream.h" 43 #include "nsIObjectOutputStream.h" 44 #include "nsXULElement.h" 45 #endif 46 #include "nsURIHashKey.h" 47 #include "nsInterfaceHashtable.h" 48 49 class nsRefMapEntry : public nsStringHashKey 50 { 51 public: nsRefMapEntry(const nsAString & aKey)52 explicit nsRefMapEntry(const nsAString& aKey) : 53 nsStringHashKey(&aKey) 54 { 55 } nsRefMapEntry(const nsAString * aKey)56 explicit nsRefMapEntry(const nsAString* aKey) : 57 nsStringHashKey(aKey) 58 { 59 } nsRefMapEntry(const nsRefMapEntry & aOther)60 nsRefMapEntry(const nsRefMapEntry& aOther) : 61 nsStringHashKey(&aOther.GetKey()) 62 { 63 NS_ERROR("Should never be called"); 64 } 65 66 mozilla::dom::Element* GetFirstElement(); 67 void AppendAll(nsCOMArray<nsIContent>* aElements); 68 /** 69 * @return true if aElement was added, false if we failed due to OOM 70 */ 71 bool AddElement(mozilla::dom::Element* aElement); 72 /** 73 * @return true if aElement was removed and it was the last content for 74 * this ref, so this entry should be removed from the map 75 */ 76 bool RemoveElement(mozilla::dom::Element* aElement); 77 78 private: 79 nsTArray<mozilla::dom::Element*> mRefContentList; 80 }; 81 82 /** 83 * The XUL document class 84 */ 85 86 namespace mozilla { 87 namespace dom { 88 89 class XULDocument final : public XMLDocument, 90 public nsIXULDocument, 91 public nsIDOMXULDocument, 92 public nsIStreamLoaderObserver, 93 public nsICSSLoaderObserver, 94 public nsIOffThreadScriptReceiver 95 { 96 public: 97 XULDocument(); 98 99 // nsISupports interface 100 NS_DECL_ISUPPORTS_INHERITED 101 NS_DECL_NSISTREAMLOADEROBSERVER 102 103 // nsIDocument interface 104 virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) override; 105 virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup, 106 nsIPrincipal* aPrincipal) override; 107 108 virtual nsresult StartDocumentLoad(const char* aCommand, 109 nsIChannel *channel, 110 nsILoadGroup* aLoadGroup, 111 nsISupports* aContainer, 112 nsIStreamListener **aDocListener, 113 bool aReset = true, 114 nsIContentSink* aSink = nullptr) override; 115 116 virtual void SetContentType(const nsAString& aContentType) override; 117 118 virtual void EndLoad() override; 119 120 // nsIMutationObserver interface 121 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED 122 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED 123 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED 124 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED 125 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE 126 127 // nsIXULDocument interface 128 virtual void GetElementsForID(const nsAString& aID, 129 nsCOMArray<nsIContent>& aElements) override; 130 131 NS_IMETHOD AddSubtreeToDocument(nsIContent* aContent) override; 132 NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent) override; 133 NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent, 134 nsIXULTemplateBuilder* aBuilder) override; 135 NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent, 136 nsIXULTemplateBuilder** aResult) override; 137 NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) override; 138 bool OnDocumentParserError() override; 139 140 // nsINode interface overrides 141 virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; 142 143 // nsIDOMNode interface 144 NS_FORWARD_NSIDOMNODE_TO_NSINODE 145 146 // nsIDOMDocument interface 147 using nsDocument::CreateElement; 148 using nsDocument::CreateElementNS; 149 NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::) 150 // And explicitly import the things from nsDocument that we just shadowed 151 using nsDocument::GetImplementation; 152 using nsDocument::GetTitle; 153 using nsDocument::SetTitle; 154 using nsDocument::GetLastStyleSheetSet; 155 using nsDocument::MozSetImageElement; 156 using nsDocument::GetMozFullScreenElement; 157 using nsIDocument::GetLocation; 158 159 // nsDocument interface overrides 160 virtual Element* GetElementById(const nsAString & elementId) override; 161 162 // nsIDOMXULDocument interface 163 NS_DECL_NSIDOMXULDOCUMENT 164 165 // nsICSSLoaderObserver 166 NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, 167 bool aWasAlternate, 168 nsresult aStatus) override; 169 170 virtual void EndUpdate(nsUpdateType aUpdateType) override; 171 172 virtual bool IsDocumentRightToLeft() override; 173 174 virtual void ResetDocumentDirection() override; 175 176 virtual int GetDocumentLWTheme() override; 177 ResetDocumentLWTheme()178 virtual void ResetDocumentLWTheme() override { mDocLWTheme = Doc_Theme_Uninitialized; } 179 180 NS_IMETHOD OnScriptCompileComplete(JSScript* aScript, nsresult aStatus) override; 181 182 static bool 183 MatchAttribute(nsIContent* aContent, 184 int32_t aNameSpaceID, 185 nsIAtom* aAttrName, 186 void* aData); 187 188 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULDocument, XMLDocument) 189 190 void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber); 191 192 // WebIDL API 193 already_AddRefed<nsINode> GetPopupNode(); 194 void SetPopupNode(nsINode* aNode); 195 already_AddRefed<nsINode> GetPopupRangeParent(ErrorResult& aRv); 196 int32_t GetPopupRangeOffset(ErrorResult& aRv); 197 already_AddRefed<nsINode> GetTooltipNode(); SetTooltipNode(nsINode * aNode)198 void SetTooltipNode(nsINode* aNode) { /* do nothing */ } GetCommandDispatcher()199 nsIDOMXULCommandDispatcher* GetCommandDispatcher() const 200 { 201 return mCommandDispatcher; 202 } 203 int32_t GetWidth(ErrorResult& aRv); 204 int32_t GetHeight(ErrorResult& aRv); 205 already_AddRefed<nsINodeList> 206 GetElementsByAttribute(const nsAString& aAttribute, 207 const nsAString& aValue); 208 already_AddRefed<nsINodeList> 209 GetElementsByAttributeNS(const nsAString& aNamespaceURI, 210 const nsAString& aAttribute, 211 const nsAString& aValue, 212 ErrorResult& aRv); 213 void AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener, 214 const nsAString& aAttr, ErrorResult& aRv); 215 void RemoveBroadcastListenerFor(Element& aBroadcaster, Element& aListener, 216 const nsAString& aAttr); Persist(const nsAString & aId,const nsAString & aAttr,ErrorResult & aRv)217 void Persist(const nsAString& aId, const nsAString& aAttr, ErrorResult& aRv) 218 { 219 aRv = Persist(aId, aAttr); 220 } 221 using nsDocument::GetBoxObjectFor; LoadOverlay(const nsAString & aURL,nsIObserver * aObserver,ErrorResult & aRv)222 void LoadOverlay(const nsAString& aURL, nsIObserver* aObserver, 223 ErrorResult& aRv) 224 { 225 aRv = LoadOverlay(aURL, aObserver); 226 } 227 228 protected: 229 virtual ~XULDocument(); 230 231 // Implementation methods 232 friend nsresult 233 (::NS_NewXULDocument(nsIXULDocument** aResult)); 234 235 nsresult Init(void) override; 236 nsresult StartLayout(void); 237 238 nsresult 239 AddElementToRefMap(Element* aElement); 240 void 241 RemoveElementFromRefMap(Element* aElement); 242 243 nsresult GetViewportSize(int32_t* aWidth, int32_t* aHeight); 244 245 nsresult PrepareToLoad(nsISupports* aContainer, 246 const char* aCommand, 247 nsIChannel* aChannel, 248 nsILoadGroup* aLoadGroup, 249 nsIParser** aResult); 250 251 nsresult 252 PrepareToLoadPrototype(nsIURI* aURI, 253 const char* aCommand, 254 nsIPrincipal* aDocumentPrincipal, 255 nsIParser** aResult); 256 257 nsresult 258 LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic, bool* aShouldReturn, 259 bool* aFailureFromContent); 260 261 nsresult ApplyPersistentAttributes(); 262 nsresult ApplyPersistentAttributesInternal(); 263 nsresult ApplyPersistentAttributesToElements(const nsAString &aID, 264 nsCOMArray<nsIContent>& aElements); 265 266 nsresult 267 AddElementToDocumentPre(Element* aElement); 268 269 nsresult 270 AddElementToDocumentPost(Element* aElement); 271 272 nsresult 273 ExecuteOnBroadcastHandlerFor(Element* aBroadcaster, 274 Element* aListener, 275 nsIAtom* aAttr); 276 277 nsresult 278 BroadcastAttributeChangeFromOverlay(nsIContent* aNode, 279 int32_t aNameSpaceID, 280 nsIAtom* aAttribute, 281 nsIAtom* aPrefix, 282 const nsAString& aValue); 283 284 already_AddRefed<nsPIWindowRoot> GetWindowRoot(); 285 286 static void DirectionChanged(const char* aPrefName, void* aData); 287 288 // pseudo constants 289 static int32_t gRefCnt; 290 291 static nsIAtom** kIdentityAttrs[]; 292 293 static nsIRDFService* gRDFService; 294 static nsIRDFResource* kNC_persist; 295 static nsIRDFResource* kNC_attribute; 296 static nsIRDFResource* kNC_value; 297 298 static LazyLogModule gXULLog; 299 300 nsresult 301 Persist(nsIContent* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute); 302 // Just like Persist but ignores the return value so we can use it 303 // as a runnable method. DoPersist(nsIContent * aElement,int32_t aNameSpaceID,nsIAtom * aAttribute)304 void DoPersist(nsIContent* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute) 305 { 306 Persist(aElement, aNameSpaceID, aAttribute); 307 } 308 309 virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; 310 311 // IMPORTANT: The ownership implicit in the following member 312 // variables has been explicitly checked and set using nsCOMPtr 313 // for owning pointers and raw COM interface pointers for weak 314 // (ie, non owning) references. If you add any members to this 315 // class, please make the ownership explicit (pinkerton, scc). 316 // NOTE, THIS IS STILL IN PROGRESS, TALK TO PINK OR SCC BEFORE 317 // CHANGING 318 319 XULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr 320 321 // Tracks elements with a 'ref' attribute, or an 'id' attribute where 322 // the element's namespace has no registered ID attribute name. 323 nsTHashtable<nsRefMapEntry> mRefMap; 324 nsCOMPtr<nsIXULStore> mLocalStore; 325 bool mApplyingPersistedAttrs; 326 bool mIsWritingFastLoad; 327 bool mDocumentLoaded; 328 /** 329 * Since ResumeWalk is interruptible, it's possible that last 330 * stylesheet finishes loading while the PD walk is still in 331 * progress (waiting for an overlay to finish loading). 332 * mStillWalking prevents DoneLoading (and StartLayout) from being 333 * called in this situation. 334 */ 335 bool mStillWalking; 336 337 /** 338 * These two values control where persistent attributes get applied. 339 */ 340 bool mRestrictPersistence; 341 nsTHashtable<nsStringHashKey> mPersistenceIds; 342 343 /** 344 * An array of style sheets, that will be added (preserving order) to the 345 * document after all of them are loaded (in DoneWalking). 346 */ 347 nsTArray<RefPtr<StyleSheet>> mOverlaySheets; 348 349 nsCOMPtr<nsIDOMXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker 350 351 // Maintains the template builders that have been attached to 352 // content elements 353 typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXULTemplateBuilder> 354 BuilderTable; 355 BuilderTable* mTemplateBuilderTable; 356 357 uint32_t mPendingSheets; 358 359 /** 360 * document lightweight theme for use with :-moz-lwtheme, :-moz-lwtheme-brighttext 361 * and :-moz-lwtheme-darktext 362 */ 363 DocumentTheme mDocLWTheme; 364 365 /** 366 * Context stack, which maintains the state of the Builder and allows 367 * it to be interrupted. 368 */ 369 class ContextStack { 370 protected: 371 struct Entry { 372 nsXULPrototypeElement* mPrototype; 373 nsIContent* mElement; 374 int32_t mIndex; 375 Entry* mNext; 376 }; 377 378 Entry* mTop; 379 int32_t mDepth; 380 381 public: 382 ContextStack(); 383 ~ContextStack(); 384 Depth()385 int32_t Depth() { return mDepth; } 386 387 nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement); 388 nsresult Pop(); 389 nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement, int32_t* aIndex); 390 391 nsresult SetTopIndex(int32_t aIndex); 392 }; 393 394 friend class ContextStack; 395 ContextStack mContextStack; 396 397 enum State { eState_Master, eState_Overlay }; 398 State mState; 399 400 /** 401 * An array of overlay nsIURIs that have yet to be resolved. The 402 * order of the array is significant: overlays at the _end_ of the 403 * array are resolved before overlays earlier in the array (i.e., 404 * it is a stack). 405 * 406 * In the current implementation the order the overlays are loaded 407 * in is as follows: first overlays from xul-overlay PIs, in the 408 * same order as in the document, then the overlays from the chrome 409 * registry. 410 */ 411 nsTArray<nsCOMPtr<nsIURI> > mUnloadedOverlays; 412 413 /** 414 * Load the transcluded script at the specified URI. If the 415 * prototype construction must 'block' until the load has 416 * completed, aBlock will be set to true. 417 */ 418 nsresult LoadScript(nsXULPrototypeScript *aScriptProto, bool* aBlock); 419 420 /** 421 * Execute the precompiled script object scoped by this XUL document's 422 * containing window object. 423 */ 424 nsresult ExecuteScript(nsXULPrototypeScript *aScript); 425 426 /** 427 * Create a delegate content model element from a prototype. 428 * Note that the resulting content node is not bound to any tree 429 */ 430 nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, 431 Element** aResult, 432 bool aIsRoot); 433 434 /** 435 * Create a hook-up element to which content nodes can be attached for 436 * later resolution. 437 */ 438 nsresult CreateOverlayElement(nsXULPrototypeElement* aPrototype, 439 Element** aResult); 440 441 /** 442 * Add attributes from the prototype to the element. 443 */ 444 nsresult AddAttributes(nsXULPrototypeElement* aPrototype, nsIContent* aElement); 445 446 /** 447 * The prototype-script of the current transcluded script that is being 448 * loaded. For document.write('<script src="nestedwrite.js"><\/script>') 449 * to work, these need to be in a stack element type, and we need to hold 450 * the top of stack here. 451 */ 452 nsXULPrototypeScript* mCurrentScriptProto; 453 454 /** 455 * Whether the current transcluded script is being compiled off thread. 456 * The load event is blocked while this is in progress. 457 */ 458 bool mOffThreadCompiling; 459 460 /** 461 * If the current transcluded script is being compiled off thread, the 462 * source for that script. 463 */ 464 char16_t* mOffThreadCompileStringBuf; 465 size_t mOffThreadCompileStringLength; 466 467 /** 468 * Check if a XUL template builder has already been hooked up. 469 */ 470 static nsresult 471 CheckTemplateBuilderHookup(nsIContent* aElement, bool* aNeedsHookup); 472 473 /** 474 * Create a XUL template builder on the specified node. 475 */ 476 static nsresult 477 CreateTemplateBuilder(nsIContent* aElement); 478 479 /** 480 * Add the current prototype's style sheets (currently it's just 481 * style overlays from the chrome registry) to the document. 482 */ 483 nsresult AddPrototypeSheets(); 484 485 486 protected: 487 /* Declarations related to forward references. 488 * 489 * Forward references are declarations which are added to the temporary 490 * list (mForwardReferences) during the document (or overlay) load and 491 * are resolved later, when the document loading is almost complete. 492 */ 493 494 /** 495 * The list of different types of forward references to resolve. After 496 * a reference is resolved, it is removed from this array (and 497 * automatically deleted) 498 */ 499 nsTArray<nsAutoPtr<nsForwardReference> > mForwardReferences; 500 501 /** Indicates what kind of forward references are still to be processed. */ 502 nsForwardReference::Phase mResolutionPhase; 503 504 /** 505 * Adds aRef to the mForwardReferences array. Takes the ownership of aRef. 506 */ 507 nsresult AddForwardReference(nsForwardReference* aRef); 508 509 /** 510 * Resolve all of the document's forward references. 511 */ 512 nsresult ResolveForwardReferences(); 513 514 /** 515 * Used to resolve broadcaster references 516 */ 517 class BroadcasterHookup : public nsForwardReference 518 { 519 protected: 520 XULDocument* mDocument; // [WEAK] 521 RefPtr<Element> mObservesElement; // [OWNER] 522 bool mResolved; 523 524 public: BroadcasterHookup(XULDocument * aDocument,Element * aObservesElement)525 BroadcasterHookup(XULDocument* aDocument, 526 Element* aObservesElement) 527 : mDocument(aDocument), 528 mObservesElement(aObservesElement), 529 mResolved(false) 530 { 531 } 532 533 virtual ~BroadcasterHookup(); 534 GetPhase()535 virtual Phase GetPhase() override { return eHookup; } 536 virtual Result Resolve() override; 537 }; 538 539 friend class BroadcasterHookup; 540 541 542 /** 543 * Used to hook up overlays 544 */ 545 class OverlayForwardReference : public nsForwardReference 546 { 547 protected: 548 XULDocument* mDocument; // [WEAK] 549 nsCOMPtr<nsIContent> mOverlay; // [OWNER] 550 bool mResolved; 551 552 nsresult Merge(nsIContent* aTargetNode, nsIContent* aOverlayNode, bool aNotify); 553 554 public: OverlayForwardReference(XULDocument * aDocument,nsIContent * aOverlay)555 OverlayForwardReference(XULDocument* aDocument, nsIContent* aOverlay) 556 : mDocument(aDocument), mOverlay(aOverlay), mResolved(false) {} 557 558 virtual ~OverlayForwardReference(); 559 GetPhase()560 virtual Phase GetPhase() override { return eConstruction; } 561 virtual Result Resolve() override; 562 }; 563 564 friend class OverlayForwardReference; 565 566 class TemplateBuilderHookup : public nsForwardReference 567 { 568 protected: 569 nsCOMPtr<nsIContent> mElement; // [OWNER] 570 571 public: TemplateBuilderHookup(nsIContent * aElement)572 explicit TemplateBuilderHookup(nsIContent* aElement) 573 : mElement(aElement) {} 574 GetPhase()575 virtual Phase GetPhase() override { return eHookup; } 576 virtual Result Resolve() override; 577 }; 578 579 friend class TemplateBuilderHookup; 580 581 // The out params of FindBroadcaster only have values that make sense when 582 // the method returns NS_FINDBROADCASTER_FOUND. In all other cases, the 583 // values of the out params should not be relied on (though *aListener and 584 // *aBroadcaster do need to be released if non-null, of course). 585 nsresult 586 FindBroadcaster(Element* aElement, 587 Element** aListener, 588 nsString& aBroadcasterID, 589 nsString& aAttribute, 590 Element** aBroadcaster); 591 592 nsresult 593 CheckBroadcasterHookup(Element* aElement, 594 bool* aNeedsHookup, 595 bool* aDidResolve); 596 597 void 598 SynchronizeBroadcastListener(Element *aBroadcaster, 599 Element *aListener, 600 const nsAString &aAttr); 601 602 static 603 nsresult 604 InsertElement(nsINode* aParent, nsIContent* aChild, bool aNotify); 605 606 static 607 nsresult 608 RemoveElement(nsINode* aParent, nsINode* aChild); 609 610 /** 611 * The current prototype that we are walking to construct the 612 * content model. 613 */ 614 RefPtr<nsXULPrototypeDocument> mCurrentPrototype; 615 616 /** 617 * The master document (outermost, .xul) prototype, from which 618 * all subdocuments get their security principals. 619 */ 620 RefPtr<nsXULPrototypeDocument> mMasterPrototype; 621 622 /** 623 * Owning references to all of the prototype documents that were 624 * used to construct this document. 625 */ 626 nsTArray< RefPtr<nsXULPrototypeDocument> > mPrototypes; 627 628 /** 629 * Prepare to walk the current prototype. 630 */ 631 nsresult PrepareToWalk(); 632 633 /** 634 * Creates a processing instruction based on aProtoPI and inserts 635 * it to the DOM (as the aIndex-th child of aParent). 636 */ 637 nsresult 638 CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, 639 nsINode* aParent, uint32_t aIndex); 640 641 /** 642 * Inserts the passed <?xml-stylesheet ?> PI at the specified 643 * index. Loads and applies the associated stylesheet 644 * asynchronously. 645 * The prototype document walk can happen before the stylesheets 646 * are loaded, but the final steps in the load process (see 647 * DoneWalking()) are not run before all the stylesheets are done 648 * loading. 649 */ 650 nsresult 651 InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI, 652 nsINode* aParent, 653 uint32_t aIndex, 654 nsIContent* aPINode); 655 656 /** 657 * Inserts the passed <?xul-overlay ?> PI at the specified index. 658 * Schedules the referenced overlay URI for further processing. 659 */ 660 nsresult 661 InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI, 662 nsINode* aParent, 663 uint32_t aIndex, 664 nsIContent* aPINode); 665 666 /** 667 * Add overlays from the chrome registry to the set of unprocessed 668 * overlays still to do. 669 */ 670 nsresult AddChromeOverlays(); 671 672 /** 673 * Resume (or initiate) an interrupted (or newly prepared) 674 * prototype walk. 675 */ 676 nsresult ResumeWalk(); 677 678 /** 679 * Called at the end of ResumeWalk() and from StyleSheetLoaded(). 680 * Expects that both the prototype document walk is complete and 681 * all referenced stylesheets finished loading. 682 */ 683 nsresult DoneWalking(); 684 685 /** 686 * Report that an overlay failed to load 687 * @param aURI the URI of the overlay that failed to load 688 */ 689 void ReportMissingOverlay(nsIURI* aURI); 690 691 class CachedChromeStreamListener : public nsIStreamListener { 692 protected: 693 RefPtr<XULDocument> mDocument; 694 bool mProtoLoaded; 695 696 virtual ~CachedChromeStreamListener(); 697 698 public: 699 CachedChromeStreamListener(XULDocument* aDocument, 700 bool aProtoLoaded); 701 702 NS_DECL_ISUPPORTS 703 NS_DECL_NSIREQUESTOBSERVER 704 NS_DECL_NSISTREAMLISTENER 705 }; 706 707 friend class CachedChromeStreamListener; 708 709 710 class ParserObserver : public nsIRequestObserver { 711 protected: 712 RefPtr<XULDocument> mDocument; 713 RefPtr<nsXULPrototypeDocument> mPrototype; 714 virtual ~ParserObserver(); 715 716 public: 717 ParserObserver(XULDocument* aDocument, 718 nsXULPrototypeDocument* aPrototype); 719 720 NS_DECL_ISUPPORTS 721 NS_DECL_NSIREQUESTOBSERVER 722 }; 723 724 friend class ParserObserver; 725 726 /** 727 * A map from a broadcaster element to a list of listener elements. 728 */ 729 PLDHashTable* mBroadcasterMap; 730 731 nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mOverlayLoadObservers; 732 nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mPendingOverlayLoadNotifications; 733 734 bool mInitialLayoutComplete; 735 736 class nsDelayedBroadcastUpdate 737 { 738 public: nsDelayedBroadcastUpdate(Element * aBroadcaster,Element * aListener,const nsAString & aAttr)739 nsDelayedBroadcastUpdate(Element* aBroadcaster, 740 Element* aListener, 741 const nsAString &aAttr) 742 : mBroadcaster(aBroadcaster), mListener(aListener), mAttr(aAttr), 743 mSetAttr(false), mNeedsAttrChange(false) {} 744 nsDelayedBroadcastUpdate(Element * aBroadcaster,Element * aListener,nsIAtom * aAttrName,const nsAString & aAttr,bool aSetAttr,bool aNeedsAttrChange)745 nsDelayedBroadcastUpdate(Element* aBroadcaster, 746 Element* aListener, 747 nsIAtom* aAttrName, 748 const nsAString &aAttr, 749 bool aSetAttr, 750 bool aNeedsAttrChange) 751 : mBroadcaster(aBroadcaster), mListener(aListener), mAttr(aAttr), 752 mAttrName(aAttrName), mSetAttr(aSetAttr), 753 mNeedsAttrChange(aNeedsAttrChange) {} 754 nsDelayedBroadcastUpdate(const nsDelayedBroadcastUpdate & aOther)755 nsDelayedBroadcastUpdate(const nsDelayedBroadcastUpdate& aOther) 756 : mBroadcaster(aOther.mBroadcaster), mListener(aOther.mListener), 757 mAttr(aOther.mAttr), mAttrName(aOther.mAttrName), 758 mSetAttr(aOther.mSetAttr), mNeedsAttrChange(aOther.mNeedsAttrChange) {} 759 760 nsCOMPtr<Element> mBroadcaster; 761 nsCOMPtr<Element> mListener; 762 // Note if mAttrName isn't used, this is the name of the attr, otherwise 763 // this is the value of the attribute. 764 nsString mAttr; 765 nsCOMPtr<nsIAtom> mAttrName; 766 bool mSetAttr; 767 bool mNeedsAttrChange; 768 769 class Comparator { 770 public: Equals(const nsDelayedBroadcastUpdate & a,const nsDelayedBroadcastUpdate & b)771 static bool Equals(const nsDelayedBroadcastUpdate& a, const nsDelayedBroadcastUpdate& b) { 772 return a.mBroadcaster == b.mBroadcaster && a.mListener == b.mListener && a.mAttrName == b.mAttrName; 773 } 774 }; 775 }; 776 777 nsTArray<nsDelayedBroadcastUpdate> mDelayedBroadcasters; 778 nsTArray<nsDelayedBroadcastUpdate> mDelayedAttrChangeBroadcasts; 779 bool mHandlingDelayedAttrChange; 780 bool mHandlingDelayedBroadcasters; 781 782 void MaybeBroadcast(); 783 private: 784 // helpers 785 786 }; 787 788 } // namespace dom 789 } // namespace mozilla 790 791 #endif // mozilla_dom_XULDocument_h 792