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 "nsString.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 ProgressTracker;
39 : } // namespace image
40 : } // namespace mozilla
41 :
42 : struct NewPartResult;
43 :
44 : class imgRequest final : public nsIStreamListener,
45 : public nsIThreadRetargetableStreamListener,
46 : public nsIChannelEventSink,
47 : public nsIInterfaceRequestor,
48 : public nsIAsyncVerifyRedirectCallback
49 : {
50 : typedef mozilla::image::Image Image;
51 : typedef mozilla::image::ImageCacheKey ImageCacheKey;
52 : typedef mozilla::image::ProgressTracker ProgressTracker;
53 : typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
54 :
55 : public:
56 : imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey);
57 :
58 : NS_DECL_THREADSAFE_ISUPPORTS
59 : NS_DECL_NSISTREAMLISTENER
60 : NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
61 : NS_DECL_NSIREQUESTOBSERVER
62 : NS_DECL_NSICHANNELEVENTSINK
63 : NS_DECL_NSIINTERFACEREQUESTOR
64 : NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
65 :
66 : MOZ_MUST_USE nsresult Init(nsIURI* aURI,
67 : nsIURI* aFinalURI,
68 : bool aHadInsecureRedirect,
69 : nsIRequest* aRequest,
70 : nsIChannel* aChannel,
71 : imgCacheEntry* aCacheEntry,
72 : nsISupports* aCX,
73 : nsIPrincipal* aTriggeringPrincipal,
74 : int32_t aCORSMode,
75 : ReferrerPolicy aReferrerPolicy);
76 :
77 : void ClearLoader();
78 :
79 : // Callers must call imgRequestProxy::Notify later.
80 : void AddProxy(imgRequestProxy* proxy);
81 :
82 : nsresult RemoveProxy(imgRequestProxy* proxy, nsresult aStatus);
83 :
84 : // Cancel, but also ensure that all work done in Init() is undone. Call this
85 : // only when the channel has failed to open, and so calling Cancel() on it
86 : // won't be sufficient.
87 : void CancelAndAbort(nsresult aStatus);
88 :
89 : // Called or dispatched by cancel for main thread only execution.
90 : void ContinueCancel(nsresult aStatus);
91 :
92 : // Called or dispatched by EvictFromCache for main thread only execution.
93 : void ContinueEvict();
94 :
95 : // Request that we start decoding the image as soon as data becomes available.
96 : void StartDecoding();
97 :
98 : inline uint64_t InnerWindowID() const {
99 : return mInnerWindowId;
100 : }
101 :
102 : // Set the cache validation information (expiry time, whether we must
103 : // validate, etc) on the cache entry based on the request information.
104 : // If this function is called multiple times, the information set earliest
105 : // wins.
106 : static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest);
107 :
108 : // Check if application cache of the original load is different from
109 : // application cache of the new load. Also lack of application cache
110 : // on one of the loads is considered a change of a loading cache since
111 : // HTTP cache may contain a different data then app cache.
112 : bool CacheChanged(nsIRequest* aNewRequest);
113 :
114 : bool GetMultipart() const;
115 :
116 : // Returns whether we went through an insecure (non-HTTPS) redirect at some
117 : // point during loading. This does not consider the final URI.
118 : bool HadInsecureRedirect() const;
119 :
120 : // The CORS mode for which we loaded this image.
121 : int32_t GetCORSMode() const { return mCORSMode; }
122 :
123 : // The Referrer Policy in effect when loading this image.
124 : ReferrerPolicy GetReferrerPolicy() const { return mReferrerPolicy; }
125 :
126 : // The principal for the document that loaded this image. Used when trying to
127 : // validate a CORS image load.
128 : already_AddRefed<nsIPrincipal> GetTriggeringPrincipal() const
129 : {
130 : nsCOMPtr<nsIPrincipal> principal = mTriggeringPrincipal;
131 : return principal.forget();
132 : }
133 :
134 : // Return the ProgressTracker associated with this imgRequest. It may live
135 : // in |mProgressTracker| or in |mImage.mProgressTracker|, depending on whether
136 : // mImage has been instantiated yet.
137 : already_AddRefed<ProgressTracker> GetProgressTracker() const;
138 :
139 : /// Returns the Image associated with this imgRequest, if it's ready.
140 : already_AddRefed<Image> GetImage() const;
141 :
142 : // Get the current principal of the image. No AddRefing.
143 0 : inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
144 :
145 : /// Get the ImageCacheKey associated with this request.
146 : const ImageCacheKey& CacheKey() const { return mCacheKey; }
147 :
148 : // Resize the cache entry to 0 if it exists
149 : void ResetCacheEntry();
150 :
151 : // OK to use on any thread.
152 : nsresult GetURI(nsIURI** aURI);
153 : nsresult GetFinalURI(nsIURI** aURI);
154 : bool IsScheme(const char* aScheme) const;
155 : bool IsChrome() const;
156 : bool IsData() 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 : nsIRequest* GetRequest() const { return mRequest; }
178 :
179 2 : nsITimedChannel* GetTimedChannel() const { return mTimedChannel; }
180 :
181 : nsresult GetSecurityInfo(nsISupports** aSecurityInfoOut);
182 :
183 : imgCacheValidator* GetValidator() const { return mValidator; }
184 : void SetValidator(imgCacheValidator* aValidator) { mValidator = aValidator; }
185 :
186 : void* LoadId() const { return mLoadId; }
187 : 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 : 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 : nsCOMPtr<nsIURI> mURI;
237 : // The URI of the resource we ended up loading after all redirects, etc.
238 : nsCOMPtr<nsIURI> mFinalURI;
239 : // The principal which triggered the load of this image. Generally either
240 : // the principal of the document the image is being loaded into, or of the
241 : // stylesheet which specified the image to load. Used when validating for CORS.
242 : nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
243 : // The principal of this image.
244 : nsCOMPtr<nsIPrincipal> mPrincipal;
245 : nsCOMPtr<nsIProperties> mProperties;
246 : nsCOMPtr<nsISupports> mSecurityInfo;
247 : nsCOMPtr<nsIChannel> mChannel;
248 : nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
249 : nsCOMPtr<nsIApplicationCache> mApplicationCache;
250 :
251 : nsCOMPtr<nsITimedChannel> mTimedChannel;
252 :
253 : nsCString mContentType;
254 :
255 : /* we hold on to this to this so long as we have observers */
256 : RefPtr<imgCacheEntry> mCacheEntry;
257 :
258 : /// The key under which this imgRequest is stored in the image cache.
259 : ImageCacheKey mCacheKey;
260 :
261 : void* mLoadId;
262 :
263 : /// Raw pointer to the first proxy that was added to this imgRequest. Use only
264 : /// pointer comparisons; there's no guarantee this will remain valid.
265 : void* mFirstProxy;
266 :
267 : imgCacheValidator* mValidator;
268 : nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
269 : nsCOMPtr<nsIChannel> mNewRedirectChannel;
270 :
271 : // The ID of the inner window origin, used for error reporting.
272 : uint64_t mInnerWindowId;
273 :
274 : // The CORS mode (defined in imgIRequest) this image was loaded with. By
275 : // default, imgIRequest::CORS_NONE.
276 : int32_t mCORSMode;
277 :
278 : // The Referrer Policy (defined in ReferrerPolicy.h) used for this image.
279 : ReferrerPolicy mReferrerPolicy;
280 :
281 : nsresult mImageErrorCode;
282 :
283 : // The categories of prioritization strategy that have been requested.
284 : uint32_t mBoostCategoriesRequested = 0;
285 :
286 : mutable mozilla::Mutex mMutex;
287 :
288 : // Member variables protected by mMutex. Note that *all* flags in our bitfield
289 : // are protected by mMutex; if you're adding a new flag that isn'protected, it
290 : // must not be a part of this bitfield.
291 : RefPtr<ProgressTracker> mProgressTracker;
292 : RefPtr<Image> mImage;
293 : bool mIsMultiPartChannel : 1;
294 : bool mGotData : 1;
295 : bool mIsInCache : 1;
296 : bool mDecodeRequested : 1;
297 : bool mNewPartPending : 1;
298 : bool mHadInsecureRedirect : 1;
299 : };
300 :
301 : #endif // mozilla_image_imgRequest_h
|