content/xul/document/src/XULDocument.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial