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