LCOV - code coverage report
Current view: top level - dom/base - nsReferencedElement.h (source / functions) Hit Total Coverage
Test: output.info Lines: 4 45 8.9 %
Date: 2017-07-14 16:53:18 Functions: 2 21 9.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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/. */
       6             : 
       7             : #ifndef NSREFERENCEDELEMENT_H_
       8             : #define NSREFERENCEDELEMENT_H_
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/dom/Element.h"
      12             : #include "nsIAtom.h"
      13             : #include "nsIDocument.h"
      14             : #include "nsThreadUtils.h"
      15             : 
      16             : class nsIURI;
      17             : 
      18             : /**
      19             :  * Class to track what element is referenced by a given ID.
      20             :  *
      21             :  * To use it, call Reset() to set it up to watch a given URI. Call get()
      22             :  * anytime to determine the referenced element (which may be null if
      23             :  * the element isn't found). When the element changes, ElementChanged
      24             :  * will be called, so subclass this class if you want to receive that
      25             :  * notification. ElementChanged runs at safe-for-script time, i.e. outside
      26             :  * of the content update. Call Unlink() if you want to stop watching
      27             :  * for changes (get() will then return null).
      28             :  *
      29             :  * By default this is a single-shot tracker --- i.e., when ElementChanged
      30             :  * fires, we will automatically stop tracking. get() will continue to return
      31             :  * the changed-to element.
      32             :  * Override IsPersistent to return true if you want to keep tracking after
      33             :  * the first change.
      34             :  */
      35             : class nsReferencedElement {
      36             : public:
      37             :   typedef mozilla::dom::Element Element;
      38             : 
      39          32 :   nsReferencedElement()
      40          32 :     : mReferencingImage(false)
      41          32 :   {}
      42           0 :   ~nsReferencedElement() {
      43           0 :     Unlink();
      44           0 :   }
      45             : 
      46             :   /**
      47             :    * Find which element, if any, is referenced.
      48             :    */
      49          69 :   Element* get() { return mElement; }
      50             : 
      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);
      65             : 
      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);
      77             : 
      78             :   /**
      79             :    * Clears the reference. ElementChanged is not triggered. get() will return
      80             :    * null.
      81             :    */
      82             :   void Unlink();
      83             : 
      84             :   void Traverse(nsCycleCollectionTraversalCallback* aCB);
      85             : 
      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           0 :   virtual void ElementChanged(Element* aFrom, Element* aTo) {
      93           0 :     mElement = aTo;
      94           0 :   }
      95             : 
      96             :   /**
      97             :    * Override this to convert from a single-shot notification to
      98             :    * a persistent notification.
      99             :    */
     100           0 :   virtual bool IsPersistent() { return false; }
     101             : 
     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);
     108             : 
     109             : private:
     110             :   static bool Observe(Element* aOldElement,
     111             :                         Element* aNewElement, void* aData);
     112             : 
     113             :   class Notification : public nsISupports {
     114             :   public:
     115             :     virtual void SetTo(Element* aTo) = 0;
     116           0 :     virtual void Clear() { mTarget = nullptr; }
     117           0 :     virtual ~Notification() {}
     118             :   protected:
     119           0 :     explicit Notification(nsReferencedElement* aTarget)
     120           0 :       : mTarget(aTarget)
     121             :     {
     122           0 :       NS_PRECONDITION(aTarget, "Must have a target");
     123           0 :     }
     124             :     nsReferencedElement* mTarget;
     125             :   };
     126             : 
     127             :   class ChangeNotification : public mozilla::Runnable,
     128             :                              public Notification
     129             :   {
     130             :   public:
     131           0 :     ChangeNotification(nsReferencedElement* aTarget,
     132             :                        Element* aFrom,
     133             :                        Element* aTo)
     134           0 :       : mozilla::Runnable("nsReferencedElement::ChangeNotification")
     135             :       , Notification(aTarget)
     136             :       , mFrom(aFrom)
     137           0 :       , mTo(aTo)
     138           0 :     {}
     139             : 
     140             :     NS_DECL_ISUPPORTS_INHERITED
     141           0 :     NS_IMETHOD Run() override {
     142           0 :       if (mTarget) {
     143           0 :         mTarget->mPendingNotification = nullptr;
     144           0 :         mTarget->ElementChanged(mFrom, mTo);
     145             :       }
     146           0 :       return NS_OK;
     147             :     }
     148           0 :     virtual void SetTo(Element* aTo) override { mTo = aTo; }
     149           0 :     virtual void Clear() override
     150             :     {
     151           0 :       Notification::Clear(); mFrom = nullptr; mTo = nullptr;
     152           0 :     }
     153             :   protected:
     154           0 :     virtual ~ChangeNotification() {}
     155             : 
     156             :     RefPtr<Element> mFrom;
     157             :     RefPtr<Element> mTo;
     158             :   };
     159             :   friend class ChangeNotification;
     160             : 
     161             :   class DocumentLoadNotification : public Notification,
     162             :                                    public nsIObserver
     163             :   {
     164             :   public:
     165           0 :     DocumentLoadNotification(nsReferencedElement* aTarget,
     166           0 :                              const nsString& aRef) :
     167           0 :       Notification(aTarget)
     168             :     {
     169           0 :       if (!mTarget->IsPersistent()) {
     170           0 :         mRef = aRef;
     171             :       }
     172           0 :     }
     173             : 
     174             :     NS_DECL_ISUPPORTS
     175             :     NS_DECL_NSIOBSERVER
     176             :   private:
     177           0 :     virtual ~DocumentLoadNotification() {}
     178             : 
     179           0 :     virtual void SetTo(Element* aTo) override { }
     180             : 
     181             :     nsString mRef;
     182             :   };
     183             :   friend class DocumentLoadNotification;
     184             : 
     185             :   nsCOMPtr<nsIAtom>      mWatchID;
     186             :   nsCOMPtr<nsIDocument>  mWatchDocument;
     187             :   RefPtr<Element> mElement;
     188             :   RefPtr<Notification> mPendingNotification;
     189             :   bool                   mReferencingImage;
     190             : };
     191             : 
     192             : inline void
     193           0 : ImplCycleCollectionUnlink(nsReferencedElement& aField)
     194             : {
     195           0 :   aField.Unlink();
     196           0 : }
     197             : 
     198             : inline void
     199           0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
     200             :                             nsReferencedElement& aField,
     201             :                             const char* aName,
     202             :                             uint32_t aFlags = 0)
     203             : {
     204           0 :   aField.Traverse(&aCallback);
     205           0 : }
     206             : 
     207             : #endif /*NSREFERENCEDELEMENT_H_*/

Generated by: LCOV version 1.13