1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1999
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /*
39 : */
40 :
41 : #ifndef nsDocLoader_h__
42 : #define nsDocLoader_h__
43 :
44 : #include "nsIDocumentLoader.h"
45 : #include "nsIWebProgress.h"
46 : #include "nsIWebProgressListener.h"
47 : #include "nsIRequestObserver.h"
48 : #include "nsWeakReference.h"
49 : #include "nsILoadGroup.h"
50 : #include "nsCOMArray.h"
51 : #include "nsVoidArray.h"
52 : #include "nsString.h"
53 : #include "nsIChannel.h"
54 : #include "nsIProgressEventSink.h"
55 : #include "nsIInterfaceRequestor.h"
56 : #include "nsIInterfaceRequestorUtils.h"
57 : #include "nsIChannelEventSink.h"
58 : #include "nsISecurityEventSink.h"
59 : #include "nsISupportsPriority.h"
60 : #include "nsCOMPtr.h"
61 : #include "pldhash.h"
62 : #include "prclist.h"
63 : #include "nsAutoPtr.h"
64 :
65 : struct nsRequestInfo;
66 : struct nsListenerInfo;
67 :
68 : /****************************************************************************
69 : * nsDocLoader implementation...
70 : ****************************************************************************/
71 :
72 : #define NS_THIS_DOCLOADER_IMPL_CID \
73 : { /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */ \
74 : 0xb4ec8387, \
75 : 0x98aa, \
76 : 0x4c08, \
77 : {0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \
78 : }
79 :
80 : class nsDocLoader : public nsIDocumentLoader,
81 : public nsIRequestObserver,
82 : public nsSupportsWeakReference,
83 : public nsIProgressEventSink,
84 : public nsIWebProgress,
85 : public nsIInterfaceRequestor,
86 : public nsIChannelEventSink,
87 : public nsISecurityEventSink,
88 : public nsISupportsPriority
89 : {
90 : public:
91 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_THIS_DOCLOADER_IMPL_CID)
92 :
93 : nsDocLoader();
94 :
95 : virtual nsresult Init();
96 :
97 : static already_AddRefed<nsDocLoader> GetAsDocLoader(nsISupports* aSupports);
98 : // Needed to deal with ambiguous inheritance from nsISupports...
99 0 : static nsISupports* GetAsSupports(nsDocLoader* aDocLoader) {
100 0 : return static_cast<nsIDocumentLoader*>(aDocLoader);
101 : }
102 :
103 : // Add aDocLoader as a child to the docloader service.
104 : static nsresult AddDocLoaderAsChildOfRoot(nsDocLoader* aDocLoader);
105 :
106 : NS_DECL_ISUPPORTS
107 : NS_DECL_NSIDOCUMENTLOADER
108 :
109 : // nsIProgressEventSink
110 : NS_DECL_NSIPROGRESSEVENTSINK
111 :
112 : NS_DECL_NSISECURITYEVENTSINK
113 :
114 : // nsIRequestObserver methods: (for observing the load group)
115 : NS_DECL_NSIREQUESTOBSERVER
116 : NS_DECL_NSIWEBPROGRESS
117 :
118 : NS_DECL_NSIINTERFACEREQUESTOR
119 : NS_DECL_NSICHANNELEVENTSINK
120 : NS_DECL_NSISUPPORTSPRIORITY
121 :
122 : // Implementation specific methods...
123 :
124 : // Remove aChild from our childlist. This nulls out the child's mParent
125 : // pointer.
126 : nsresult RemoveChildLoader(nsDocLoader *aChild);
127 : // Add aChild to our child list. This will set aChild's mParent pointer to
128 : // |this|.
129 : nsresult AddChildLoader(nsDocLoader* aChild);
130 : nsDocLoader* GetParent() const { return mParent; }
131 :
132 : protected:
133 : virtual ~nsDocLoader();
134 :
135 : virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
136 :
137 : bool IsBusy();
138 :
139 : void Destroy();
140 : virtual void DestroyChildren();
141 :
142 0 : nsIDocumentLoader* ChildAt(PRInt32 i) {
143 0 : return static_cast<nsDocLoader*>(mChildList[i]);
144 : }
145 :
146 : nsIDocumentLoader* SafeChildAt(PRInt32 i) {
147 : return static_cast<nsDocLoader*>(mChildList.SafeElementAt(i));
148 : }
149 :
150 : void FireOnProgressChange(nsDocLoader* aLoadInitiator,
151 : nsIRequest *request,
152 : PRInt64 aProgress,
153 : PRInt64 aProgressMax,
154 : PRInt64 aProgressDelta,
155 : PRInt64 aTotalProgress,
156 : PRInt64 aMaxTotalProgress);
157 :
158 : // This should be at least 2 long since we'll generally always
159 : // have the current page and the global docloader on the ancestor
160 : // list. But to deal with frames it's better to make it a bit
161 : // longer, and it's always a stack temporary so there's no real
162 : // reason not to.
163 : typedef nsAutoTArray<nsRefPtr<nsDocLoader>, 8> WebProgressList;
164 : void GatherAncestorWebProgresses(WebProgressList& aList);
165 :
166 : void FireOnStateChange(nsIWebProgress *aProgress,
167 : nsIRequest* request,
168 : PRInt32 aStateFlags,
169 : nsresult aStatus);
170 :
171 : // The guts of FireOnStateChange, but does not call itself on our ancestors.
172 : // The arguments that are const are const so that we can detect cases when
173 : // DoFireOnStateChange wants to propagate changes to the next web progress
174 : // at compile time. The ones that are not, are references so that such
175 : // changes can be propagated.
176 : void DoFireOnStateChange(nsIWebProgress * const aProgress,
177 : nsIRequest* const request,
178 : PRInt32 &aStateFlags,
179 : const nsresult aStatus);
180 :
181 : void FireOnStatusChange(nsIWebProgress *aWebProgress,
182 : nsIRequest *aRequest,
183 : nsresult aStatus,
184 : const PRUnichar* aMessage);
185 :
186 : void FireOnLocationChange(nsIWebProgress* aWebProgress,
187 : nsIRequest* aRequest,
188 : nsIURI *aUri,
189 : PRUint32 aFlags);
190 :
191 : bool RefreshAttempted(nsIWebProgress* aWebProgress,
192 : nsIURI *aURI,
193 : PRInt32 aDelay,
194 : bool aSameURI);
195 :
196 : // this function is overridden by the docshell, it is provided so that we
197 : // can pass more information about redirect state (the normal OnStateChange
198 : // doesn't get the new channel).
199 : // @param aRedirectFlags The flags being sent to OnStateChange that
200 : // indicate the type of redirect.
201 : // @param aStateFlags The channel flags normally sent to OnStateChange.
202 0 : virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
203 : nsIChannel* aNewChannel,
204 : PRUint32 aRedirectFlags,
205 0 : PRUint32 aStateFlags) {}
206 :
207 : void doStartDocumentLoad();
208 : void doStartURLLoad(nsIRequest *request);
209 : void doStopURLLoad(nsIRequest *request, nsresult aStatus);
210 : void doStopDocumentLoad(nsIRequest *request, nsresult aStatus);
211 :
212 : // Inform a parent docloader that aChild is about to call its onload
213 : // handler.
214 0 : bool ChildEnteringOnload(nsIDocumentLoader* aChild) {
215 : // It's ok if we're already in the list -- we'll just be in there twice
216 : // and then the RemoveObject calls from ChildDoneWithOnload will remove
217 : // us.
218 0 : return mChildrenInOnload.AppendObject(aChild);
219 : }
220 :
221 : // Inform a parent docloader that aChild is done calling its onload
222 : // handler.
223 0 : void ChildDoneWithOnload(nsIDocumentLoader* aChild) {
224 0 : mChildrenInOnload.RemoveObject(aChild);
225 0 : DocLoaderIsEmpty(true);
226 0 : }
227 :
228 : protected:
229 : // IMPORTANT: The ownership implicit in the following member
230 : // variables has been explicitly checked and set using nsCOMPtr
231 : // for owning pointers and raw COM interface pointers for weak
232 : // (ie, non owning) references. If you add any members to this
233 : // class, please make the ownership explicit (pinkerton, scc).
234 :
235 : nsCOMPtr<nsIRequest> mDocumentRequest; // [OWNER] ???compare with document
236 :
237 : nsDocLoader* mParent; // [WEAK]
238 :
239 : nsVoidArray mListenerInfoList;
240 :
241 : nsCOMPtr<nsILoadGroup> mLoadGroup;
242 : // We hold weak refs to all our kids
243 : nsVoidArray mChildList;
244 :
245 : // The following member variables are related to the new nsIWebProgress
246 : // feedback interfaces that travis cooked up.
247 : PRInt32 mProgressStateFlags;
248 :
249 : PRInt64 mCurrentSelfProgress;
250 : PRInt64 mMaxSelfProgress;
251 :
252 : PRInt64 mCurrentTotalProgress;
253 : PRInt64 mMaxTotalProgress;
254 :
255 : PLDHashTable mRequestInfoHash;
256 : PRInt64 mCompletedTotalProgress;
257 :
258 : PRCList mStatusInfoList;
259 :
260 : /*
261 : * This flag indicates that the loader is loading a document. It is set
262 : * from the call to LoadDocument(...) until the OnConnectionsComplete(...)
263 : * notification is fired...
264 : */
265 : bool mIsLoadingDocument;
266 :
267 : /* Flag to indicate that we're in the process of restoring a document. */
268 : bool mIsRestoringDocument;
269 :
270 : /* Flag to indicate that we're in the process of flushing layout
271 : under DocLoaderIsEmpty() and should not do another flush. */
272 : bool mDontFlushLayout;
273 :
274 : /* Flag to indicate whether we should consider ourselves as currently
275 : flushing layout for the purposes of IsBusy. For example, if Stop has
276 : been called then IsBusy should return false even if we are still
277 : flushing. */
278 : bool mIsFlushingLayout;
279 :
280 : private:
281 : // A list of kids that are in the middle of their onload calls and will let
282 : // us know once they're done. We don't want to fire onload for "normal"
283 : // DocLoaderIsEmpty calls (those coming from requests finishing in our
284 : // loadgroup) unless this is empty.
285 : nsCOMArray<nsIDocumentLoader> mChildrenInOnload;
286 :
287 : // DocLoaderIsEmpty should be called whenever the docloader may be empty.
288 : // This method is idempotent and does nothing if the docloader is not in
289 : // fact empty. This method _does_ make sure that layout is flushed if our
290 : // loadgroup has no active requests before checking for "real" emptiness if
291 : // aFlushLayout is true.
292 : void DocLoaderIsEmpty(bool aFlushLayout);
293 :
294 : nsListenerInfo *GetListenerInfo(nsIWebProgressListener* aListener);
295 :
296 : PRInt64 GetMaxTotalProgress();
297 :
298 : nsresult AddRequestInfo(nsIRequest* aRequest);
299 : void RemoveRequestInfo(nsIRequest* aRequest);
300 : nsRequestInfo *GetRequestInfo(nsIRequest* aRequest);
301 : void ClearRequestInfoHash();
302 : PRInt64 CalculateMaxProgress();
303 : /// void DumpChannelInfo(void);
304 :
305 : // used to clear our internal progress state between loads...
306 : void ClearInternalProgress();
307 : };
308 :
309 : NS_DEFINE_STATIC_IID_ACCESSOR(nsDocLoader, NS_THIS_DOCLOADER_IMPL_CID)
310 :
311 : #endif /* nsDocLoader_h__ */
|