tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

imgRequestProxy.h (9294B)


      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 
     12 #include "nsIPrincipal.h"
     13 #include "nsISupportsPriority.h"
     14 #include "nsITimedChannel.h"
     15 #include "nsCOMPtr.h"
     16 #include "nsThreadUtils.h"
     17 #include "mozilla/PreloaderBase.h"
     18 #include "mozilla/TimeStamp.h"
     19 #include "mozilla/UniquePtr.h"
     20 #include "mozilla/gfx/Rect.h"
     21 
     22 #include "IProgressObserver.h"
     23 
     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 
     31 class imgCacheValidator;
     32 class imgINotificationObserver;
     33 class imgRequest;
     34 class imgStatusNotifyRunnable;
     35 class ProxyBehaviour;
     36 
     37 namespace mozilla {
     38 namespace image {
     39 class Image;
     40 class ProgressTracker;
     41 }  // namespace image
     42 }  // namespace mozilla
     43 
     44 class imgRequestProxy : public mozilla::PreloaderBase,
     45                        public imgIRequest,
     46                        public mozilla::image::IProgressObserver,
     47                        public nsISupportsPriority,
     48                        public nsITimedChannel {
     49 protected:
     50  virtual ~imgRequestProxy();
     51 
     52 public:
     53  typedef mozilla::dom::Document Document;
     54  typedef mozilla::image::Image Image;
     55  typedef mozilla::image::ProgressTracker ProgressTracker;
     56 
     57  NS_INLINE_DECL_STATIC_IID(NS_IMGREQUESTPROXY_CID)
     58  MOZ_DECLARE_REFCOUNTED_TYPENAME(imgRequestProxy)
     59  NS_DECL_ISUPPORTS
     60  NS_DECL_IMGIREQUEST
     61  NS_DECL_NSIREQUEST
     62  NS_DECL_NSISUPPORTSPRIORITY
     63  // nsITimedChannel declared below
     64 
     65  imgRequestProxy();
     66 
     67  // Callers to Init or ChangeOwner are required to call NotifyListener after
     68  // (although not immediately after) doing so.
     69  nsresult Init(imgRequest* aOwner, nsILoadGroup* aLoadGroup, nsIURI* aURI,
     70                imgINotificationObserver* aObserver);
     71 
     72  nsresult ChangeOwner(imgRequest* aNewOwner);  // this will change mOwner.
     73                                                // Do not call this if the
     74                                                // previous owner has already
     75                                                // sent notifications out!
     76 
     77  // Add the request to the load group, if any. This should only be called once
     78  // during initialization.
     79  void AddToLoadGroup();
     80 
     81  inline bool HasObserver() const { return mListener != nullptr; }
     82 
     83  // Asynchronously notify this proxy's listener of the current state of the
     84  // image, and, if we have an imgRequest mOwner, any status changes that
     85  // happen between the time this function is called and the time the
     86  // notification is scheduled.
     87  void NotifyListener();
     88 
     89  // Synchronously notify this proxy's listener of the current state of the
     90  // image. Only use this function if you are currently servicing an
     91  // asynchronously-called function.
     92  void SyncNotifyListener();
     93 
     94  // imgINotificationObserver methods:
     95  virtual void Notify(int32_t aType,
     96                      const mozilla::gfx::IntRect* aRect = nullptr) override;
     97  virtual void OnLoadComplete(bool aLastPart) override;
     98 
     99  // Other, internal-only methods:
    100  virtual void SetHasImage() override;
    101 
    102  // Whether we want notifications from ProgressTracker to be deferred until
    103  // an event it has scheduled has been fired and/or validation is complete.
    104  virtual bool NotificationsDeferred() const override {
    105    return IsValidating() || mPendingNotify;
    106  }
    107  virtual void MarkPendingNotify() override { mPendingNotify = true; }
    108  virtual void ClearPendingNotify() override { mPendingNotify = false; }
    109  bool IsValidating() const { return mValidating; }
    110  void MarkValidating();
    111  void ClearValidating();
    112 
    113  // Flags this image load as not cancelable temporarily. This is needed so that
    114  // stylesheets can be shared across documents properly, see bug 1800979.
    115  void SetCancelable(bool);
    116 
    117  // Removes all animation consumers that were created with
    118  // IncrementAnimationConsumers. This is necessary since we need
    119  // to do it before the proxy itself is destroyed. See
    120  // imgRequest::RemoveProxy
    121  void ClearAnimationConsumers();
    122 
    123  nsresult SyncClone(imgINotificationObserver* aObserver,
    124                     Document* aLoadingDocument, imgRequestProxy** aClone);
    125  nsresult Clone(imgINotificationObserver* aObserver,
    126                 Document* aLoadingDocument, imgRequestProxy** aClone);
    127  already_AddRefed<imgRequestProxy> GetStaticRequest(
    128      Document* aLoadingDocument);
    129 
    130  imgRequest* GetOwner() const;
    131 
    132  struct LCPTimings {
    133    bool AreSet() const { return mLoadTime.isSome() && mRenderTime.isSome(); }
    134 
    135    void Reset() {
    136      mLoadTime = mozilla::Nothing();
    137      mRenderTime = mozilla::Nothing();
    138    }
    139 
    140    mozilla::Maybe<mozilla::TimeStamp> mLoadTime;
    141    mozilla::Maybe<mozilla::TimeStamp> mRenderTime;
    142 
    143    void Set(const mozilla::TimeStamp& aLoadTime,
    144             const mozilla::TimeStamp& aRenderTime) {
    145      mLoadTime = Some(aLoadTime);
    146      mRenderTime = Some(aRenderTime);
    147    }
    148  };
    149 
    150  LCPTimings& GetLCPTimings() { return mLCPTimings; }
    151 
    152  const LCPTimings& GetLCPTimings() const { return mLCPTimings; }
    153 
    154 protected:
    155  friend class mozilla::image::ProgressTracker;
    156  friend class imgStatusNotifyRunnable;
    157 
    158  class imgCancelRunnable;
    159  friend class imgCancelRunnable;
    160 
    161  class imgCancelRunnable : public mozilla::Runnable {
    162   public:
    163    imgCancelRunnable(imgRequestProxy* owner, nsresult status)
    164        : Runnable("imgCancelRunnable"), mOwner(owner), mStatus(status) {}
    165 
    166    NS_IMETHOD Run() override {
    167      mOwner->DoCancel(mStatus);
    168      return NS_OK;
    169    }
    170 
    171   private:
    172    RefPtr<imgRequestProxy> mOwner;
    173    nsresult mStatus;
    174  };
    175 
    176  /* Remove from and forget the load group. */
    177  void RemoveFromLoadGroup();
    178 
    179  /* Remove from the load group and re-add as a background request. */
    180  void MoveToBackgroundInLoadGroup();
    181 
    182  /* Finish up canceling ourselves */
    183  void DoCancel(nsresult status);
    184 
    185  /* Do the proper refcount management to null out mListener */
    186  void NullOutListener();
    187 
    188  // Return the ProgressTracker associated with mOwner and/or mImage. It may
    189  // live either on mOwner or mImage, depending on whether
    190  //   (a) we have an mOwner at all
    191  //   (b) whether mOwner has instantiated its image yet
    192  already_AddRefed<ProgressTracker> GetProgressTracker() const;
    193 
    194  nsITimedChannel* TimedChannel();
    195 
    196  already_AddRefed<Image> GetImage() const;
    197  bool HasImage() const;
    198  imgCacheValidator* GetValidator() const;
    199 
    200  nsresult PerformClone(imgINotificationObserver* aObserver,
    201                        Document* aLoadingDocument, bool aSyncNotify,
    202                        imgRequestProxy** aClone);
    203 
    204  virtual imgRequestProxy* NewClonedProxy();
    205 
    206 public:
    207  NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
    208 
    209 protected:
    210  mozilla::UniquePtr<ProxyBehaviour> mBehaviour;
    211 
    212 private:
    213  friend class imgCacheValidator;
    214 
    215  void AddToOwner();
    216  void RemoveFromOwner(nsresult aStatus);
    217 
    218  nsresult DispatchWithTargetIfAvailable(already_AddRefed<nsIRunnable> aEvent);
    219 
    220  // The URI of our request.
    221  nsCOMPtr<nsIURI> mURI;
    222 
    223  LCPTimings mLCPTimings;
    224  // mListener is only promised to be a weak ref (see imgILoader.idl),
    225  // but we actually keep a strong ref to it until we've seen our
    226  // first OnStopRequest.
    227  imgINotificationObserver* MOZ_UNSAFE_REF(
    228      "Observers must call Cancel() or "
    229      "CancelAndForgetObserver() before "
    230      "they are destroyed") mListener;
    231 
    232  nsCOMPtr<nsILoadGroup> mLoadGroup;
    233 
    234  nsLoadFlags mLoadFlags;
    235  uint32_t mLockCount;
    236  uint32_t mAnimationConsumers;
    237  bool mCancelable : 1;
    238  bool mCanceled : 1;
    239  bool mIsInLoadGroup : 1;
    240  bool mForceDispatchLoadGroup : 1;
    241  bool mListenerIsStrongRef : 1;
    242  bool mDecodeRequested : 1;
    243 
    244  // Whether we want to defer our notifications by the non-virtual Observer
    245  // interfaces as image loads proceed.
    246  bool mPendingNotify : 1;
    247  bool mValidating : 1;
    248 };
    249 
    250 inline nsISupports* ToSupports(imgRequestProxy* p) {
    251  return NS_ISUPPORTS_CAST(imgIRequest*, p);
    252 }
    253 
    254 // Used for static image proxies for which no requests are available, so
    255 // certain behaviours must be overridden to compensate.
    256 class imgRequestProxyStatic : public imgRequestProxy {
    257 public:
    258  imgRequestProxyStatic(Image* aImage, nsIPrincipal* aImagePrincipal,
    259                        nsIPrincipal* aTriggeringPrincipal,
    260                        bool hadCrossOriginRedirects);
    261 
    262  NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) override;
    263  NS_IMETHOD GetTriggeringPrincipal(nsIPrincipal** aPrincipal) override;
    264 
    265  NS_IMETHOD GetHadCrossOriginRedirects(
    266      bool* aHadCrossOriginRedirects) override;
    267 
    268 protected:
    269  imgRequestProxy* NewClonedProxy() override;
    270 
    271  // Our principal. We have to cache it, rather than accessing the underlying
    272  // request on-demand, because static proxies don't have an underlying request.
    273  const nsCOMPtr<nsIPrincipal> mImagePrincipal;
    274  const nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
    275  const bool mHadCrossOriginRedirects;
    276 };
    277 
    278 #endif  // mozilla_image_imgRequestProxy_h