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