Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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/. */
7 #ifndef imgRequestProxy_h__
8 #define imgRequestProxy_h__
10 #include "mozilla/WeakPtr.h"
11 #include "imgIRequest.h"
12 #include "nsISecurityInfoProvider.h"
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"
22 #include "imgRequest.h"
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 }
32 class imgINotificationObserver;
33 class imgRequestNotifyRunnable;
34 class imgStatusNotifyRunnable;
35 class nsIntRect;
36 class ProxyBehaviour;
38 namespace mozilla {
39 namespace image {
40 class Image;
41 class ImageURL;
42 } // namespace image
43 } // namespace mozilla
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
61 imgRequestProxy();
62 virtual ~imgRequestProxy();
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);
71 nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous
72 // owner has already sent notifications out!
74 void AddToLoadGroup();
75 void RemoveFromLoadGroup(bool releaseLoadGroup);
77 inline bool HasObserver() const {
78 return mListener != nullptr;
79 }
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();
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();
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 }
103 // XXXbholley - This eventually gets folded into the new notification API.
104 void SetHasImage();
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();
112 virtual nsresult Clone(imgINotificationObserver* aObserver, imgRequestProxy** aClone);
113 nsresult GetStaticRequest(imgRequestProxy** aReturn);
115 nsresult GetURI(ImageURL **aURI);
117 protected:
118 friend class imgStatusTracker;
119 friend class imgStatusNotifyRunnable;
120 friend class imgRequestNotifyRunnable;
122 class imgCancelRunnable;
123 friend class imgCancelRunnable;
125 class imgCancelRunnable : public nsRunnable
126 {
127 public:
128 imgCancelRunnable(imgRequestProxy* owner, nsresult status)
129 : mOwner(owner), mStatus(status)
130 {}
132 NS_IMETHOD Run() {
133 mOwner->DoCancel(mStatus);
134 return NS_OK;
135 }
137 private:
138 nsRefPtr<imgRequestProxy> mOwner;
139 nsresult mStatus;
140 };
142 // The following notification functions are protected to ensure that (friend
143 // class) imgStatusTracker is the only class allowed to send us
144 // notifications.
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 ();
156 /* non-virtual sort-of-nsIRequestObserver methods */
157 void OnStartRequest();
158 void OnStopRequest(bool aLastPart);
160 /* non-virtual imgIOnloadBlocker methods */
161 void BlockOnload();
162 void UnblockOnload();
164 /* Finish up canceling ourselves */
165 void DoCancel(nsresult status);
167 /* Do the proper refcount management to null out mListener */
168 void NullOutListener();
170 void DoRemoveFromLoadGroup() {
171 RemoveFromLoadGroup(true);
172 }
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;
180 nsITimedChannel* TimedChannel()
181 {
182 if (!GetOwner())
183 return nullptr;
184 return GetOwner()->mTimedChannel;
185 }
187 already_AddRefed<mozilla::image::Image> GetImage() const;
188 bool HasImage() const;
189 imgRequest* GetOwner() const;
191 nsresult PerformClone(imgINotificationObserver* aObserver,
192 imgRequestProxy* (aAllocFn)(imgRequestProxy*),
193 imgRequestProxy** aClone);
195 public:
196 NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
198 protected:
199 nsAutoPtr<ProxyBehaviour> mBehaviour;
201 private:
202 friend class imgCacheValidator;
203 friend imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis);
205 // The URI of our request.
206 nsRefPtr<ImageURL> mURI;
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;
214 nsLoadFlags mLoadFlags;
215 uint32_t mLockCount;
216 uint32_t mAnimationConsumers;
217 bool mCanceled;
218 bool mIsInLoadGroup;
219 bool mListenerIsStrongRef;
220 bool mDecodeRequested;
222 // Whether we want to defer our notifications by the non-virtual Observer
223 // interfaces as image loads proceed.
224 bool mDeferNotifications;
226 // We only want to send OnStartContainer once for each proxy, but we might
227 // get multiple OnStartContainer calls.
228 bool mSentStartContainer;
229 };
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 {
236 public:
237 imgRequestProxyStatic(mozilla::image::Image* aImage,
238 nsIPrincipal* aPrincipal);
240 NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) MOZ_OVERRIDE;
242 using imgRequestProxy::Clone;
244 virtual nsresult Clone(imgINotificationObserver* aObserver,
245 imgRequestProxy** aClone) MOZ_OVERRIDE;
247 protected:
248 friend imgRequestProxy* NewStaticProxy(imgRequestProxy*);
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 };
255 #endif // imgRequestProxy_h__