tor-browser

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

ResponsiveImageSelector.h (7725B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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_dom_responsiveimageselector_h__
      8 #define mozilla_dom_responsiveimageselector_h__
      9 
     10 #include "mozilla/FunctionRef.h"
     11 #include "mozilla/ServoBindingTypes.h"
     12 #include "mozilla/UniquePtr.h"
     13 #include "nsCycleCollectionParticipant.h"
     14 #include "nsIContent.h"
     15 #include "nsISupports.h"
     16 #include "nsString.h"
     17 
     18 class nsMediaQuery;
     19 class nsCSSValue;
     20 
     21 namespace mozilla::dom {
     22 
     23 class ResponsiveImageCandidate;
     24 
     25 class ResponsiveImageSelector {
     26  friend class ResponsiveImageCandidate;
     27 
     28 public:
     29  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ResponsiveImageSelector)
     30  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ResponsiveImageSelector)
     31 
     32  explicit ResponsiveImageSelector(nsIContent* aContent);
     33  explicit ResponsiveImageSelector(dom::Document* aDocument);
     34 
     35  // Parses the raw candidates and calls into the callback for each one of them.
     36  static void ParseSourceSet(const nsAString& aSrcSet,
     37                             FunctionRef<void(ResponsiveImageCandidate&&)>);
     38 
     39  // NOTE ABOUT CURRENT SELECTION
     40  //
     41  // The best candidate is selected lazily when GetSelectedImage*() is
     42  // called, or when SelectImage() is called explicitly. This result
     43  // is then cached until either invalidated by further Set*() calls,
     44  // or explicitly by replaced by SelectImage(aReselect = true).
     45  //
     46  // Because the selected image depends on external variants like
     47  // viewport size and device pixel ratio, the time at which image
     48  // selection occurs can affect the result.
     49 
     50  // Given a srcset string, parse and replace current candidates (does not
     51  // replace default source)
     52  bool SetCandidatesFromSourceSet(const nsAString& aSrcSet,
     53                                  nsIPrincipal* aTriggeringPrincipal = nullptr);
     54 
     55  // Fill the source sizes from a valid sizes descriptor. Returns false if
     56  // descriptor is invalid.
     57  bool SetSizesFromDescriptor(const nsAString& aSizesDescriptor);
     58 
     59  // Set the default source, treated as the least-precedence 1.0 density source.
     60  void SetDefaultSource(const nsAString& aURLString, nsIPrincipal* = nullptr);
     61  void SetDefaultSource(nsIURI* aURI, nsIPrincipal* = nullptr);
     62  void ClearDefaultSource();
     63 
     64  uint32_t NumCandidates(bool aIncludeDefault = true);
     65 
     66  // If this was created for a specific content. May be null if we were only
     67  // created for a document.
     68  nsIContent* Content();
     69 
     70  // The document we were created for, or the owner document of the content if
     71  // we were created for a specific nsIContent.
     72  dom::Document* Document();
     73 
     74  // Get the url and density for the selected best candidate. These
     75  // implicitly cause an image to be selected if necessary.
     76  already_AddRefed<nsIURI> GetSelectedImageURL();
     77  // Returns false if there is no selected image
     78  bool GetSelectedImageURLSpec(nsAString& aResult);
     79  double GetSelectedImageDensity();
     80  nsIPrincipal* GetSelectedImageTriggeringPrincipal();
     81 
     82  // Runs image selection now if necessary. If an image has already
     83  // been choosen, takes no action unless aReselect is true.
     84  //
     85  // aReselect - Always re-run selection, replacing the previously
     86  //             choosen image.
     87  // return - true if the selected image result changed.
     88  bool SelectImage(bool aReselect = false);
     89 
     90 protected:
     91  virtual ~ResponsiveImageSelector();
     92 
     93 private:
     94  // Append a candidate unless its selector is duplicated by a higher priority
     95  // candidate
     96  void AppendCandidateIfUnique(ResponsiveImageCandidate&& aCandidate);
     97 
     98  // Append a default candidate with this URL if necessary. Does not check if
     99  // the array already contains one, use SetDefaultSource instead.
    100  void MaybeAppendDefaultCandidate();
    101 
    102  // Get index of selected candidate, triggering selection if necessary.
    103  int GetSelectedCandidateIndex();
    104 
    105  // Forget currently selected candidate. (See "NOTE ABOUT CURRENT SELECTION"
    106  // above.)
    107  void ClearSelectedCandidate();
    108 
    109  // Compute a density from a Candidate width. Returns false if sizes were not
    110  // specified for this selector.
    111  //
    112  // aContext is the presContext to use for current viewport sizing, null will
    113  // use the associated content's context.
    114  bool ComputeFinalWidthForCurrentViewport(double* aWidth);
    115 
    116  nsCOMPtr<nsINode> mOwnerNode;
    117  // The cached URL for default candidate.
    118  nsString mDefaultSourceURL;
    119  nsCOMPtr<nsIPrincipal> mDefaultSourceTriggeringPrincipal;
    120  // If this array contains an eCandidateType_Default, it should be the last
    121  // element, such that the Setters can preserve/replace it respectively.
    122  nsTArray<ResponsiveImageCandidate> mCandidates;
    123  int mSelectedCandidateIndex;
    124  // The cached resolved URL for mSelectedCandidateIndex, such that we only
    125  // resolve the absolute URL at selection time
    126  nsCOMPtr<nsIURI> mSelectedCandidateURL;
    127 
    128  // Servo bits.
    129  UniquePtr<StyleSourceSizeList> mServoSourceSizeList;
    130 };
    131 
    132 class ResponsiveImageCandidate {
    133 public:
    134  ResponsiveImageCandidate();
    135  ResponsiveImageCandidate(const ResponsiveImageCandidate&) = delete;
    136  ResponsiveImageCandidate(ResponsiveImageCandidate&&) = default;
    137 
    138  void SetURLSpec(const nsAString& aURLString);
    139  void SetTriggeringPrincipal(nsIPrincipal* aPrincipal);
    140  // Set this as a default-candidate. This behaves the same as density 1.0, but
    141  // has a differing type such that it can be replaced by subsequent
    142  // SetDefaultSource calls.
    143  void SetParameterDefault();
    144 
    145  // Set this candidate as a by-density candidate with specified density.
    146  void SetParameterAsDensity(double aDensity);
    147  void SetParameterAsComputedWidth(int32_t aWidth);
    148 
    149  void SetParameterInvalid();
    150 
    151  // Consume descriptors from a string defined by aIter and aIterEnd, adjusts
    152  // aIter to the end of data consumed.
    153  // Returns false if descriptors string is invalid, but still parses to the end
    154  // of descriptors microsyntax.
    155  bool ConsumeDescriptors(nsAString::const_iterator& aIter,
    156                          const nsAString::const_iterator& aIterEnd);
    157 
    158  // Check if our parameter (which does not include the url) is identical
    159  bool HasSameParameter(const ResponsiveImageCandidate& aOther) const;
    160 
    161  const nsAString& URLString() const { return mURLString; }
    162  nsIPrincipal* TriggeringPrincipal() const { return mTriggeringPrincipal; }
    163 
    164  // Compute and return the density relative to a selector.
    165  double Density(ResponsiveImageSelector* aSelector) const;
    166  // If the width is already known. Useful when iterating over candidates to
    167  // avoid having each call re-compute the width.
    168  double Density(double aMatchingWidth) const;
    169 
    170  // Append the descriptors for this candidate serialized as a string.
    171  void AppendDescriptors(nsAString&) const;
    172 
    173  bool IsValid() const { return mType != CandidateType::Invalid; }
    174 
    175  // If this selector is computed from the selector's matching width.
    176  bool IsComputedFromWidth() const {
    177    return mType == CandidateType::ComputedFromWidth;
    178  }
    179 
    180  bool IsDefault() const { return mType == CandidateType::Default; }
    181 
    182  enum class CandidateType : uint8_t {
    183    Invalid,
    184    Density,
    185    // Treated as 1.0 density, but a separate type so we can update the
    186    // responsive candidates and default separately
    187    Default,
    188    ComputedFromWidth
    189  };
    190 
    191  CandidateType Type() const { return mType; }
    192 
    193 private:
    194  nsString mURLString;
    195  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
    196  CandidateType mType;
    197  union {
    198    double mDensity;
    199    int32_t mWidth;
    200  } mValue;
    201 };
    202 
    203 }  // namespace mozilla::dom
    204 
    205 #endif  // mozilla_dom_responsiveimageselector_h__