1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/uriloader/base/nsDocLoader.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,327 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +*/ 1.11 + 1.12 +#ifndef nsDocLoader_h__ 1.13 +#define nsDocLoader_h__ 1.14 + 1.15 +#include "nsIDocumentLoader.h" 1.16 +#include "nsIWebProgress.h" 1.17 +#include "nsIWebProgressListener.h" 1.18 +#include "nsIRequestObserver.h" 1.19 +#include "nsWeakReference.h" 1.20 +#include "nsILoadGroup.h" 1.21 +#include "nsCOMArray.h" 1.22 +#include "nsTObserverArray.h" 1.23 +#include "nsVoidArray.h" 1.24 +#include "nsString.h" 1.25 +#include "nsIChannel.h" 1.26 +#include "nsIProgressEventSink.h" 1.27 +#include "nsIInterfaceRequestor.h" 1.28 +#include "nsIInterfaceRequestorUtils.h" 1.29 +#include "nsIChannelEventSink.h" 1.30 +#include "nsISecurityEventSink.h" 1.31 +#include "nsISupportsPriority.h" 1.32 +#include "nsCOMPtr.h" 1.33 +#include "pldhash.h" 1.34 +#include "nsAutoPtr.h" 1.35 + 1.36 +#include "mozilla/LinkedList.h" 1.37 + 1.38 +struct nsListenerInfo; 1.39 + 1.40 +/**************************************************************************** 1.41 + * nsDocLoader implementation... 1.42 + ****************************************************************************/ 1.43 + 1.44 +#define NS_THIS_DOCLOADER_IMPL_CID \ 1.45 + { /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */ \ 1.46 + 0xb4ec8387, \ 1.47 + 0x98aa, \ 1.48 + 0x4c08, \ 1.49 + {0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \ 1.50 + } 1.51 + 1.52 +class nsDocLoader : public nsIDocumentLoader, 1.53 + public nsIRequestObserver, 1.54 + public nsSupportsWeakReference, 1.55 + public nsIProgressEventSink, 1.56 + public nsIWebProgress, 1.57 + public nsIInterfaceRequestor, 1.58 + public nsIChannelEventSink, 1.59 + public nsISecurityEventSink, 1.60 + public nsISupportsPriority 1.61 +{ 1.62 +public: 1.63 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_THIS_DOCLOADER_IMPL_CID) 1.64 + 1.65 + nsDocLoader(); 1.66 + 1.67 + virtual nsresult Init(); 1.68 + 1.69 + static already_AddRefed<nsDocLoader> GetAsDocLoader(nsISupports* aSupports); 1.70 + // Needed to deal with ambiguous inheritance from nsISupports... 1.71 + static nsISupports* GetAsSupports(nsDocLoader* aDocLoader) { 1.72 + return static_cast<nsIDocumentLoader*>(aDocLoader); 1.73 + } 1.74 + 1.75 + // Add aDocLoader as a child to the docloader service. 1.76 + static nsresult AddDocLoaderAsChildOfRoot(nsDocLoader* aDocLoader); 1.77 + 1.78 + NS_DECL_ISUPPORTS 1.79 + NS_DECL_NSIDOCUMENTLOADER 1.80 + 1.81 + // nsIProgressEventSink 1.82 + NS_DECL_NSIPROGRESSEVENTSINK 1.83 + 1.84 + NS_DECL_NSISECURITYEVENTSINK 1.85 + 1.86 + // nsIRequestObserver methods: (for observing the load group) 1.87 + NS_DECL_NSIREQUESTOBSERVER 1.88 + NS_DECL_NSIWEBPROGRESS 1.89 + 1.90 + NS_DECL_NSIINTERFACEREQUESTOR 1.91 + NS_DECL_NSICHANNELEVENTSINK 1.92 + NS_DECL_NSISUPPORTSPRIORITY 1.93 + 1.94 + // Implementation specific methods... 1.95 + 1.96 + // Remove aChild from our childlist. This nulls out the child's mParent 1.97 + // pointer. 1.98 + nsresult RemoveChildLoader(nsDocLoader *aChild); 1.99 + // Add aChild to our child list. This will set aChild's mParent pointer to 1.100 + // |this|. 1.101 + nsresult AddChildLoader(nsDocLoader* aChild); 1.102 + nsDocLoader* GetParent() const { return mParent; } 1.103 + 1.104 +protected: 1.105 + virtual ~nsDocLoader(); 1.106 + 1.107 + virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); 1.108 + 1.109 + bool IsBusy(); 1.110 + 1.111 + void Destroy(); 1.112 + virtual void DestroyChildren(); 1.113 + 1.114 + nsIDocumentLoader* ChildAt(int32_t i) { 1.115 + return mChildList.SafeElementAt(i, nullptr); 1.116 + } 1.117 + 1.118 + void FireOnProgressChange(nsDocLoader* aLoadInitiator, 1.119 + nsIRequest *request, 1.120 + int64_t aProgress, 1.121 + int64_t aProgressMax, 1.122 + int64_t aProgressDelta, 1.123 + int64_t aTotalProgress, 1.124 + int64_t aMaxTotalProgress); 1.125 + 1.126 + // This should be at least 2 long since we'll generally always 1.127 + // have the current page and the global docloader on the ancestor 1.128 + // list. But to deal with frames it's better to make it a bit 1.129 + // longer, and it's always a stack temporary so there's no real 1.130 + // reason not to. 1.131 + typedef nsAutoTArray<nsRefPtr<nsDocLoader>, 8> WebProgressList; 1.132 + void GatherAncestorWebProgresses(WebProgressList& aList); 1.133 + 1.134 + void FireOnStateChange(nsIWebProgress *aProgress, 1.135 + nsIRequest* request, 1.136 + int32_t aStateFlags, 1.137 + nsresult aStatus); 1.138 + 1.139 + // The guts of FireOnStateChange, but does not call itself on our ancestors. 1.140 + // The arguments that are const are const so that we can detect cases when 1.141 + // DoFireOnStateChange wants to propagate changes to the next web progress 1.142 + // at compile time. The ones that are not, are references so that such 1.143 + // changes can be propagated. 1.144 + void DoFireOnStateChange(nsIWebProgress * const aProgress, 1.145 + nsIRequest* const request, 1.146 + int32_t &aStateFlags, 1.147 + const nsresult aStatus); 1.148 + 1.149 + void FireOnStatusChange(nsIWebProgress *aWebProgress, 1.150 + nsIRequest *aRequest, 1.151 + nsresult aStatus, 1.152 + const char16_t* aMessage); 1.153 + 1.154 + void FireOnLocationChange(nsIWebProgress* aWebProgress, 1.155 + nsIRequest* aRequest, 1.156 + nsIURI *aUri, 1.157 + uint32_t aFlags); 1.158 + 1.159 + bool RefreshAttempted(nsIWebProgress* aWebProgress, 1.160 + nsIURI *aURI, 1.161 + int32_t aDelay, 1.162 + bool aSameURI); 1.163 + 1.164 + // this function is overridden by the docshell, it is provided so that we 1.165 + // can pass more information about redirect state (the normal OnStateChange 1.166 + // doesn't get the new channel). 1.167 + // @param aRedirectFlags The flags being sent to OnStateChange that 1.168 + // indicate the type of redirect. 1.169 + // @param aStateFlags The channel flags normally sent to OnStateChange. 1.170 + virtual void OnRedirectStateChange(nsIChannel* aOldChannel, 1.171 + nsIChannel* aNewChannel, 1.172 + uint32_t aRedirectFlags, 1.173 + uint32_t aStateFlags) {} 1.174 + 1.175 + void doStartDocumentLoad(); 1.176 + void doStartURLLoad(nsIRequest *request); 1.177 + void doStopURLLoad(nsIRequest *request, nsresult aStatus); 1.178 + void doStopDocumentLoad(nsIRequest *request, nsresult aStatus); 1.179 + 1.180 + // Inform a parent docloader that aChild is about to call its onload 1.181 + // handler. 1.182 + bool ChildEnteringOnload(nsIDocumentLoader* aChild) { 1.183 + // It's ok if we're already in the list -- we'll just be in there twice 1.184 + // and then the RemoveObject calls from ChildDoneWithOnload will remove 1.185 + // us. 1.186 + return mChildrenInOnload.AppendObject(aChild); 1.187 + } 1.188 + 1.189 + // Inform a parent docloader that aChild is done calling its onload 1.190 + // handler. 1.191 + void ChildDoneWithOnload(nsIDocumentLoader* aChild) { 1.192 + mChildrenInOnload.RemoveObject(aChild); 1.193 + DocLoaderIsEmpty(true); 1.194 + } 1.195 + 1.196 +protected: 1.197 + struct nsStatusInfo : public mozilla::LinkedListElement<nsStatusInfo> 1.198 + { 1.199 + nsString mStatusMessage; 1.200 + nsresult mStatusCode; 1.201 + // Weak mRequest is ok; we'll be told if it decides to go away. 1.202 + nsIRequest * const mRequest; 1.203 + 1.204 + nsStatusInfo(nsIRequest* aRequest) : 1.205 + mRequest(aRequest) 1.206 + { 1.207 + MOZ_COUNT_CTOR(nsStatusInfo); 1.208 + } 1.209 + ~nsStatusInfo() 1.210 + { 1.211 + MOZ_COUNT_DTOR(nsStatusInfo); 1.212 + } 1.213 + }; 1.214 + 1.215 + struct nsRequestInfo : public PLDHashEntryHdr 1.216 + { 1.217 + nsRequestInfo(const void* key) 1.218 + : mKey(key), mCurrentProgress(0), mMaxProgress(0), mUploading(false) 1.219 + , mLastStatus(nullptr) 1.220 + { 1.221 + MOZ_COUNT_CTOR(nsRequestInfo); 1.222 + } 1.223 + 1.224 + ~nsRequestInfo() 1.225 + { 1.226 + MOZ_COUNT_DTOR(nsRequestInfo); 1.227 + } 1.228 + 1.229 + nsIRequest* Request() { 1.230 + return static_cast<nsIRequest*>(const_cast<void*>(mKey)); 1.231 + } 1.232 + 1.233 + const void* mKey; // Must be first for the pldhash stubs to work 1.234 + int64_t mCurrentProgress; 1.235 + int64_t mMaxProgress; 1.236 + bool mUploading; 1.237 + 1.238 + nsAutoPtr<nsStatusInfo> mLastStatus; 1.239 + }; 1.240 + 1.241 + static bool RequestInfoHashInitEntry(PLDHashTable* table, PLDHashEntryHdr* entry, 1.242 + const void* key); 1.243 + static void RequestInfoHashClearEntry(PLDHashTable* table, PLDHashEntryHdr* entry); 1.244 + 1.245 + // IMPORTANT: The ownership implicit in the following member 1.246 + // variables has been explicitly checked and set using nsCOMPtr 1.247 + // for owning pointers and raw COM interface pointers for weak 1.248 + // (ie, non owning) references. If you add any members to this 1.249 + // class, please make the ownership explicit (pinkerton, scc). 1.250 + 1.251 + nsCOMPtr<nsIRequest> mDocumentRequest; // [OWNER] ???compare with document 1.252 + 1.253 + nsDocLoader* mParent; // [WEAK] 1.254 + 1.255 + nsVoidArray mListenerInfoList; 1.256 + 1.257 + nsCOMPtr<nsILoadGroup> mLoadGroup; 1.258 + // We hold weak refs to all our kids 1.259 + nsTObserverArray<nsDocLoader*> mChildList; 1.260 + 1.261 + // The following member variables are related to the new nsIWebProgress 1.262 + // feedback interfaces that travis cooked up. 1.263 + int32_t mProgressStateFlags; 1.264 + 1.265 + int64_t mCurrentSelfProgress; 1.266 + int64_t mMaxSelfProgress; 1.267 + 1.268 + int64_t mCurrentTotalProgress; 1.269 + int64_t mMaxTotalProgress; 1.270 + 1.271 + PLDHashTable mRequestInfoHash; 1.272 + int64_t mCompletedTotalProgress; 1.273 + 1.274 + mozilla::LinkedList<nsStatusInfo> mStatusInfoList; 1.275 + 1.276 + /* 1.277 + * This flag indicates that the loader is loading a document. It is set 1.278 + * from the call to LoadDocument(...) until the OnConnectionsComplete(...) 1.279 + * notification is fired... 1.280 + */ 1.281 + bool mIsLoadingDocument; 1.282 + 1.283 + /* Flag to indicate that we're in the process of restoring a document. */ 1.284 + bool mIsRestoringDocument; 1.285 + 1.286 + /* Flag to indicate that we're in the process of flushing layout 1.287 + under DocLoaderIsEmpty() and should not do another flush. */ 1.288 + bool mDontFlushLayout; 1.289 + 1.290 + /* Flag to indicate whether we should consider ourselves as currently 1.291 + flushing layout for the purposes of IsBusy. For example, if Stop has 1.292 + been called then IsBusy should return false even if we are still 1.293 + flushing. */ 1.294 + bool mIsFlushingLayout; 1.295 + 1.296 +private: 1.297 + // A list of kids that are in the middle of their onload calls and will let 1.298 + // us know once they're done. We don't want to fire onload for "normal" 1.299 + // DocLoaderIsEmpty calls (those coming from requests finishing in our 1.300 + // loadgroup) unless this is empty. 1.301 + nsCOMArray<nsIDocumentLoader> mChildrenInOnload; 1.302 + 1.303 + // DocLoaderIsEmpty should be called whenever the docloader may be empty. 1.304 + // This method is idempotent and does nothing if the docloader is not in 1.305 + // fact empty. This method _does_ make sure that layout is flushed if our 1.306 + // loadgroup has no active requests before checking for "real" emptiness if 1.307 + // aFlushLayout is true. 1.308 + void DocLoaderIsEmpty(bool aFlushLayout); 1.309 + 1.310 + nsListenerInfo *GetListenerInfo(nsIWebProgressListener* aListener); 1.311 + 1.312 + int64_t GetMaxTotalProgress(); 1.313 + 1.314 + nsresult AddRequestInfo(nsIRequest* aRequest); 1.315 + void RemoveRequestInfo(nsIRequest* aRequest); 1.316 + nsRequestInfo *GetRequestInfo(nsIRequest* aRequest); 1.317 + void ClearRequestInfoHash(); 1.318 + int64_t CalculateMaxProgress(); 1.319 + static PLDHashOperator CalcMaxProgressCallback(PLDHashTable* table, 1.320 + PLDHashEntryHdr* hdr, 1.321 + uint32_t number, void* arg); 1.322 +/// void DumpChannelInfo(void); 1.323 + 1.324 + // used to clear our internal progress state between loads... 1.325 + void ClearInternalProgress(); 1.326 +}; 1.327 + 1.328 +NS_DEFINE_STATIC_IID_ACCESSOR(nsDocLoader, NS_THIS_DOCLOADER_IMPL_CID) 1.329 + 1.330 +#endif /* nsDocLoader_h__ */