1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "PreloadHashKey.h"
6
7 #include "mozilla/dom/Element.h" // StringToCORSMode
8 #include "mozilla/css/SheetLoadData.h"
9 #include "mozilla/dom/ReferrerPolicyBinding.h"
10 #include "nsIPrincipal.h"
11 #include "nsIReferrerInfo.h"
12
13 namespace mozilla {
14
PreloadHashKey(const nsIURI * aKey,ResourceType aAs)15 PreloadHashKey::PreloadHashKey(const nsIURI* aKey, ResourceType aAs)
16 : nsURIHashKey(aKey), mAs(aAs) {}
17
PreloadHashKey(const PreloadHashKey * aKey)18 PreloadHashKey::PreloadHashKey(const PreloadHashKey* aKey)
19 : nsURIHashKey(aKey->mKey) {
20 *this = *aKey;
21 }
22
PreloadHashKey(PreloadHashKey && aToMove)23 PreloadHashKey::PreloadHashKey(PreloadHashKey&& aToMove)
24 : nsURIHashKey(std::move(aToMove)) {
25 mAs = std::move(aToMove.mAs);
26 mCORSMode = std::move(aToMove.mCORSMode);
27 mPrincipal = std::move(aToMove.mPrincipal);
28
29 switch (mAs) {
30 case ResourceType::SCRIPT:
31 mScript = std::move(aToMove.mScript);
32 break;
33 case ResourceType::STYLE:
34 mStyle = std::move(aToMove.mStyle);
35 break;
36 case ResourceType::IMAGE:
37 break;
38 case ResourceType::FONT:
39 break;
40 case ResourceType::FETCH:
41 break;
42 case ResourceType::NONE:
43 break;
44 }
45 }
46
operator =(const PreloadHashKey & aOther)47 PreloadHashKey& PreloadHashKey::operator=(const PreloadHashKey& aOther) {
48 MOZ_ASSERT(mAs == ResourceType::NONE || aOther.mAs == ResourceType::NONE,
49 "Assigning more than once, only reset is allowed");
50
51 nsURIHashKey::operator=(aOther);
52
53 mAs = aOther.mAs;
54 mCORSMode = aOther.mCORSMode;
55 mPrincipal = aOther.mPrincipal;
56
57 switch (mAs) {
58 case ResourceType::SCRIPT:
59 mScript = aOther.mScript;
60 break;
61 case ResourceType::STYLE:
62 mStyle = aOther.mStyle;
63 break;
64 case ResourceType::IMAGE:
65 break;
66 case ResourceType::FONT:
67 break;
68 case ResourceType::FETCH:
69 break;
70 case ResourceType::NONE:
71 break;
72 }
73
74 return *this;
75 }
76
77 // static
CreateAsScript(nsIURI * aURI,CORSMode aCORSMode,dom::ScriptKind aScriptKind)78 PreloadHashKey PreloadHashKey::CreateAsScript(nsIURI* aURI, CORSMode aCORSMode,
79 dom::ScriptKind aScriptKind) {
80 PreloadHashKey key(aURI, ResourceType::SCRIPT);
81 key.mCORSMode = aCORSMode;
82
83 key.mScript.mScriptKind = aScriptKind;
84
85 return key;
86 }
87
88 // static
CreateAsScript(nsIURI * aURI,const nsAString & aCrossOrigin,const nsAString & aType)89 PreloadHashKey PreloadHashKey::CreateAsScript(nsIURI* aURI,
90 const nsAString& aCrossOrigin,
91 const nsAString& aType) {
92 dom::ScriptKind scriptKind = dom::ScriptKind::eClassic;
93 if (aType.LowerCaseEqualsASCII("module")) {
94 scriptKind = dom::ScriptKind::eModule;
95 }
96 CORSMode crossOrigin = dom::Element::StringToCORSMode(aCrossOrigin);
97 return CreateAsScript(aURI, crossOrigin, scriptKind);
98 }
99
100 // static
CreateAsStyle(nsIURI * aURI,nsIPrincipal * aPrincipal,CORSMode aCORSMode,css::SheetParsingMode aParsingMode)101 PreloadHashKey PreloadHashKey::CreateAsStyle(
102 nsIURI* aURI, nsIPrincipal* aPrincipal, CORSMode aCORSMode,
103 css::SheetParsingMode aParsingMode) {
104 PreloadHashKey key(aURI, ResourceType::STYLE);
105 key.mCORSMode = aCORSMode;
106 key.mPrincipal = aPrincipal;
107
108 key.mStyle.mParsingMode = aParsingMode;
109
110 return key;
111 }
112
113 // static
CreateAsStyle(css::SheetLoadData & aSheetLoadData)114 PreloadHashKey PreloadHashKey::CreateAsStyle(
115 css::SheetLoadData& aSheetLoadData) {
116 return CreateAsStyle(aSheetLoadData.mURI, aSheetLoadData.mTriggeringPrincipal,
117 aSheetLoadData.mSheet->GetCORSMode(),
118 aSheetLoadData.mSheet->ParsingMode());
119 }
120
121 // static
CreateAsImage(nsIURI * aURI,nsIPrincipal * aPrincipal,CORSMode aCORSMode)122 PreloadHashKey PreloadHashKey::CreateAsImage(nsIURI* aURI,
123 nsIPrincipal* aPrincipal,
124 CORSMode aCORSMode) {
125 PreloadHashKey key(aURI, ResourceType::IMAGE);
126 key.mCORSMode = aCORSMode;
127 key.mPrincipal = aPrincipal;
128
129 return key;
130 }
131
132 // static
CreateAsFetch(nsIURI * aURI,CORSMode aCORSMode)133 PreloadHashKey PreloadHashKey::CreateAsFetch(nsIURI* aURI, CORSMode aCORSMode) {
134 PreloadHashKey key(aURI, ResourceType::FETCH);
135 key.mCORSMode = aCORSMode;
136
137 return key;
138 }
139
140 // static
CreateAsFetch(nsIURI * aURI,const nsAString & aCrossOrigin)141 PreloadHashKey PreloadHashKey::CreateAsFetch(nsIURI* aURI,
142 const nsAString& aCrossOrigin) {
143 return CreateAsFetch(aURI, dom::Element::StringToCORSMode(aCrossOrigin));
144 }
145
CreateAsFont(nsIURI * aURI,CORSMode aCORSMode)146 PreloadHashKey PreloadHashKey::CreateAsFont(nsIURI* aURI, CORSMode aCORSMode) {
147 PreloadHashKey key(aURI, ResourceType::FONT);
148 key.mCORSMode = aCORSMode;
149
150 return key;
151 }
152
KeyEquals(KeyTypePointer aOther) const153 bool PreloadHashKey::KeyEquals(KeyTypePointer aOther) const {
154 if (mAs != aOther->mAs || mCORSMode != aOther->mCORSMode) {
155 return false;
156 }
157
158 if (!mPrincipal != !aOther->mPrincipal) {
159 // One or the other has a principal, but not both... not equal
160 return false;
161 }
162
163 if (mPrincipal && !mPrincipal->Equals(aOther->mPrincipal)) {
164 return false;
165 }
166
167 if (!nsURIHashKey::KeyEquals(
168 static_cast<const nsURIHashKey*>(aOther)->GetKey())) {
169 return false;
170 }
171
172 switch (mAs) {
173 case ResourceType::SCRIPT:
174 if (mScript.mScriptKind != aOther->mScript.mScriptKind) {
175 return false;
176 }
177 break;
178 case ResourceType::STYLE: {
179 if (mStyle.mParsingMode != aOther->mStyle.mParsingMode) {
180 return false;
181 }
182 break;
183 }
184 case ResourceType::IMAGE:
185 // No more checks needed. The image cache key consists of the document
186 // (which we are scoped into), origin attributes (which we compare as part
187 // of the principal check) and the URL. imgLoader::ValidateEntry compares
188 // CORS, referrer info and principal, which we do by default.
189 break;
190 case ResourceType::FONT:
191 break;
192 case ResourceType::FETCH:
193 // No more checks needed.
194 break;
195 case ResourceType::NONE:
196 break;
197 }
198
199 return true;
200 }
201
202 // static
HashKey(KeyTypePointer aKey)203 PLDHashNumber PreloadHashKey::HashKey(KeyTypePointer aKey) {
204 PLDHashNumber hash = nsURIHashKey::HashKey(aKey->mKey);
205
206 // Enough to use the common attributes
207 hash = AddToHash(hash, static_cast<uint32_t>(aKey->mAs));
208 hash = AddToHash(hash, static_cast<uint32_t>(aKey->mCORSMode));
209
210 return hash;
211 }
212
213 } // namespace mozilla
214