content/base/public/nsReferencedElement.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.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 sw=2 et tw=78: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef NSREFERENCEDELEMENT_H_
     8 #define NSREFERENCEDELEMENT_H_
    10 #include "mozilla/Attributes.h"
    11 #include "mozilla/dom/Element.h"
    12 #include "nsIAtom.h"
    13 #include "nsIDocument.h"
    14 #include "nsThreadUtils.h"
    15 #include "nsAutoPtr.h"
    17 class nsIURI;
    18 class nsCycleCollectionCallback;
    20 /**
    21  * Class to track what element is referenced by a given ID.
    22  * 
    23  * To use it, call Reset() to set it up to watch a given URI. Call get()
    24  * anytime to determine the referenced element (which may be null if
    25  * the element isn't found). When the element changes, ElementChanged
    26  * will be called, so subclass this class if you want to receive that
    27  * notification. ElementChanged runs at safe-for-script time, i.e. outside
    28  * of the content update. Call Unlink() if you want to stop watching
    29  * for changes (get() will then return null).
    30  *
    31  * By default this is a single-shot tracker --- i.e., when ElementChanged
    32  * fires, we will automatically stop tracking. get() will continue to return
    33  * the changed-to element.
    34  * Override IsPersistent to return true if you want to keep tracking after
    35  * the first change.
    36  */
    37 class nsReferencedElement {
    38 public:
    39   typedef mozilla::dom::Element Element;
    41   nsReferencedElement() {}
    42   ~nsReferencedElement() {
    43     Unlink();
    44   }
    46   /**
    47    * Find which element, if any, is referenced.
    48    */
    49   Element* get() { return mElement; }
    51   /**
    52    * Set up the reference. This can be called multiple times to
    53    * change which reference is being tracked, but these changes
    54    * do not trigger ElementChanged.
    55    * @param aFrom the source element for context
    56    * @param aURI the URI containing a hash-reference to the element
    57    * @param aWatch if false, then we do not set up the notifications to track
    58    * changes, so ElementChanged won't fire and get() will always return the same
    59    * value, the current element for the ID.
    60    * @param aReferenceImage whether the ID references image elements which are
    61    * subject to the document's mozSetImageElement overriding mechanism.
    62    */
    63   void Reset(nsIContent* aFrom, nsIURI* aURI, bool aWatch = true,
    64              bool aReferenceImage = false);
    66   /**
    67    * A variation on Reset() to set up a reference that consists of the ID of
    68    * an element in the same document as aFrom.
    69    * @param aFrom the source element for context
    70    * @param aID the ID of the element
    71    * @param aWatch if false, then we do not set up the notifications to track
    72    * changes, so ElementChanged won't fire and get() will always return the same
    73    * value, the current element for the ID.
    74    */
    75   void ResetWithID(nsIContent* aFrom, const nsString& aID,
    76                    bool aWatch = true);
    78   /**
    79    * Clears the reference. ElementChanged is not triggered. get() will return
    80    * null.
    81    */
    82   void Unlink();
    84   void Traverse(nsCycleCollectionTraversalCallback* aCB);
    86 protected:
    87   /**
    88    * Override this to be notified of element changes. Don't forget
    89    * to call this superclass method to change mElement. This is called
    90    * at script-runnable time.
    91    */
    92   virtual void ElementChanged(Element* aFrom, Element* aTo) {
    93     mElement = aTo;
    94   }
    96   /**
    97    * Override this to convert from a single-shot notification to
    98    * a persistent notification.
    99    */
   100   virtual bool IsPersistent() { return false; }
   102   /**
   103    * Set ourselves up with our new document.  Note that aDocument might be
   104    * null.  Either aWatch must be false or aRef must be empty.
   105    */
   106   void HaveNewDocument(nsIDocument* aDocument, bool aWatch,
   107                        const nsString& aRef);
   109 private:
   110   static bool Observe(Element* aOldElement,
   111                         Element* aNewElement, void* aData);
   113   class Notification : public nsISupports {
   114   public:
   115     virtual void SetTo(Element* aTo) = 0;
   116     virtual void Clear() { mTarget = nullptr; }
   117     virtual ~Notification() {}
   118   protected:
   119     Notification(nsReferencedElement* aTarget)
   120       : mTarget(aTarget)
   121     {
   122       NS_PRECONDITION(aTarget, "Must have a target");
   123     }
   124     nsReferencedElement* mTarget;
   125   };
   127   class ChangeNotification : public nsRunnable,
   128                              public Notification
   129   {
   130   public:
   131     ChangeNotification(nsReferencedElement* aTarget,
   132                        Element* aFrom, Element* aTo)
   133       : Notification(aTarget), mFrom(aFrom), mTo(aTo)
   134     {}
   135     virtual ~ChangeNotification() {}
   137     NS_DECL_ISUPPORTS_INHERITED
   138     NS_IMETHOD Run() MOZ_OVERRIDE {
   139       if (mTarget) {
   140         mTarget->mPendingNotification = nullptr;
   141         mTarget->ElementChanged(mFrom, mTo);
   142       }
   143       return NS_OK;
   144     }
   145     virtual void SetTo(Element* aTo) { mTo = aTo; }
   146     virtual void Clear()
   147     {
   148       Notification::Clear(); mFrom = nullptr; mTo = nullptr;
   149     }
   150   protected:
   151     nsRefPtr<Element> mFrom;
   152     nsRefPtr<Element> mTo;
   153   };
   154   friend class ChangeNotification;
   156   class DocumentLoadNotification : public Notification,
   157                                    public nsIObserver
   158   {
   159   public:
   160     DocumentLoadNotification(nsReferencedElement* aTarget,
   161                              const nsString& aRef) :
   162       Notification(aTarget)
   163     {
   164       if (!mTarget->IsPersistent()) {
   165         mRef = aRef;
   166       }
   167     }
   168     virtual ~DocumentLoadNotification() {}
   170     NS_DECL_ISUPPORTS
   171     NS_DECL_NSIOBSERVER
   172   private:
   173     virtual void SetTo(Element* aTo) { }
   175     nsString mRef;
   176   };
   177   friend class DocumentLoadNotification;
   179   nsCOMPtr<nsIAtom>      mWatchID;
   180   nsCOMPtr<nsIDocument>  mWatchDocument;
   181   nsRefPtr<Element> mElement;
   182   nsRefPtr<Notification> mPendingNotification;
   183   bool                   mReferencingImage;
   184 };
   186 #endif /*NSREFERENCEDELEMENT_H_*/

mercurial