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_imgRequest_h
8 : #define mozilla_image_imgRequest_h
9 :
10 : #include "nsIChannelEventSink.h"
11 : #include "nsIInterfaceRequestor.h"
12 : #include "nsIStreamListener.h"
13 : #include "nsIThreadRetargetableStreamListener.h"
14 : #include "nsIPrincipal.h"
15 :
16 : #include "nsCOMPtr.h"
17 : #include "nsProxyRelease.h"
18 : #include "nsStringGlue.h"
19 : #include "nsError.h"
20 : #include "nsIAsyncVerifyRedirectCallback.h"
21 : #include "mozilla/Mutex.h"
22 : #include "mozilla/net/ReferrerPolicy.h"
23 : #include "ImageCacheKey.h"
24 :
25 : class imgCacheValidator;
26 : class imgLoader;
27 : class imgRequestProxy;
28 : class imgCacheEntry;
29 : class nsIApplicationCache;
30 : class nsIProperties;
31 : class nsIRequest;
32 : class nsITimedChannel;
33 : class nsIURI;
34 :
35 : namespace mozilla {
36 : namespace image {
37 : class Image;
38 : class ImageURL;
39 : class ProgressTracker;
40 : } // namespace image
41 : } // namespace mozilla
42 :
43 : struct NewPartResult;
44 :
45 : class imgRequest final : public nsIStreamListener,
46 : public nsIThreadRetargetableStreamListener,
47 : public nsIChannelEventSink,
48 : public nsIInterfaceRequestor,
49 : public nsIAsyncVerifyRedirectCallback
50 : {
51 : typedef mozilla::image::Image Image;
52 : typedef mozilla::image::ImageCacheKey ImageCacheKey;
53 : typedef mozilla::image::ImageURL ImageURL;
54 : typedef mozilla::image::ProgressTracker ProgressTracker;
55 : typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
56 :
57 : public:
58 : imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey);
59 :
60 : NS_DECL_THREADSAFE_ISUPPORTS
61 : NS_DECL_NSISTREAMLISTENER
62 : NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
63 : NS_DECL_NSIREQUESTOBSERVER
64 : NS_DECL_NSICHANNELEVENTSINK
65 : NS_DECL_NSIINTERFACEREQUESTOR
66 : NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
67 :
68 : MOZ_MUST_USE nsresult Init(nsIURI* aURI,
69 : nsIURI* aCurrentURI,
70 : bool aHadInsecureRedirect,
71 : nsIRequest* aRequest,
72 : nsIChannel* aChannel,
73 : imgCacheEntry* aCacheEntry,
74 : nsISupports* aCX,
75 : nsIPrincipal* aLoadingPrincipal,
76 : int32_t aCORSMode,
77 : ReferrerPolicy aReferrerPolicy);
78 :
79 : void ClearLoader();
80 :
81 : // Callers must call imgRequestProxy::Notify later.
82 : void AddProxy(imgRequestProxy* proxy);
83 :
84 : nsresult RemoveProxy(imgRequestProxy* proxy, nsresult aStatus);
85 :
86 : // Cancel, but also ensure that all work done in Init() is undone. Call this
87 : // only when the channel has failed to open, and so calling Cancel() on it
88 : // won't be sufficient.
89 : void CancelAndAbort(nsresult aStatus);
90 :
91 : // Called or dispatched by cancel for main thread only execution.
92 : void ContinueCancel(nsresult aStatus);
93 :
94 : // Called or dispatched by EvictFromCache for main thread only execution.
95 : void ContinueEvict();
96 :
97 : // Request that we start decoding the image as soon as data becomes available.
98 : void StartDecoding();
99 :
100 : inline uint64_t InnerWindowID() const {
101 : return mInnerWindowId;
102 : }
103 :
104 : // Set the cache validation information (expiry time, whether we must
105 : // validate, etc) on the cache entry based on the request information.
106 : // If this function is called multiple times, the information set earliest
107 : // wins.
108 : static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest);
109 :
110 : // Check if application cache of the original load is different from
111 : // application cache of the new load. Also lack of application cache
112 : // on one of the loads is considered a change of a loading cache since
113 : // HTTP cache may contain a different data then app cache.
114 : bool CacheChanged(nsIRequest* aNewRequest);
115 :
116 : bool GetMultipart() const;
117 :
118 : // Returns whether we went through an insecure (non-HTTPS) redirect at some
119 : // point during loading. This does not consider the current URI.
120 : bool HadInsecureRedirect() const;
121 :
122 : // The CORS mode for which we loaded this image.
123 8 : int32_t GetCORSMode() const { return mCORSMode; }
124 :
125 : // The Referrer Policy in effect when loading this image.
126 4 : ReferrerPolicy GetReferrerPolicy() const { return mReferrerPolicy; }
127 :
128 : // The principal for the document that loaded this image. Used when trying to
129 : // validate a CORS image load.
130 0 : already_AddRefed<nsIPrincipal> GetLoadingPrincipal() const
131 : {
132 0 : nsCOMPtr<nsIPrincipal> principal = mLoadingPrincipal;
133 0 : return principal.forget();
134 : }
135 :
136 : // Return the ProgressTracker associated with this imgRequest. It may live
137 : // in |mProgressTracker| or in |mImage.mProgressTracker|, depending on whether
138 : // mImage has been instantiated yet.
139 : already_AddRefed<ProgressTracker> GetProgressTracker() const;
140 :
141 : /// Returns the Image associated with this imgRequest, if it's ready.
142 : already_AddRefed<Image> GetImage() const;
143 :
144 : // Get the current principal of the image. No AddRefing.
145 0 : inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
146 :
147 : /// Get the ImageCacheKey associated with this request.
148 42 : const ImageCacheKey& CacheKey() const { return mCacheKey; }
149 :
150 : // Resize the cache entry to 0 if it exists
151 : void ResetCacheEntry();
152 :
153 : // OK to use on any thread.
154 : nsresult GetURI(ImageURL** aURI);
155 : nsresult GetCurrentURI(nsIURI** aURI);
156 : bool IsChrome() const;
157 :
158 : nsresult GetImageErrorCode(void);
159 :
160 : /// Returns true if we've received any data.
161 : bool HasTransferredData() const;
162 :
163 : /// Returns a non-owning pointer to this imgRequest's MIME type.
164 0 : const char* GetMimeType() const { return mContentType.get(); }
165 :
166 : /// @return the priority of the underlying network request, or
167 : /// PRIORITY_NORMAL if it doesn't support nsISupportsPriority.
168 : int32_t Priority() const;
169 :
170 : /// Adjust the priority of the underlying network request by @aDelta on behalf
171 : /// of @aProxy.
172 : void AdjustPriority(imgRequestProxy* aProxy, int32_t aDelta);
173 :
174 : void BoostPriority(uint32_t aCategory);
175 :
176 : /// Returns a weak pointer to the underlying request.
177 4 : nsIRequest* GetRequest() const { return mRequest; }
178 :
179 51 : nsITimedChannel* GetTimedChannel() const { return mTimedChannel; }
180 :
181 : nsresult GetSecurityInfo(nsISupports** aSecurityInfoOut);
182 :
183 92 : imgCacheValidator* GetValidator() const { return mValidator; }
184 0 : void SetValidator(imgCacheValidator* aValidator) { mValidator = aValidator; }
185 :
186 4 : void* LoadId() const { return mLoadId; }
187 86 : void SetLoadId(void* aLoadId) { mLoadId = aLoadId; }
188 :
189 : /// Reset the cache entry after we've dropped our reference to it. Used by
190 : /// imgLoader when our cache entry is re-requested after we've dropped our
191 : /// reference to it.
192 : void SetCacheEntry(imgCacheEntry* aEntry);
193 :
194 : /// Returns whether we've got a reference to the cache entry.
195 : bool HasCacheEntry() const;
196 :
197 : /// Set whether this request is stored in the cache. If it isn't, regardless
198 : /// of whether this request has a non-null mCacheEntry, this imgRequest won't
199 : /// try to update or modify the image cache.
200 : void SetIsInCache(bool aCacheable);
201 :
202 : void EvictFromCache();
203 : void RemoveFromCache();
204 :
205 : // Sets properties for this image; will dispatch to main thread if needed.
206 : void SetProperties(const nsACString& aContentType,
207 : const nsACString& aContentDisposition);
208 :
209 0 : nsIProperties* Properties() const { return mProperties; }
210 :
211 : bool HasConsumers() const;
212 :
213 : private:
214 : friend class FinishPreparingForNewPartRunnable;
215 :
216 : virtual ~imgRequest();
217 :
218 : void FinishPreparingForNewPart(const NewPartResult& aResult);
219 :
220 : void Cancel(nsresult aStatus);
221 :
222 : // Update the cache entry size based on the image container.
223 : void UpdateCacheEntrySize();
224 :
225 : /// Returns true if StartDecoding() was called.
226 : bool IsDecodeRequested() const;
227 :
228 : void AdjustPriorityInternal(int32_t aDelta);
229 :
230 : // Weak reference to parent loader; this request cannot outlive its owner.
231 : imgLoader* mLoader;
232 : nsCOMPtr<nsIRequest> mRequest;
233 : // The original URI we were loaded with. This is the same as the URI we are
234 : // keyed on in the cache. We store a string here to avoid off main thread
235 : // refcounting issues with nsStandardURL.
236 : RefPtr<ImageURL> mURI;
237 : // The URI of the resource we ended up loading after all redirects, etc.
238 : nsCOMPtr<nsIURI> mCurrentURI;
239 : // The principal of the document which loaded this image. Used when
240 : // validating for CORS.
241 : nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
242 : // The principal of this image.
243 : nsCOMPtr<nsIPrincipal> mPrincipal;
244 : nsCOMPtr<nsIProperties> mProperties;
245 : nsCOMPtr<nsISupports> mSecurityInfo;
246 : nsCOMPtr<nsIChannel> mChannel;
247 : nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
248 : nsCOMPtr<nsIApplicationCache> mApplicationCache;
249 :
250 : nsCOMPtr<nsITimedChannel> mTimedChannel;
251 :
252 : nsCString mContentType;
253 :
254 : /* we hold on to this to this so long as we have observers */
255 : RefPtr<imgCacheEntry> mCacheEntry;
256 :
257 : /// The key under which this imgRequest is stored in the image cache.
258 : ImageCacheKey mCacheKey;
259 :
260 : void* mLoadId;
261 :
262 : /// Raw pointer to the first proxy that was added to this imgRequest. Use only
263 : /// pointer comparisons; there's no guarantee this will remain valid.
264 : void* mFirstProxy;
265 :
266 : imgCacheValidator* mValidator;
267 : nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
268 : nsCOMPtr<nsIChannel> mNewRedirectChannel;
269 :
270 : // The ID of the inner window origin, used for error reporting.
271 : uint64_t mInnerWindowId;
272 :
273 : // The CORS mode (defined in imgIRequest) this image was loaded with. By
274 : // default, imgIRequest::CORS_NONE.
275 : int32_t mCORSMode;
276 :
277 : // The Referrer Policy (defined in ReferrerPolicy.h) used for this image.
278 : ReferrerPolicy mReferrerPolicy;
279 :
280 : nsresult mImageErrorCode;
281 :
282 : // The categories of prioritization strategy that have been requested.
283 : uint32_t mBoostCategoriesRequested = 0;
284 :
285 : mutable mozilla::Mutex mMutex;
286 :
287 : // Member variables protected by mMutex. Note that *all* flags in our bitfield
288 : // are protected by mMutex; if you're adding a new flag that isn'protected, it
289 : // must not be a part of this bitfield.
290 : RefPtr<ProgressTracker> mProgressTracker;
291 : RefPtr<Image> mImage;
292 : bool mIsMultiPartChannel : 1;
293 : bool mGotData : 1;
294 : bool mIsInCache : 1;
295 : bool mDecodeRequested : 1;
296 : bool mNewPartPending : 1;
297 : bool mHadInsecureRedirect : 1;
298 : };
299 :
300 : #endif // mozilla_image_imgRequest_h
|