1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 2001
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Stuart Parmenter <pavlov@netscape.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef imgRequestProxy_h__
41 : #define imgRequestProxy_h__
42 :
43 : #include "imgIRequest.h"
44 : #include "imgIDecoderObserver.h"
45 : #include "nsISecurityInfoProvider.h"
46 :
47 : #include "nsIRequestObserver.h"
48 : #include "nsIChannel.h"
49 : #include "nsILoadGroup.h"
50 : #include "nsISupportsPriority.h"
51 : #include "nsITimedChannel.h"
52 : #include "nsCOMPtr.h"
53 : #include "nsAutoPtr.h"
54 : #include "nsThreadUtils.h"
55 :
56 : #include "imgRequest.h"
57 :
58 : #define NS_IMGREQUESTPROXY_CID \
59 : { /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \
60 : 0x20557898, \
61 : 0x1dd2, \
62 : 0x11b2, \
63 : {0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
64 : }
65 :
66 : class imgRequestNotifyRunnable;
67 : class imgStatusNotifyRunnable;
68 :
69 : namespace mozilla {
70 : namespace image {
71 : class Image;
72 : } // namespace image
73 : } // namespace mozilla
74 :
75 : class imgRequestProxy : public imgIRequest,
76 : public nsISupportsPriority,
77 : public nsISecurityInfoProvider,
78 : public nsITimedChannel
79 : {
80 : public:
81 : NS_DECL_ISUPPORTS
82 : NS_DECL_IMGIREQUEST
83 : NS_DECL_NSIREQUEST
84 : NS_DECL_NSISUPPORTSPRIORITY
85 : NS_DECL_NSISECURITYINFOPROVIDER
86 : // nsITimedChannel declared below
87 :
88 : imgRequestProxy();
89 : virtual ~imgRequestProxy();
90 :
91 : // Callers to Init or ChangeOwner are required to call NotifyListener after
92 : // (although not immediately after) doing so.
93 : nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup,
94 : mozilla::image::Image* aImage,
95 : nsIURI* aURI, imgIDecoderObserver *aObserver);
96 :
97 : nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous
98 : // owner has already sent notifications out!
99 :
100 : void AddToLoadGroup();
101 : void RemoveFromLoadGroup(bool releaseLoadGroup);
102 :
103 8 : inline bool HasObserver() const {
104 8 : return mListener != nsnull;
105 : }
106 :
107 : void SetPrincipal(nsIPrincipal *aPrincipal);
108 :
109 : // Asynchronously notify this proxy's listener of the current state of the
110 : // image, and, if we have an imgRequest mOwner, any status changes that
111 : // happen between the time this function is called and the time the
112 : // notification is scheduled.
113 : void NotifyListener();
114 :
115 : // Synchronously notify this proxy's listener of the current state of the
116 : // image. Only use this function if you are currently servicing an
117 : // asynchronously-called function.
118 : void SyncNotifyListener();
119 :
120 : // Whether we want notifications from imgStatusTracker to be deferred until
121 : // an event it has scheduled has been fired.
122 158 : bool NotificationsDeferred() const
123 : {
124 158 : return mDeferNotifications;
125 : }
126 14 : void SetNotificationsDeferred(bool aDeferNotifications)
127 : {
128 14 : mDeferNotifications = aDeferNotifications;
129 14 : }
130 :
131 : // Setter for our |mImage| pointer, for imgRequest to use, once it
132 : // instantiates an Image.
133 : void SetImage(mozilla::image::Image* aImage);
134 :
135 : // Removes all animation consumers that were created with
136 : // IncrementAnimationConsumers. This is necessary since we need
137 : // to do it before the proxy itself is destroyed. See
138 : // imgRequest::RemoveProxy
139 : void ClearAnimationConsumers();
140 :
141 : protected:
142 : friend class imgStatusTracker;
143 : friend class imgStatusNotifyRunnable;
144 : friend class imgRequestNotifyRunnable;
145 :
146 : class imgCancelRunnable;
147 : friend class imgCancelRunnable;
148 :
149 : class imgCancelRunnable : public nsRunnable
150 116 : {
151 : public:
152 29 : imgCancelRunnable(imgRequestProxy* owner, nsresult status)
153 29 : : mOwner(owner), mStatus(status)
154 29 : {}
155 :
156 29 : NS_IMETHOD Run() {
157 29 : mOwner->DoCancel(mStatus);
158 29 : return NS_OK;
159 : }
160 :
161 : private:
162 : nsRefPtr<imgRequestProxy> mOwner;
163 : nsresult mStatus;
164 : };
165 :
166 : // The following notification functions are protected to ensure that (friend
167 : // class) imgStatusTracker is the only class allowed to send us
168 : // notifications.
169 :
170 : /* non-virtual imgIDecoderObserver methods */
171 : void OnStartDecode ();
172 : void OnStartContainer (imgIContainer *aContainer);
173 : void OnStartFrame (PRUint32 aFrame);
174 : void OnDataAvailable (bool aCurrentFrame, const nsIntRect * aRect);
175 : void OnStopFrame (PRUint32 aFrame);
176 : void OnStopContainer (imgIContainer *aContainer);
177 : void OnStopDecode (nsresult status, const PRUnichar *statusArg);
178 : void OnDiscard ();
179 : void OnImageIsAnimated ();
180 :
181 : /* non-virtual imgIContainerObserver methods */
182 : void FrameChanged(imgIContainer *aContainer,
183 : const nsIntRect *aDirtyRect);
184 :
185 : /* non-virtual sort-of-nsIRequestObserver methods */
186 : void OnStartRequest();
187 : void OnStopRequest(bool aLastPart);
188 :
189 : /* Finish up canceling ourselves */
190 : void DoCancel(nsresult status);
191 :
192 : /* Do the proper refcount management to null out mListener */
193 : void NullOutListener();
194 :
195 0 : void DoRemoveFromLoadGroup() {
196 0 : RemoveFromLoadGroup(true);
197 0 : }
198 :
199 : // Return the imgStatusTracker associated with mOwner and/or mImage. It may
200 : // live either on mOwner or mImage, depending on whether
201 : // (a) we have an mOwner at all
202 : // (b) whether mOwner has instantiated its image yet
203 : imgStatusTracker& GetStatusTracker();
204 :
205 313 : nsITimedChannel* TimedChannel()
206 : {
207 313 : if (!mOwner)
208 40 : return nsnull;
209 273 : return mOwner->mTimedChannel;
210 : }
211 :
212 : public:
213 0 : NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
214 :
215 : private:
216 : friend class imgCacheValidator;
217 :
218 : // We maintain the following invariant:
219 : // The proxy is registered at most with a single imgRequest as an observer,
220 : // and whenever it is, mOwner points to that object. This helps ensure that
221 : // imgRequestProxy::~imgRequestProxy unregisters the proxy as an observer
222 : // from whatever request it was registered with (if any). This, in turn,
223 : // means that imgRequest::mObservers will not have any stale pointers in it.
224 : nsRefPtr<imgRequest> mOwner;
225 :
226 : // The URI of our request.
227 : nsCOMPtr<nsIURI> mURI;
228 :
229 : // The image we represent. Is null until data has been received, and is then
230 : // set by imgRequest.
231 : nsRefPtr<mozilla::image::Image> mImage;
232 :
233 : // Our principal. Is null until data has been received from the channel, and
234 : // is then set by imgRequest.
235 : nsCOMPtr<nsIPrincipal> mPrincipal;
236 :
237 : // mListener is only promised to be a weak ref (see imgILoader.idl),
238 : // but we actually keep a strong ref to it until we've seen our
239 : // first OnStopRequest.
240 : imgIDecoderObserver* mListener;
241 : nsCOMPtr<nsILoadGroup> mLoadGroup;
242 :
243 : nsLoadFlags mLoadFlags;
244 : PRUint32 mLockCount;
245 : PRUint32 mAnimationConsumers;
246 : bool mCanceled;
247 : bool mIsInLoadGroup;
248 : bool mListenerIsStrongRef;
249 : bool mDecodeRequested;
250 :
251 : // Whether we want to defer our notifications by the non-virtual Observer
252 : // interfaces as image loads proceed.
253 : bool mDeferNotifications;
254 :
255 : // We only want to send OnStartContainer once for each proxy, but we might
256 : // get multiple OnStartContainer calls (e.g. from multipart/x-mixed-replace).
257 : bool mSentStartContainer;
258 : };
259 :
260 : #endif // imgRequestProxy_h__
|