|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef imgRequestProxy_h__ |
|
8 #define imgRequestProxy_h__ |
|
9 |
|
10 #include "mozilla/WeakPtr.h" |
|
11 #include "imgIRequest.h" |
|
12 #include "nsISecurityInfoProvider.h" |
|
13 |
|
14 #include "nsILoadGroup.h" |
|
15 #include "nsISupportsPriority.h" |
|
16 #include "nsITimedChannel.h" |
|
17 #include "nsCOMPtr.h" |
|
18 #include "nsAutoPtr.h" |
|
19 #include "nsThreadUtils.h" |
|
20 #include "mozilla/TimeStamp.h" |
|
21 |
|
22 #include "imgRequest.h" |
|
23 |
|
24 #define NS_IMGREQUESTPROXY_CID \ |
|
25 { /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \ |
|
26 0x20557898, \ |
|
27 0x1dd2, \ |
|
28 0x11b2, \ |
|
29 {0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \ |
|
30 } |
|
31 |
|
32 class imgINotificationObserver; |
|
33 class imgRequestNotifyRunnable; |
|
34 class imgStatusNotifyRunnable; |
|
35 class nsIntRect; |
|
36 class ProxyBehaviour; |
|
37 |
|
38 namespace mozilla { |
|
39 namespace image { |
|
40 class Image; |
|
41 class ImageURL; |
|
42 } // namespace image |
|
43 } // namespace mozilla |
|
44 |
|
45 class imgRequestProxy : public imgIRequest, |
|
46 public nsISupportsPriority, |
|
47 public nsISecurityInfoProvider, |
|
48 public nsITimedChannel, |
|
49 public mozilla::SupportsWeakPtr<imgRequestProxy> |
|
50 { |
|
51 public: |
|
52 MOZ_DECLARE_REFCOUNTED_TYPENAME(imgRequestProxy) |
|
53 typedef mozilla::image::ImageURL ImageURL; |
|
54 NS_DECL_ISUPPORTS |
|
55 NS_DECL_IMGIREQUEST |
|
56 NS_DECL_NSIREQUEST |
|
57 NS_DECL_NSISUPPORTSPRIORITY |
|
58 NS_DECL_NSISECURITYINFOPROVIDER |
|
59 // nsITimedChannel declared below |
|
60 |
|
61 imgRequestProxy(); |
|
62 virtual ~imgRequestProxy(); |
|
63 |
|
64 // Callers to Init or ChangeOwner are required to call NotifyListener after |
|
65 // (although not immediately after) doing so. |
|
66 nsresult Init(imgRequest* aOwner, |
|
67 nsILoadGroup *aLoadGroup, |
|
68 ImageURL* aURI, |
|
69 imgINotificationObserver *aObserver); |
|
70 |
|
71 nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous |
|
72 // owner has already sent notifications out! |
|
73 |
|
74 void AddToLoadGroup(); |
|
75 void RemoveFromLoadGroup(bool releaseLoadGroup); |
|
76 |
|
77 inline bool HasObserver() const { |
|
78 return mListener != nullptr; |
|
79 } |
|
80 |
|
81 // Asynchronously notify this proxy's listener of the current state of the |
|
82 // image, and, if we have an imgRequest mOwner, any status changes that |
|
83 // happen between the time this function is called and the time the |
|
84 // notification is scheduled. |
|
85 void NotifyListener(); |
|
86 |
|
87 // Synchronously notify this proxy's listener of the current state of the |
|
88 // image. Only use this function if you are currently servicing an |
|
89 // asynchronously-called function. |
|
90 void SyncNotifyListener(); |
|
91 |
|
92 // Whether we want notifications from imgStatusTracker to be deferred until |
|
93 // an event it has scheduled has been fired. |
|
94 bool NotificationsDeferred() const |
|
95 { |
|
96 return mDeferNotifications; |
|
97 } |
|
98 void SetNotificationsDeferred(bool aDeferNotifications) |
|
99 { |
|
100 mDeferNotifications = aDeferNotifications; |
|
101 } |
|
102 |
|
103 // XXXbholley - This eventually gets folded into the new notification API. |
|
104 void SetHasImage(); |
|
105 |
|
106 // Removes all animation consumers that were created with |
|
107 // IncrementAnimationConsumers. This is necessary since we need |
|
108 // to do it before the proxy itself is destroyed. See |
|
109 // imgRequest::RemoveProxy |
|
110 void ClearAnimationConsumers(); |
|
111 |
|
112 virtual nsresult Clone(imgINotificationObserver* aObserver, imgRequestProxy** aClone); |
|
113 nsresult GetStaticRequest(imgRequestProxy** aReturn); |
|
114 |
|
115 nsresult GetURI(ImageURL **aURI); |
|
116 |
|
117 protected: |
|
118 friend class imgStatusTracker; |
|
119 friend class imgStatusNotifyRunnable; |
|
120 friend class imgRequestNotifyRunnable; |
|
121 |
|
122 class imgCancelRunnable; |
|
123 friend class imgCancelRunnable; |
|
124 |
|
125 class imgCancelRunnable : public nsRunnable |
|
126 { |
|
127 public: |
|
128 imgCancelRunnable(imgRequestProxy* owner, nsresult status) |
|
129 : mOwner(owner), mStatus(status) |
|
130 {} |
|
131 |
|
132 NS_IMETHOD Run() { |
|
133 mOwner->DoCancel(mStatus); |
|
134 return NS_OK; |
|
135 } |
|
136 |
|
137 private: |
|
138 nsRefPtr<imgRequestProxy> mOwner; |
|
139 nsresult mStatus; |
|
140 }; |
|
141 |
|
142 // The following notification functions are protected to ensure that (friend |
|
143 // class) imgStatusTracker is the only class allowed to send us |
|
144 // notifications. |
|
145 |
|
146 /* non-virtual imgDecoderObserver methods */ |
|
147 void OnStartDecode (); |
|
148 void OnStartContainer (); |
|
149 void OnFrameUpdate (const nsIntRect * aRect); |
|
150 void OnStopFrame (); |
|
151 void OnStopDecode (); |
|
152 void OnDiscard (); |
|
153 void OnUnlockedDraw (); |
|
154 void OnImageIsAnimated (); |
|
155 |
|
156 /* non-virtual sort-of-nsIRequestObserver methods */ |
|
157 void OnStartRequest(); |
|
158 void OnStopRequest(bool aLastPart); |
|
159 |
|
160 /* non-virtual imgIOnloadBlocker methods */ |
|
161 void BlockOnload(); |
|
162 void UnblockOnload(); |
|
163 |
|
164 /* Finish up canceling ourselves */ |
|
165 void DoCancel(nsresult status); |
|
166 |
|
167 /* Do the proper refcount management to null out mListener */ |
|
168 void NullOutListener(); |
|
169 |
|
170 void DoRemoveFromLoadGroup() { |
|
171 RemoveFromLoadGroup(true); |
|
172 } |
|
173 |
|
174 // Return the imgStatusTracker associated with mOwner and/or mImage. It may |
|
175 // live either on mOwner or mImage, depending on whether |
|
176 // (a) we have an mOwner at all |
|
177 // (b) whether mOwner has instantiated its image yet |
|
178 already_AddRefed<imgStatusTracker> GetStatusTracker() const; |
|
179 |
|
180 nsITimedChannel* TimedChannel() |
|
181 { |
|
182 if (!GetOwner()) |
|
183 return nullptr; |
|
184 return GetOwner()->mTimedChannel; |
|
185 } |
|
186 |
|
187 already_AddRefed<mozilla::image::Image> GetImage() const; |
|
188 bool HasImage() const; |
|
189 imgRequest* GetOwner() const; |
|
190 |
|
191 nsresult PerformClone(imgINotificationObserver* aObserver, |
|
192 imgRequestProxy* (aAllocFn)(imgRequestProxy*), |
|
193 imgRequestProxy** aClone); |
|
194 |
|
195 public: |
|
196 NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel()) |
|
197 |
|
198 protected: |
|
199 nsAutoPtr<ProxyBehaviour> mBehaviour; |
|
200 |
|
201 private: |
|
202 friend class imgCacheValidator; |
|
203 friend imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis); |
|
204 |
|
205 // The URI of our request. |
|
206 nsRefPtr<ImageURL> mURI; |
|
207 |
|
208 // mListener is only promised to be a weak ref (see imgILoader.idl), |
|
209 // but we actually keep a strong ref to it until we've seen our |
|
210 // first OnStopRequest. |
|
211 imgINotificationObserver* mListener; |
|
212 nsCOMPtr<nsILoadGroup> mLoadGroup; |
|
213 |
|
214 nsLoadFlags mLoadFlags; |
|
215 uint32_t mLockCount; |
|
216 uint32_t mAnimationConsumers; |
|
217 bool mCanceled; |
|
218 bool mIsInLoadGroup; |
|
219 bool mListenerIsStrongRef; |
|
220 bool mDecodeRequested; |
|
221 |
|
222 // Whether we want to defer our notifications by the non-virtual Observer |
|
223 // interfaces as image loads proceed. |
|
224 bool mDeferNotifications; |
|
225 |
|
226 // We only want to send OnStartContainer once for each proxy, but we might |
|
227 // get multiple OnStartContainer calls. |
|
228 bool mSentStartContainer; |
|
229 }; |
|
230 |
|
231 // Used for static image proxies for which no requests are available, so |
|
232 // certain behaviours must be overridden to compensate. |
|
233 class imgRequestProxyStatic : public imgRequestProxy |
|
234 { |
|
235 |
|
236 public: |
|
237 imgRequestProxyStatic(mozilla::image::Image* aImage, |
|
238 nsIPrincipal* aPrincipal); |
|
239 |
|
240 NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) MOZ_OVERRIDE; |
|
241 |
|
242 using imgRequestProxy::Clone; |
|
243 |
|
244 virtual nsresult Clone(imgINotificationObserver* aObserver, |
|
245 imgRequestProxy** aClone) MOZ_OVERRIDE; |
|
246 |
|
247 protected: |
|
248 friend imgRequestProxy* NewStaticProxy(imgRequestProxy*); |
|
249 |
|
250 // Our principal. We have to cache it, rather than accessing the underlying |
|
251 // request on-demand, because static proxies don't have an underlying request. |
|
252 nsCOMPtr<nsIPrincipal> mPrincipal; |
|
253 }; |
|
254 |
|
255 #endif // imgRequestProxy_h__ |