1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/imgRequestProxy.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,255 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef imgRequestProxy_h__ 1.11 +#define imgRequestProxy_h__ 1.12 + 1.13 +#include "mozilla/WeakPtr.h" 1.14 +#include "imgIRequest.h" 1.15 +#include "nsISecurityInfoProvider.h" 1.16 + 1.17 +#include "nsILoadGroup.h" 1.18 +#include "nsISupportsPriority.h" 1.19 +#include "nsITimedChannel.h" 1.20 +#include "nsCOMPtr.h" 1.21 +#include "nsAutoPtr.h" 1.22 +#include "nsThreadUtils.h" 1.23 +#include "mozilla/TimeStamp.h" 1.24 + 1.25 +#include "imgRequest.h" 1.26 + 1.27 +#define NS_IMGREQUESTPROXY_CID \ 1.28 +{ /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \ 1.29 + 0x20557898, \ 1.30 + 0x1dd2, \ 1.31 + 0x11b2, \ 1.32 + {0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \ 1.33 +} 1.34 + 1.35 +class imgINotificationObserver; 1.36 +class imgRequestNotifyRunnable; 1.37 +class imgStatusNotifyRunnable; 1.38 +class nsIntRect; 1.39 +class ProxyBehaviour; 1.40 + 1.41 +namespace mozilla { 1.42 +namespace image { 1.43 +class Image; 1.44 +class ImageURL; 1.45 +} // namespace image 1.46 +} // namespace mozilla 1.47 + 1.48 +class imgRequestProxy : public imgIRequest, 1.49 + public nsISupportsPriority, 1.50 + public nsISecurityInfoProvider, 1.51 + public nsITimedChannel, 1.52 + public mozilla::SupportsWeakPtr<imgRequestProxy> 1.53 +{ 1.54 +public: 1.55 + MOZ_DECLARE_REFCOUNTED_TYPENAME(imgRequestProxy) 1.56 + typedef mozilla::image::ImageURL ImageURL; 1.57 + NS_DECL_ISUPPORTS 1.58 + NS_DECL_IMGIREQUEST 1.59 + NS_DECL_NSIREQUEST 1.60 + NS_DECL_NSISUPPORTSPRIORITY 1.61 + NS_DECL_NSISECURITYINFOPROVIDER 1.62 + // nsITimedChannel declared below 1.63 + 1.64 + imgRequestProxy(); 1.65 + virtual ~imgRequestProxy(); 1.66 + 1.67 + // Callers to Init or ChangeOwner are required to call NotifyListener after 1.68 + // (although not immediately after) doing so. 1.69 + nsresult Init(imgRequest* aOwner, 1.70 + nsILoadGroup *aLoadGroup, 1.71 + ImageURL* aURI, 1.72 + imgINotificationObserver *aObserver); 1.73 + 1.74 + nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous 1.75 + // owner has already sent notifications out! 1.76 + 1.77 + void AddToLoadGroup(); 1.78 + void RemoveFromLoadGroup(bool releaseLoadGroup); 1.79 + 1.80 + inline bool HasObserver() const { 1.81 + return mListener != nullptr; 1.82 + } 1.83 + 1.84 + // Asynchronously notify this proxy's listener of the current state of the 1.85 + // image, and, if we have an imgRequest mOwner, any status changes that 1.86 + // happen between the time this function is called and the time the 1.87 + // notification is scheduled. 1.88 + void NotifyListener(); 1.89 + 1.90 + // Synchronously notify this proxy's listener of the current state of the 1.91 + // image. Only use this function if you are currently servicing an 1.92 + // asynchronously-called function. 1.93 + void SyncNotifyListener(); 1.94 + 1.95 + // Whether we want notifications from imgStatusTracker to be deferred until 1.96 + // an event it has scheduled has been fired. 1.97 + bool NotificationsDeferred() const 1.98 + { 1.99 + return mDeferNotifications; 1.100 + } 1.101 + void SetNotificationsDeferred(bool aDeferNotifications) 1.102 + { 1.103 + mDeferNotifications = aDeferNotifications; 1.104 + } 1.105 + 1.106 + // XXXbholley - This eventually gets folded into the new notification API. 1.107 + void SetHasImage(); 1.108 + 1.109 + // Removes all animation consumers that were created with 1.110 + // IncrementAnimationConsumers. This is necessary since we need 1.111 + // to do it before the proxy itself is destroyed. See 1.112 + // imgRequest::RemoveProxy 1.113 + void ClearAnimationConsumers(); 1.114 + 1.115 + virtual nsresult Clone(imgINotificationObserver* aObserver, imgRequestProxy** aClone); 1.116 + nsresult GetStaticRequest(imgRequestProxy** aReturn); 1.117 + 1.118 + nsresult GetURI(ImageURL **aURI); 1.119 + 1.120 +protected: 1.121 + friend class imgStatusTracker; 1.122 + friend class imgStatusNotifyRunnable; 1.123 + friend class imgRequestNotifyRunnable; 1.124 + 1.125 + class imgCancelRunnable; 1.126 + friend class imgCancelRunnable; 1.127 + 1.128 + class imgCancelRunnable : public nsRunnable 1.129 + { 1.130 + public: 1.131 + imgCancelRunnable(imgRequestProxy* owner, nsresult status) 1.132 + : mOwner(owner), mStatus(status) 1.133 + {} 1.134 + 1.135 + NS_IMETHOD Run() { 1.136 + mOwner->DoCancel(mStatus); 1.137 + return NS_OK; 1.138 + } 1.139 + 1.140 + private: 1.141 + nsRefPtr<imgRequestProxy> mOwner; 1.142 + nsresult mStatus; 1.143 + }; 1.144 + 1.145 + // The following notification functions are protected to ensure that (friend 1.146 + // class) imgStatusTracker is the only class allowed to send us 1.147 + // notifications. 1.148 + 1.149 + /* non-virtual imgDecoderObserver methods */ 1.150 + void OnStartDecode (); 1.151 + void OnStartContainer (); 1.152 + void OnFrameUpdate (const nsIntRect * aRect); 1.153 + void OnStopFrame (); 1.154 + void OnStopDecode (); 1.155 + void OnDiscard (); 1.156 + void OnUnlockedDraw (); 1.157 + void OnImageIsAnimated (); 1.158 + 1.159 + /* non-virtual sort-of-nsIRequestObserver methods */ 1.160 + void OnStartRequest(); 1.161 + void OnStopRequest(bool aLastPart); 1.162 + 1.163 + /* non-virtual imgIOnloadBlocker methods */ 1.164 + void BlockOnload(); 1.165 + void UnblockOnload(); 1.166 + 1.167 + /* Finish up canceling ourselves */ 1.168 + void DoCancel(nsresult status); 1.169 + 1.170 + /* Do the proper refcount management to null out mListener */ 1.171 + void NullOutListener(); 1.172 + 1.173 + void DoRemoveFromLoadGroup() { 1.174 + RemoveFromLoadGroup(true); 1.175 + } 1.176 + 1.177 + // Return the imgStatusTracker associated with mOwner and/or mImage. It may 1.178 + // live either on mOwner or mImage, depending on whether 1.179 + // (a) we have an mOwner at all 1.180 + // (b) whether mOwner has instantiated its image yet 1.181 + already_AddRefed<imgStatusTracker> GetStatusTracker() const; 1.182 + 1.183 + nsITimedChannel* TimedChannel() 1.184 + { 1.185 + if (!GetOwner()) 1.186 + return nullptr; 1.187 + return GetOwner()->mTimedChannel; 1.188 + } 1.189 + 1.190 + already_AddRefed<mozilla::image::Image> GetImage() const; 1.191 + bool HasImage() const; 1.192 + imgRequest* GetOwner() const; 1.193 + 1.194 + nsresult PerformClone(imgINotificationObserver* aObserver, 1.195 + imgRequestProxy* (aAllocFn)(imgRequestProxy*), 1.196 + imgRequestProxy** aClone); 1.197 + 1.198 +public: 1.199 + NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel()) 1.200 + 1.201 +protected: 1.202 + nsAutoPtr<ProxyBehaviour> mBehaviour; 1.203 + 1.204 +private: 1.205 + friend class imgCacheValidator; 1.206 + friend imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis); 1.207 + 1.208 + // The URI of our request. 1.209 + nsRefPtr<ImageURL> mURI; 1.210 + 1.211 + // mListener is only promised to be a weak ref (see imgILoader.idl), 1.212 + // but we actually keep a strong ref to it until we've seen our 1.213 + // first OnStopRequest. 1.214 + imgINotificationObserver* mListener; 1.215 + nsCOMPtr<nsILoadGroup> mLoadGroup; 1.216 + 1.217 + nsLoadFlags mLoadFlags; 1.218 + uint32_t mLockCount; 1.219 + uint32_t mAnimationConsumers; 1.220 + bool mCanceled; 1.221 + bool mIsInLoadGroup; 1.222 + bool mListenerIsStrongRef; 1.223 + bool mDecodeRequested; 1.224 + 1.225 + // Whether we want to defer our notifications by the non-virtual Observer 1.226 + // interfaces as image loads proceed. 1.227 + bool mDeferNotifications; 1.228 + 1.229 + // We only want to send OnStartContainer once for each proxy, but we might 1.230 + // get multiple OnStartContainer calls. 1.231 + bool mSentStartContainer; 1.232 +}; 1.233 + 1.234 +// Used for static image proxies for which no requests are available, so 1.235 +// certain behaviours must be overridden to compensate. 1.236 +class imgRequestProxyStatic : public imgRequestProxy 1.237 +{ 1.238 + 1.239 +public: 1.240 + imgRequestProxyStatic(mozilla::image::Image* aImage, 1.241 + nsIPrincipal* aPrincipal); 1.242 + 1.243 + NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) MOZ_OVERRIDE; 1.244 + 1.245 + using imgRequestProxy::Clone; 1.246 + 1.247 + virtual nsresult Clone(imgINotificationObserver* aObserver, 1.248 + imgRequestProxy** aClone) MOZ_OVERRIDE; 1.249 + 1.250 +protected: 1.251 + friend imgRequestProxy* NewStaticProxy(imgRequestProxy*); 1.252 + 1.253 + // Our principal. We have to cache it, rather than accessing the underlying 1.254 + // request on-demand, because static proxies don't have an underlying request. 1.255 + nsCOMPtr<nsIPrincipal> mPrincipal; 1.256 +}; 1.257 + 1.258 +#endif // imgRequestProxy_h__