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