XULDocument.h 26 KB

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