4343
4444namespace WebCore {
4545
46+ WTF::Vector<WTF::KeyValuePair<WTF::String, WTF::String>> MixedContentChecker::m_whitelist = {};
47+
4648// static
4749bool MixedContentChecker::isMixedContent (SecurityOrigin& securityOrigin, const URL& url)
4850{
@@ -65,6 +67,11 @@ bool MixedContentChecker::canDisplayInsecureContent(Frame& frame, SecurityOrigin
6567 if (!isMixedContent (securityOrigin, url))
6668 return true ;
6769
70+ if (isWhitelisted (securityOrigin.toString (), url.protocolHostAndPort ())) {
71+ logWarning (frame, true , " display" _s, url);
72+ return true ;
73+ }
74+
6875 if (!frame.document ()->contentSecurityPolicy ()->allowRunningOrDisplayingInsecureContent (url))
6976 return false ;
7077
@@ -88,6 +95,11 @@ bool MixedContentChecker::canRunInsecureContent(Frame& frame, SecurityOrigin& se
8895 if (!isMixedContent (securityOrigin, url))
8996 return true ;
9097
98+ if (isWhitelisted (securityOrigin.toString (), url.protocolHostAndPort ())) {
99+ logWarning (frame, true , " run" _s, url);
100+ return true ;
101+ }
102+
91103 if (!frame.document ()->contentSecurityPolicy ()->allowRunningOrDisplayingInsecureContent (url))
92104 return false ;
93105
@@ -140,4 +152,79 @@ std::optional<String> MixedContentChecker::checkForMixedContentInFrameTree(const
140152 return std::nullopt ;
141153}
142154
155+ bool wildcardMatch (const String& pattern, const String& url)
156+ {
157+ int patternLen = pattern.length ();
158+ int patternPos = 0 ;
159+ int urlLen = url.length ();
160+ int urlPos = 0 ;
161+ int wildcardPos = -1 ;
162+ int wildcardMatchEnd = 0 ;
163+
164+ while (urlPos < urlLen) {
165+ if (patternPos < patternLen && pattern[patternPos] == url[urlPos]) {
166+ // characters match
167+ patternPos++;
168+ urlPos++;
169+ } else if (patternPos < patternLen && pattern[patternPos] == ' *' ) {
170+ // mark wildcard position, start matching the rest of the pattern
171+ wildcardPos = patternPos;
172+ wildcardMatchEnd = urlPos;
173+ patternPos++;
174+ } else if (wildcardPos != -1 ) {
175+ // no match, but we have a wildcard - assume wildcard handles a match to this position,
176+ // revert patternPos to after last *
177+ patternPos = wildcardPos + 1 ;
178+ wildcardMatchEnd++;
179+ urlPos = wildcardMatchEnd;
180+ } else {
181+ // no match, no wildcard - pattern does not match
182+ return false ;
183+ }
184+ }
185+
186+ // url matches so far, and we're at the end of it
187+ // skip any remaining wildcards
188+ while (patternPos < patternLen && pattern[patternPos] == ' *' ) {
189+ patternPos++;
190+ }
191+ // if we're at the end of pattern, that's a match
192+ // otherwise, the remaining part of the pattern can't be matched
193+ return patternPos == patternLen;
194+ }
195+
196+ // static
197+ bool MixedContentChecker::isWhitelisted (const String& origin, const String& domain)
198+ {
199+ for (auto kvPair : m_whitelist) {
200+ if (wildcardMatch (kvPair.key , origin) && wildcardMatch (kvPair.value , domain)) {
201+ return true ;
202+ }
203+ }
204+ return false ;
205+ }
206+
207+ // static
208+ void MixedContentChecker::addMixedContentWhitelistEntry (const String& origin, const String& domain)
209+ {
210+ MixedContentChecker::m_whitelist.append (makeKeyValuePair (origin, domain));
211+ }
212+
213+ // static
214+ void MixedContentChecker::removeMixedContentWhitelistEntry (const String& origin, const String& domain)
215+ {
216+ for (size_t i = 0 ; i < MixedContentChecker::m_whitelist.size (); i++) {
217+ if (MixedContentChecker::m_whitelist[i].key == origin && MixedContentChecker::m_whitelist[i].value == domain) {
218+ MixedContentChecker::m_whitelist.remove (i);
219+ break ;
220+ }
221+ }
222+ }
223+
224+ // static
225+ void MixedContentChecker::resetMixedContentWhitelist ()
226+ {
227+ MixedContentChecker::m_whitelist.clear ();
228+ }
229+
143230} // namespace WebCore
0 commit comments