LCOV - code coverage report
Current view: top level - uriloader/base - nsDocLoader.h (source / functions) Hit Total Coverage
Test: output.info Lines: 33 35 94.3 %
Date: 2017-07-14 16:53:18 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; 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             : /*
       7             : */
       8             : 
       9             : #ifndef nsDocLoader_h__
      10             : #define nsDocLoader_h__
      11             : 
      12             : #include "nsIDocumentLoader.h"
      13             : #include "nsIWebProgress.h"
      14             : #include "nsIWebProgressListener.h"
      15             : #include "nsIRequestObserver.h"
      16             : #include "nsWeakReference.h"
      17             : #include "nsILoadGroup.h"
      18             : #include "nsCOMArray.h"
      19             : #include "nsTObserverArray.h"
      20             : #include "nsString.h"
      21             : #include "nsIChannel.h"
      22             : #include "nsIProgressEventSink.h"
      23             : #include "nsIInterfaceRequestor.h"
      24             : #include "nsIInterfaceRequestorUtils.h"
      25             : #include "nsIChannelEventSink.h"
      26             : #include "nsISecurityEventSink.h"
      27             : #include "nsISupportsPriority.h"
      28             : #include "nsCOMPtr.h"
      29             : #include "PLDHashTable.h"
      30             : #include "nsAutoPtr.h"
      31             : 
      32             : #include "mozilla/LinkedList.h"
      33             : 
      34             : /****************************************************************************
      35             :  * nsDocLoader implementation...
      36             :  ****************************************************************************/
      37             : 
      38             : #define NS_THIS_DOCLOADER_IMPL_CID                    \
      39             :  { /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */         \
      40             :      0xb4ec8387,                                      \
      41             :      0x98aa,                                          \
      42             :      0x4c08,                                          \
      43             :      {0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \
      44             :  }
      45             : 
      46             : class nsDocLoader : public nsIDocumentLoader,
      47             :                     public nsIRequestObserver,
      48             :                     public nsSupportsWeakReference,
      49             :                     public nsIProgressEventSink,
      50             :                     public nsIWebProgress,
      51             :                     public nsIInterfaceRequestor,
      52             :                     public nsIChannelEventSink,
      53             :                     public nsISecurityEventSink,
      54             :                     public nsISupportsPriority
      55             : {
      56             : public:
      57             :     NS_DECLARE_STATIC_IID_ACCESSOR(NS_THIS_DOCLOADER_IMPL_CID)
      58             : 
      59             :     nsDocLoader();
      60             : 
      61             :     virtual MOZ_MUST_USE nsresult Init();
      62             : 
      63             :     static already_AddRefed<nsDocLoader> GetAsDocLoader(nsISupports* aSupports);
      64             :     // Needed to deal with ambiguous inheritance from nsISupports...
      65         654 :     static nsISupports* GetAsSupports(nsDocLoader* aDocLoader) {
      66         654 :         return static_cast<nsIDocumentLoader*>(aDocLoader);
      67             :     }
      68             : 
      69             :     // Add aDocLoader as a child to the docloader service.
      70             :     static MOZ_MUST_USE nsresult AddDocLoaderAsChildOfRoot(nsDocLoader* aDocLoader);
      71             : 
      72             :     NS_DECL_ISUPPORTS
      73             :     NS_DECL_NSIDOCUMENTLOADER
      74             : 
      75             :     // nsIProgressEventSink
      76             :     NS_DECL_NSIPROGRESSEVENTSINK
      77             : 
      78             :     NS_DECL_NSISECURITYEVENTSINK
      79             : 
      80             :     // nsIRequestObserver methods: (for observing the load group)
      81             :     NS_DECL_NSIREQUESTOBSERVER
      82             :     NS_DECL_NSIWEBPROGRESS
      83             : 
      84             :     NS_DECL_NSIINTERFACEREQUESTOR
      85             :     NS_DECL_NSICHANNELEVENTSINK
      86             :     NS_DECL_NSISUPPORTSPRIORITY
      87             : 
      88             :     // Implementation specific methods...
      89             : 
      90             :     // Remove aChild from our childlist.  This nulls out the child's mParent
      91             :     // pointer.
      92             :     MOZ_MUST_USE nsresult RemoveChildLoader(nsDocLoader *aChild);
      93             :     // Add aChild to our child list.  This will set aChild's mParent pointer to
      94             :     // |this|.
      95             :     MOZ_MUST_USE nsresult AddChildLoader(nsDocLoader* aChild);
      96           6 :     nsDocLoader* GetParent() const { return mParent; }
      97             : 
      98          44 :     struct nsListenerInfo {
      99          20 :       nsListenerInfo(nsIWeakReference *aListener, unsigned long aNotifyMask)
     100          20 :         : mWeakListener(aListener),
     101          20 :           mNotifyMask(aNotifyMask)
     102             :       {
     103          20 :       }
     104             : 
     105             :       // Weak pointer for the nsIWebProgressListener...
     106             :       nsWeakPtr mWeakListener;
     107             : 
     108             :       // Mask indicating which notifications the listener wants to receive.
     109             :       unsigned long mNotifyMask;
     110             :     };
     111             : 
     112             : protected:
     113             :     virtual ~nsDocLoader();
     114             : 
     115             :     virtual MOZ_MUST_USE nsresult SetDocLoaderParent(nsDocLoader * aLoader);
     116             : 
     117             :     bool IsBusy();
     118             : 
     119             :     void Destroy();
     120             :     virtual void DestroyChildren();
     121             : 
     122          42 :     nsIDocumentLoader* ChildAt(int32_t i) {
     123          42 :         return mChildList.SafeElementAt(i, nullptr);
     124             :     }
     125             : 
     126             :     void FireOnProgressChange(nsDocLoader* aLoadInitiator,
     127             :                               nsIRequest *request,
     128             :                               int64_t aProgress,
     129             :                               int64_t aProgressMax,
     130             :                               int64_t aProgressDelta,
     131             :                               int64_t aTotalProgress,
     132             :                               int64_t aMaxTotalProgress);
     133             : 
     134             :     // This should be at least 2 long since we'll generally always
     135             :     // have the current page and the global docloader on the ancestor
     136             :     // list.  But to deal with frames it's better to make it a bit
     137             :     // longer, and it's always a stack temporary so there's no real
     138             :     // reason not to.
     139             :     typedef AutoTArray<RefPtr<nsDocLoader>, 8> WebProgressList;
     140             :     void GatherAncestorWebProgresses(WebProgressList& aList);
     141             : 
     142             :     void FireOnStateChange(nsIWebProgress *aProgress,
     143             :                            nsIRequest* request,
     144             :                            int32_t aStateFlags,
     145             :                            nsresult aStatus);
     146             : 
     147             :     // The guts of FireOnStateChange, but does not call itself on our ancestors.
     148             :     // The arguments that are const are const so that we can detect cases when
     149             :     // DoFireOnStateChange wants to propagate changes to the next web progress
     150             :     // at compile time.  The ones that are not, are references so that such
     151             :     // changes can be propagated.
     152             :     void DoFireOnStateChange(nsIWebProgress * const aProgress,
     153             :                              nsIRequest* const request,
     154             :                              int32_t &aStateFlags,
     155             :                              const nsresult aStatus);
     156             : 
     157             :     void FireOnStatusChange(nsIWebProgress *aWebProgress,
     158             :                             nsIRequest *aRequest,
     159             :                             nsresult aStatus,
     160             :                             const char16_t* aMessage);
     161             : 
     162             :     void FireOnLocationChange(nsIWebProgress* aWebProgress,
     163             :                               nsIRequest* aRequest,
     164             :                               nsIURI *aUri,
     165             :                               uint32_t aFlags);
     166             : 
     167             :     MOZ_MUST_USE bool RefreshAttempted(nsIWebProgress* aWebProgress,
     168             :                             nsIURI *aURI,
     169             :                             int32_t aDelay,
     170             :                             bool aSameURI);
     171             : 
     172             :     // this function is overridden by the docshell, it is provided so that we
     173             :     // can pass more information about redirect state (the normal OnStateChange
     174             :     // doesn't get the new channel).
     175             :     // @param aRedirectFlags The flags being sent to OnStateChange that
     176             :     //                       indicate the type of redirect.
     177             :     // @param aStateFlags    The channel flags normally sent to OnStateChange.
     178           0 :     virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
     179             :                                        nsIChannel* aNewChannel,
     180             :                                        uint32_t aRedirectFlags,
     181           0 :                                        uint32_t aStateFlags) {}
     182             : 
     183             :     void doStartDocumentLoad();
     184             :     void doStartURLLoad(nsIRequest *request, int32_t aExtraFlags);
     185             :     void doStopURLLoad(nsIRequest *request, nsresult aStatus);
     186             :     void doStopDocumentLoad(nsIRequest *request, nsresult aStatus);
     187             : 
     188             :     // Inform a parent docloader that aChild is about to call its onload
     189             :     // handler.
     190           6 :     MOZ_MUST_USE bool ChildEnteringOnload(nsIDocumentLoader* aChild) {
     191             :         // It's ok if we're already in the list -- we'll just be in there twice
     192             :         // and then the RemoveObject calls from ChildDoneWithOnload will remove
     193             :         // us.
     194           6 :         return mChildrenInOnload.AppendObject(aChild);
     195             :     }
     196             : 
     197             :     // Inform a parent docloader that aChild is done calling its onload
     198             :     // handler.
     199           6 :     void ChildDoneWithOnload(nsIDocumentLoader* aChild) {
     200           6 :         mChildrenInOnload.RemoveObject(aChild);
     201           6 :         DocLoaderIsEmpty(true);
     202           6 :     }
     203             : 
     204             : protected:
     205             :     struct nsStatusInfo : public mozilla::LinkedListElement<nsStatusInfo>
     206             :     {
     207             :         nsString mStatusMessage;
     208             :         nsresult mStatusCode;
     209             :         // Weak mRequest is ok; we'll be told if it decides to go away.
     210             :         nsIRequest * const mRequest;
     211             : 
     212           4 :         explicit nsStatusInfo(nsIRequest* aRequest) :
     213           4 :             mRequest(aRequest)
     214             :         {
     215           4 :             MOZ_COUNT_CTOR(nsStatusInfo);
     216           4 :         }
     217           4 :         ~nsStatusInfo()
     218           4 :         {
     219           4 :             MOZ_COUNT_DTOR(nsStatusInfo);
     220           4 :         }
     221             :     };
     222             : 
     223             :     struct nsRequestInfo : public PLDHashEntryHdr
     224             :     {
     225          76 :         explicit nsRequestInfo(const void* key)
     226          76 :             : mKey(key), mCurrentProgress(0), mMaxProgress(0), mUploading(false)
     227          76 :             , mLastStatus(nullptr)
     228             :         {
     229          76 :             MOZ_COUNT_CTOR(nsRequestInfo);
     230          76 :         }
     231             : 
     232          76 :         ~nsRequestInfo()
     233          76 :         {
     234          76 :             MOZ_COUNT_DTOR(nsRequestInfo);
     235          76 :         }
     236             : 
     237             :         nsIRequest* Request() {
     238             :             return static_cast<nsIRequest*>(const_cast<void*>(mKey));
     239             :         }
     240             : 
     241             :         const void* mKey; // Must be first for the PLDHashTable stubs to work
     242             :         int64_t mCurrentProgress;
     243             :         int64_t mMaxProgress;
     244             :         bool mUploading;
     245             : 
     246             :         nsAutoPtr<nsStatusInfo> mLastStatus;
     247             :     };
     248             : 
     249             :     static void RequestInfoHashInitEntry(PLDHashEntryHdr* entry, const void* key);
     250             :     static void RequestInfoHashClearEntry(PLDHashTable* table, PLDHashEntryHdr* entry);
     251             : 
     252             :     // IMPORTANT: The ownership implicit in the following member
     253             :     // variables has been explicitly checked and set using nsCOMPtr
     254             :     // for owning pointers and raw COM interface pointers for weak
     255             :     // (ie, non owning) references. If you add any members to this
     256             :     // class, please make the ownership explicit (pinkerton, scc).
     257             : 
     258             :     nsCOMPtr<nsIRequest>       mDocumentRequest;       // [OWNER] ???compare with document
     259             : 
     260             :     nsDocLoader*               mParent;                // [WEAK]
     261             : 
     262             :     typedef nsAutoTObserverArray<nsListenerInfo, 8> ListenerArray;
     263             :     ListenerArray              mListenerInfoList;
     264             : 
     265             :     nsCOMPtr<nsILoadGroup>        mLoadGroup;
     266             :     // We hold weak refs to all our kids
     267             :     nsTObserverArray<nsDocLoader*> mChildList;
     268             : 
     269             :     // The following member variables are related to the new nsIWebProgress
     270             :     // feedback interfaces that travis cooked up.
     271             :     int32_t mProgressStateFlags;
     272             : 
     273             :     int64_t mCurrentSelfProgress;
     274             :     int64_t mMaxSelfProgress;
     275             : 
     276             :     int64_t mCurrentTotalProgress;
     277             :     int64_t mMaxTotalProgress;
     278             : 
     279             :     PLDHashTable mRequestInfoHash;
     280             :     int64_t mCompletedTotalProgress;
     281             : 
     282             :     mozilla::LinkedList<nsStatusInfo> mStatusInfoList;
     283             : 
     284             :     /*
     285             :      * This flag indicates that the loader is loading a document.  It is set
     286             :      * from the call to LoadDocument(...) until the OnConnectionsComplete(...)
     287             :      * notification is fired...
     288             :      */
     289             :     bool mIsLoadingDocument;
     290             : 
     291             :     /* Flag to indicate that we're in the process of restoring a document. */
     292             :     bool mIsRestoringDocument;
     293             : 
     294             :     /* Flag to indicate that we're in the process of flushing layout
     295             :        under DocLoaderIsEmpty() and should not do another flush. */
     296             :     bool mDontFlushLayout;
     297             : 
     298             :     /* Flag to indicate whether we should consider ourselves as currently
     299             :        flushing layout for the purposes of IsBusy. For example, if Stop has
     300             :        been called then IsBusy should return false even if we are still
     301             :        flushing. */
     302             :     bool mIsFlushingLayout;
     303             : 
     304             : private:
     305             :     static const PLDHashTableOps sRequestInfoHashOps;
     306             : 
     307             :     // A list of kids that are in the middle of their onload calls and will let
     308             :     // us know once they're done.  We don't want to fire onload for "normal"
     309             :     // DocLoaderIsEmpty calls (those coming from requests finishing in our
     310             :     // loadgroup) unless this is empty.
     311             :     nsCOMArray<nsIDocumentLoader> mChildrenInOnload;
     312             : 
     313             :     // DocLoaderIsEmpty should be called whenever the docloader may be empty.
     314             :     // This method is idempotent and does nothing if the docloader is not in
     315             :     // fact empty.  This method _does_ make sure that layout is flushed if our
     316             :     // loadgroup has no active requests before checking for "real" emptiness if
     317             :     // aFlushLayout is true.
     318             :     void DocLoaderIsEmpty(bool aFlushLayout);
     319             : 
     320             :     int64_t GetMaxTotalProgress();
     321             : 
     322             :     nsresult AddRequestInfo(nsIRequest* aRequest);
     323             :     void RemoveRequestInfo(nsIRequest* aRequest);
     324             :     nsRequestInfo *GetRequestInfo(nsIRequest* aRequest);
     325             :     void ClearRequestInfoHash();
     326             :     int64_t CalculateMaxProgress();
     327             : ///    void DumpChannelInfo(void);
     328             : 
     329             :     // used to clear our internal progress state between loads...
     330             :     void ClearInternalProgress();
     331             : };
     332             : 
     333             : NS_DEFINE_STATIC_IID_ACCESSOR(nsDocLoader, NS_THIS_DOCLOADER_IMPL_CID)
     334             : 
     335             : #endif /* nsDocLoader_h__ */

Generated by: LCOV version 1.13