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