uriloader/base/nsDocLoader.h

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

mercurial