Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / base / ResponsiveImageSelector.h
blob1bbb8b47e4970e0c42a8fc21feb2b456aee8acc9
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/. */
7 #ifndef mozilla_dom_responsiveimageselector_h__
8 #define mozilla_dom_responsiveimageselector_h__
10 #include "mozilla/UniquePtr.h"
11 #include "mozilla/ServoBindingTypes.h"
12 #include "mozilla/FunctionRef.h"
13 #include "nsISupports.h"
14 #include "nsIContent.h"
15 #include "nsString.h"
16 #include "nsCycleCollectionParticipant.h"
18 class nsMediaQuery;
19 class nsCSSValue;
21 namespace mozilla::dom {
23 class ResponsiveImageCandidate;
25 class ResponsiveImageSelector {
26 friend class ResponsiveImageCandidate;
28 public:
29 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ResponsiveImageSelector)
30 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ResponsiveImageSelector)
32 explicit ResponsiveImageSelector(nsIContent* aContent);
33 explicit ResponsiveImageSelector(dom::Document* aDocument);
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&&)>);
39 // NOTE ABOUT CURRENT SELECTION
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).
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.
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);
55 // Fill the source sizes from a valid sizes descriptor. Returns false if
56 // descriptor is invalid.
57 bool SetSizesFromDescriptor(const nsAString& aSizesDescriptor);
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();
64 uint32_t NumCandidates(bool aIncludeDefault = true);
66 // If this was created for a specific content. May be null if we were only
67 // created for a document.
68 nsIContent* Content();
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();
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();
82 // Runs image selection now if necessary. If an image has already
83 // been choosen, takes no action unless aReselect is true.
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);
90 protected:
91 virtual ~ResponsiveImageSelector();
93 private:
94 // Append a candidate unless its selector is duplicated by a higher priority
95 // candidate
96 void AppendCandidateIfUnique(ResponsiveImageCandidate&& aCandidate);
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();
102 // Get index of selected candidate, triggering selection if necessary.
103 int GetSelectedCandidateIndex();
105 // Forget currently selected candidate. (See "NOTE ABOUT CURRENT SELECTION"
106 // above.)
107 void ClearSelectedCandidate();
109 // Compute a density from a Candidate width. Returns false if sizes were not
110 // specified for this selector.
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);
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;
128 // Servo bits.
129 UniquePtr<StyleSourceSizeList> mServoSourceSizeList;
132 class ResponsiveImageCandidate {
133 public:
134 ResponsiveImageCandidate();
135 ResponsiveImageCandidate(const ResponsiveImageCandidate&) = delete;
136 ResponsiveImageCandidate(ResponsiveImageCandidate&&) = default;
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();
145 // Set this candidate as a by-density candidate with specified density.
146 void SetParameterAsDensity(double aDensity);
147 void SetParameterAsComputedWidth(int32_t aWidth);
149 void SetParameterInvalid();
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);
158 // Check if our parameter (which does not include the url) is identical
159 bool HasSameParameter(const ResponsiveImageCandidate& aOther) const;
161 const nsAString& URLString() const { return mURLString; }
162 nsIPrincipal* TriggeringPrincipal() const { return mTriggeringPrincipal; }
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;
170 // Append the descriptors for this candidate serialized as a string.
171 void AppendDescriptors(nsAString&) const;
173 bool IsValid() const { return mType != CandidateType::Invalid; }
175 // If this selector is computed from the selector's matching width.
176 bool IsComputedFromWidth() const {
177 return mType == CandidateType::ComputedFromWidth;
180 bool IsDefault() const { return mType == CandidateType::Default; }
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
191 CandidateType Type() const { return mType; }
193 private:
194 nsString mURLString;
195 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
196 CandidateType mType;
197 union {
198 double mDensity;
199 int32_t mWidth;
200 } mValue;
203 } // namespace mozilla::dom
205 #endif // mozilla_dom_responsiveimageselector_h__