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 #include "mozilla/net/UrlClassifierCommon.h"
8
9 #include "ClassifierDummyChannel.h"
10 #include "mozilla/AntiTrackingUtils.h"
11 #include "mozilla/BasePrincipal.h"
12 #include "mozilla/ContentBlockingAllowList.h"
13 #include "mozilla/ContentBlockingNotifier.h"
14 #include "mozilla/dom/WindowGlobalParent.h"
15 #include "mozilla/net/HttpBaseChannel.h"
16 #include "mozilla/net/UrlClassifierFeatureFactory.h"
17 #include "mozilla/StaticPrefs_network.h"
18 #include "mozilla/StaticPrefs_privacy.h"
19 #include "mozilla/StaticPrefs_channelclassifier.h"
20 #include "mozilla/StaticPrefs_security.h"
21 #include "mozIThirdPartyUtil.h"
22 #include "nsContentUtils.h"
23 #include "nsIChannel.h"
24 #include "nsIClassifiedChannel.h"
25 #include "mozilla/dom/Document.h"
26 #include "nsIDocShell.h"
27 #include "nsIHttpChannel.h"
28 #include "nsIHttpChannelInternal.h"
29 #include "nsIParentChannel.h"
30 #include "nsIScriptError.h"
31 #include "nsIWebProgressListener.h"
32 #include "nsNetUtil.h"
33 #include "nsQueryObject.h"
34
35 namespace mozilla {
36 namespace net {
37
38 const nsCString::size_type UrlClassifierCommon::sMaxSpecLength = 128;
39
40 // MOZ_LOG=nsChannelClassifier:5
41 LazyLogModule UrlClassifierCommon::sLog("nsChannelClassifier");
42
43 /* static */
AddonMayLoad(nsIChannel * aChannel,nsIURI * aURI)44 bool UrlClassifierCommon::AddonMayLoad(nsIChannel* aChannel, nsIURI* aURI) {
45 nsCOMPtr<nsILoadInfo> channelLoadInfo = aChannel->LoadInfo();
46 // loadingPrincipal is used here to ensure we are loading into an
47 // addon principal. This allows an addon, with explicit permission, to
48 // call out to API endpoints that may otherwise get blocked.
49 nsIPrincipal* loadingPrincipal = channelLoadInfo->GetLoadingPrincipal();
50 if (!loadingPrincipal) {
51 return false;
52 }
53
54 return BasePrincipal::Cast(loadingPrincipal)->AddonAllowsLoad(aURI, true);
55 }
56
57 /* static */
ShouldEnableClassifier(nsIChannel * aChannel)58 bool UrlClassifierCommon::ShouldEnableClassifier(nsIChannel* aChannel) {
59 MOZ_ASSERT(aChannel);
60
61 nsCOMPtr<nsIURI> chanURI;
62 nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
63 if (NS_WARN_IF(NS_FAILED(rv))) {
64 return false;
65 }
66
67 if (UrlClassifierCommon::AddonMayLoad(aChannel, chanURI)) {
68 return false;
69 }
70
71 nsCOMPtr<nsIURI> topWinURI;
72 nsCOMPtr<nsIHttpChannelInternal> channel = do_QueryInterface(aChannel);
73 if (!channel) {
74 UC_LOG(("nsChannelClassifier: Not an HTTP channel"));
75 return false;
76 }
77
78 rv = channel->GetTopWindowURI(getter_AddRefs(topWinURI));
79 if (NS_FAILED(rv)) {
80 // Skipping top-level load.
81 return false;
82 }
83
84 // Tracking protection will be enabled so return without updating
85 // the security state. If any channels are subsequently cancelled
86 // (page elements blocked) the state will be then updated.
87 if (UC_LOG_ENABLED()) {
88 nsCString chanSpec = chanURI->GetSpecOrDefault();
89 chanSpec.Truncate(
90 std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength));
91 nsCString topWinSpec = topWinURI ? topWinURI->GetSpecOrDefault()
92 : NS_LITERAL_CSTRING("(null)");
93 topWinSpec.Truncate(
94 std::min(topWinSpec.Length(), UrlClassifierCommon::sMaxSpecLength));
95 UC_LOG(
96 ("nsChannelClassifier: Enabling url classifier checks on "
97 "channel[%p] with uri %s for toplevel window uri %s",
98 aChannel, chanSpec.get(), topWinSpec.get()));
99 }
100
101 return true;
102 }
103
104 /* static */
SetTrackingInfo(nsIChannel * aChannel,const nsTArray<nsCString> & aLists,const nsTArray<nsCString> & aFullHashes)105 nsresult UrlClassifierCommon::SetTrackingInfo(
106 nsIChannel* aChannel, const nsTArray<nsCString>& aLists,
107 const nsTArray<nsCString>& aFullHashes) {
108 NS_ENSURE_ARG(!aLists.IsEmpty());
109
110 // Can be called in EITHER the parent or child process.
111 nsresult rv;
112 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
113 do_QueryInterface(aChannel, &rv);
114 NS_ENSURE_SUCCESS(rv, rv);
115
116 if (classifiedChannel) {
117 classifiedChannel->SetMatchedTrackingInfo(aLists, aFullHashes);
118 }
119
120 nsCOMPtr<nsIParentChannel> parentChannel;
121 NS_QueryNotificationCallbacks(aChannel, parentChannel);
122 if (parentChannel) {
123 // This channel is a parent-process proxy for a child process request.
124 // Tell the child process channel to do this as well.
125 // TODO: We can remove the code sending the IPC to content to update
126 // tracking info once we move the ContentBlockingLog into the parent.
127 // This would be done in Bug 1599046.
128 nsAutoCString strLists, strHashes;
129 TablesToString(aLists, strLists);
130 TablesToString(aFullHashes, strHashes);
131
132 parentChannel->SetClassifierMatchedTrackingInfo(strLists, strHashes);
133 }
134
135 return NS_OK;
136 }
137
138 /* static */
SetBlockedContent(nsIChannel * channel,nsresult aErrorCode,const nsACString & aList,const nsACString & aProvider,const nsACString & aFullHash)139 nsresult UrlClassifierCommon::SetBlockedContent(nsIChannel* channel,
140 nsresult aErrorCode,
141 const nsACString& aList,
142 const nsACString& aProvider,
143 const nsACString& aFullHash) {
144 NS_ENSURE_ARG(!aList.IsEmpty());
145
146 switch (aErrorCode) {
147 case NS_ERROR_MALWARE_URI:
148 NS_SetRequestBlockingReason(
149 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_MALWARE_URI);
150 break;
151 case NS_ERROR_PHISHING_URI:
152 NS_SetRequestBlockingReason(
153 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_PHISHING_URI);
154 break;
155 case NS_ERROR_UNWANTED_URI:
156 NS_SetRequestBlockingReason(
157 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_UNWANTED_URI);
158 break;
159 case NS_ERROR_TRACKING_URI:
160 NS_SetRequestBlockingReason(
161 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_TRACKING_URI);
162 break;
163 case NS_ERROR_BLOCKED_URI:
164 NS_SetRequestBlockingReason(
165 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_BLOCKED_URI);
166 break;
167 case NS_ERROR_HARMFUL_URI:
168 NS_SetRequestBlockingReason(
169 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_HARMFUL_URI);
170 break;
171 case NS_ERROR_CRYPTOMINING_URI:
172 NS_SetRequestBlockingReason(
173 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_CRYPTOMINING_URI);
174 break;
175 case NS_ERROR_FINGERPRINTING_URI:
176 NS_SetRequestBlockingReason(
177 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_FINGERPRINTING_URI);
178 break;
179 case NS_ERROR_SOCIALTRACKING_URI:
180 NS_SetRequestBlockingReason(
181 channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_SOCIALTRACKING_URI);
182 break;
183 default:
184 MOZ_CRASH(
185 "Missing nsILoadInfo::BLOCKING_REASON* for the classification error");
186 break;
187 }
188
189 // Can be called in EITHER the parent or child process.
190 nsresult rv;
191 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
192 do_QueryInterface(channel, &rv);
193 NS_ENSURE_SUCCESS(rv, rv);
194
195 if (classifiedChannel) {
196 classifiedChannel->SetMatchedInfo(aList, aProvider, aFullHash);
197 }
198
199 if (XRE_IsParentProcess()) {
200 nsCOMPtr<nsIParentChannel> parentChannel;
201 NS_QueryNotificationCallbacks(channel, parentChannel);
202 if (parentChannel) {
203 // This channel is a parent-process proxy for a child process request.
204 // Tell the child process channel to do this as well.
205 // TODO: We can remove the code sending the IPC to content to update
206 // matched info once we move the ContentBlockingLog into the parent.
207 // This would be done in Bug 1601063.
208 parentChannel->SetClassifierMatchedInfo(aList, aProvider, aFullHash);
209 }
210
211 unsigned state =
212 UrlClassifierFeatureFactory::GetClassifierBlockingEventCode(aErrorCode);
213 if (!state) {
214 state = nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
215 }
216 ContentBlockingNotifier::OnEvent(channel, state);
217
218 return NS_OK;
219 }
220
221 // TODO: ReportToConsole is called in the child process,
222 // If nsContentUtils::ReportToConsole is not fission compatiable(cannot report
223 // to correct top-level window), we need to do this in the parent process
224 // instead (find the top-level window in the parent and send an IPC to child
225 // processes to report console).
226 nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
227 if (NS_WARN_IF(!thirdPartyUtil)) {
228 return NS_OK;
229 }
230
231 nsCOMPtr<nsIURI> uriBeingLoaded =
232 AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(channel);
233 nsCOMPtr<mozIDOMWindowProxy> win;
234 rv = thirdPartyUtil->GetTopWindowForChannel(channel, uriBeingLoaded,
235 getter_AddRefs(win));
236 NS_ENSURE_SUCCESS(rv, NS_OK);
237 auto* pwin = nsPIDOMWindowOuter::From(win);
238 nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
239 if (!docShell) {
240 return NS_OK;
241 }
242 RefPtr<dom::Document> doc = docShell->GetDocument();
243 NS_ENSURE_TRUE(doc, NS_OK);
244
245 // Log a warning to the web console.
246 nsCOMPtr<nsIURI> uri;
247 channel->GetURI(getter_AddRefs(uri));
248 AutoTArray<nsString, 1> params;
249 CopyUTF8toUTF16(uri->GetSpecOrDefault(), *params.AppendElement());
250 const char* message;
251 nsCString category;
252
253 if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)) {
254 message = UrlClassifierFeatureFactory::
255 ClassifierBlockingErrorCodeToConsoleMessage(aErrorCode, category);
256 } else {
257 message = "UnsafeUriBlocked";
258 category = NS_LITERAL_CSTRING("Safe Browsing");
259 }
260
261 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, category, doc,
262 nsContentUtils::eNECKO_PROPERTIES, message,
263 params);
264
265 return NS_OK;
266 }
267
268 /* static */
CreatePairwiseWhiteListURI(nsIChannel * aChannel,nsIURI ** aURI)269 nsresult UrlClassifierCommon::CreatePairwiseWhiteListURI(nsIChannel* aChannel,
270 nsIURI** aURI) {
271 MOZ_ASSERT(aChannel);
272 MOZ_ASSERT(aURI);
273
274 nsresult rv;
275 nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
276 NS_ENSURE_SUCCESS(rv, rv);
277 if (!chan) {
278 return NS_ERROR_FAILURE;
279 }
280
281 nsCOMPtr<nsIURI> topWinURI;
282 rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
283 NS_ENSURE_SUCCESS(rv, rv);
284
285 if (!topWinURI) {
286 if (UC_LOG_ENABLED()) {
287 nsresult rv;
288 nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(aChannel, &rv);
289 nsCOMPtr<nsIURI> uri;
290 rv = httpChan->GetURI(getter_AddRefs(uri));
291 nsAutoCString spec;
292 uri->GetAsciiSpec(spec);
293 spec.Truncate(
294 std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
295 UC_LOG(("CreatePairwiseWhiteListURI: No window URI associated with %s",
296 spec.get()));
297 }
298 return NS_OK;
299 }
300
301 nsCOMPtr<nsIScriptSecurityManager> securityManager =
302 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
303 NS_ENSURE_SUCCESS(rv, rv);
304 nsCOMPtr<nsIPrincipal> chanPrincipal;
305 rv = securityManager->GetChannelURIPrincipal(aChannel,
306 getter_AddRefs(chanPrincipal));
307 NS_ENSURE_SUCCESS(rv, rv);
308
309 // Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
310 nsAutoCString pageHostname, resourceDomain;
311 rv = topWinURI->GetHost(pageHostname);
312 if (NS_FAILED(rv)) {
313 // When the top-level page doesn't support GetHost, for example, about:home,
314 // we don't return an error here; instead, we return success to make sure
315 // that the lookup process calling this API continues to run.
316 UC_LOG(
317 ("CreatePairwiseWhiteListURI: Cannot get host from the top-level "
318 "(channel=%p)",
319 aChannel));
320 return NS_OK;
321 }
322
323 rv = chanPrincipal->GetBaseDomain(resourceDomain);
324 NS_ENSURE_SUCCESS(rv, rv);
325 nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") + pageHostname +
326 NS_LITERAL_CSTRING("/?resource=") +
327 resourceDomain;
328 UC_LOG(
329 ("CreatePairwiseWhiteListURI: Looking for %s in the whitelist "
330 "(channel=%p)",
331 whitelistEntry.get(), aChannel));
332
333 nsCOMPtr<nsIURI> whitelistURI;
334 rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
335 NS_ENSURE_SUCCESS(rv, rv);
336
337 whitelistURI.forget(aURI);
338 return NS_OK;
339 }
340
341 namespace {
342
LowerPriorityHelper(nsIChannel * aChannel)343 void LowerPriorityHelper(nsIChannel* aChannel) {
344 MOZ_ASSERT(aChannel);
345
346 bool isBlockingResource = false;
347
348 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
349 if (cos) {
350 if (StaticPrefs::network_http_tailing_enabled()) {
351 uint32_t cosFlags = 0;
352 cos->GetClassFlags(&cosFlags);
353 isBlockingResource =
354 cosFlags & (nsIClassOfService::UrgentStart |
355 nsIClassOfService::Leader | nsIClassOfService::Unblocked);
356
357 // Requests not allowed to be tailed are usually those with higher
358 // prioritization. That overweights being a tracker: don't throttle
359 // them when not in background.
360 if (!(cosFlags & nsIClassOfService::TailForbidden)) {
361 cos->AddClassFlags(nsIClassOfService::Throttleable);
362 }
363 } else {
364 // Yes, we even don't want to evaluate the isBlockingResource when tailing
365 // is off see bug 1395525.
366
367 cos->AddClassFlags(nsIClassOfService::Throttleable);
368 }
369 }
370
371 if (!isBlockingResource) {
372 nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aChannel);
373 if (p) {
374 if (UC_LOG_ENABLED()) {
375 nsCOMPtr<nsIURI> uri;
376 aChannel->GetURI(getter_AddRefs(uri));
377 nsAutoCString spec;
378 uri->GetAsciiSpec(spec);
379 spec.Truncate(
380 std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
381 UC_LOG(("Setting PRIORITY_LOWEST for channel[%p] (%s)", aChannel,
382 spec.get()));
383 }
384 p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
385 }
386 }
387 }
388
389 } // namespace
390
391 // static
SetClassificationFlagsHelper(nsIChannel * aChannel,uint32_t aClassificationFlags,bool aIsThirdParty)392 void UrlClassifierCommon::SetClassificationFlagsHelper(
393 nsIChannel* aChannel, uint32_t aClassificationFlags, bool aIsThirdParty) {
394 MOZ_ASSERT(aChannel);
395
396 nsCOMPtr<nsIParentChannel> parentChannel;
397 NS_QueryNotificationCallbacks(aChannel, parentChannel);
398 if (parentChannel) {
399 // This channel is a parent-process proxy for a child process
400 // request. We should notify the child process as well.
401 parentChannel->NotifyClassificationFlags(aClassificationFlags,
402 aIsThirdParty);
403 }
404
405 RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(aChannel);
406 if (httpChannel) {
407 httpChannel->AddClassificationFlags(aClassificationFlags, aIsThirdParty);
408 }
409
410 RefPtr<ClassifierDummyChannel> dummyChannel = do_QueryObject(aChannel);
411 if (dummyChannel) {
412 dummyChannel->AddClassificationFlags(aClassificationFlags, aIsThirdParty);
413 }
414 }
415
416 // static
AnnotateChannel(nsIChannel * aChannel,uint32_t aClassificationFlags,uint32_t aLoadingState)417 void UrlClassifierCommon::AnnotateChannel(nsIChannel* aChannel,
418 uint32_t aClassificationFlags,
419 uint32_t aLoadingState) {
420 MOZ_ASSERT(XRE_IsParentProcess());
421 MOZ_ASSERT(aChannel);
422
423 nsCOMPtr<nsIURI> chanURI;
424 nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
425 if (NS_WARN_IF(NS_FAILED(rv))) {
426 UC_LOG(
427 ("UrlClassifierCommon::AnnotateChannel nsIChannel::GetURI(%p) failed",
428 (void*)aChannel));
429 return;
430 }
431
432 bool isThirdPartyWithTopLevelWinURI =
433 AntiTrackingUtils::IsThirdPartyChannel(aChannel);
434
435 UC_LOG(("UrlClassifierCommon::AnnotateChannel, annotating channel[%p]",
436 aChannel));
437
438 SetClassificationFlagsHelper(aChannel, aClassificationFlags,
439 isThirdPartyWithTopLevelWinURI);
440
441 // We consider valid tracking flags (based on the current strict vs basic list
442 // prefs) and cryptomining (which is not considered as tracking).
443 bool validClassificationFlags =
444 IsTrackingClassificationFlag(aClassificationFlags) ||
445 IsCryptominingClassificationFlag(aClassificationFlags);
446
447 if (validClassificationFlags && isThirdPartyWithTopLevelWinURI) {
448 ContentBlockingNotifier::OnEvent(aChannel, aLoadingState);
449 }
450
451 if (isThirdPartyWithTopLevelWinURI &&
452 StaticPrefs::privacy_trackingprotection_lower_network_priority()) {
453 LowerPriorityHelper(aChannel);
454 }
455 }
456
457 // static
IsAllowListed(nsIChannel * aChannel)458 bool UrlClassifierCommon::IsAllowListed(nsIChannel* aChannel) {
459 nsCOMPtr<nsIHttpChannelInternal> channel = do_QueryInterface(aChannel);
460 if (!channel) {
461 UC_LOG(("nsChannelClassifier: Not an HTTP channel"));
462 return false;
463 }
464
465 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
466
467 bool isAllowListed = false;
468 if (StaticPrefs::channelclassifier_allowlist_example()) {
469 UC_LOG(("nsChannelClassifier: Allowlisting test domain"));
470
471 nsCOMPtr<nsIIOService> ios = services::GetIOService();
472 if (NS_WARN_IF(!ios)) {
473 return false;
474 }
475
476 nsCOMPtr<nsIURI> uri;
477 nsresult rv =
478 ios->NewURI(NS_LITERAL_CSTRING("http://allowlisted.example.com"),
479 nullptr, nullptr, getter_AddRefs(uri));
480 if (NS_WARN_IF(NS_FAILED(rv))) {
481 return false;
482 }
483 nsCOMPtr<nsIPrincipal> cbAllowListPrincipal =
484 BasePrincipal::CreateContentPrincipal(uri,
485 loadInfo->GetOriginAttributes());
486
487 rv = ContentBlockingAllowList::Check(
488 cbAllowListPrincipal, NS_UsePrivateBrowsing(aChannel), isAllowListed);
489 if (NS_WARN_IF(NS_FAILED(rv))) {
490 return false;
491 }
492 } else {
493 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
494 MOZ_ALWAYS_SUCCEEDS(
495 loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)));
496 isAllowListed = cookieJarSettings->GetIsOnContentBlockingAllowList();
497 }
498
499 if (isAllowListed) {
500 if (UC_LOG_ENABLED()) {
501 nsCOMPtr<nsIURI> chanURI;
502 nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
503 if (NS_WARN_IF(NS_FAILED(rv))) {
504 return isAllowListed;
505 }
506
507 nsCString chanSpec = chanURI->GetSpecOrDefault();
508 chanSpec.Truncate(
509 std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength));
510 UC_LOG(("nsChannelClassifier: User override on channel[%p] (%s)",
511 aChannel, chanSpec.get()));
512 }
513 }
514
515 return isAllowListed;
516 }
517
518 // static
IsTrackingClassificationFlag(uint32_t aFlag)519 bool UrlClassifierCommon::IsTrackingClassificationFlag(uint32_t aFlag) {
520 if (StaticPrefs::privacy_annotate_channels_strict_list_enabled() &&
521 (aFlag & nsIClassifiedChannel::ClassificationFlags::
522 CLASSIFIED_ANY_STRICT_TRACKING)) {
523 return true;
524 }
525
526 if (StaticPrefs::privacy_socialtracking_block_cookies_enabled() &&
527 IsSocialTrackingClassificationFlag(aFlag)) {
528 return true;
529 }
530
531 return (
532 aFlag &
533 nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_ANY_BASIC_TRACKING);
534 }
535
536 // static
IsSocialTrackingClassificationFlag(uint32_t aFlag)537 bool UrlClassifierCommon::IsSocialTrackingClassificationFlag(uint32_t aFlag) {
538 if (aFlag & nsIClassifiedChannel::ClassificationFlags::
539 CLASSIFIED_ANY_SOCIAL_TRACKING) {
540 return true;
541 }
542
543 return false;
544 }
545
546 // static
IsCryptominingClassificationFlag(uint32_t aFlag)547 bool UrlClassifierCommon::IsCryptominingClassificationFlag(uint32_t aFlag) {
548 if (aFlag &
549 nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_CRYPTOMINING) {
550 return true;
551 }
552
553 if (StaticPrefs::privacy_annotate_channels_strict_list_enabled() &&
554 (aFlag & nsIClassifiedChannel::ClassificationFlags::
555 CLASSIFIED_CRYPTOMINING_CONTENT)) {
556 return true;
557 }
558
559 return false;
560 }
561
TablesToString(const nsTArray<nsCString> & aList,nsACString & aString)562 void UrlClassifierCommon::TablesToString(const nsTArray<nsCString>& aList,
563 nsACString& aString) {
564 aString.Truncate();
565
566 for (const nsCString& table : aList) {
567 if (!aString.IsEmpty()) {
568 aString.Append(",");
569 }
570 aString.Append(table);
571 }
572 }
573
TablesToClassificationFlags(const nsTArray<nsCString> & aList,const std::vector<ClassificationData> & aData,uint32_t aDefaultFlag)574 uint32_t UrlClassifierCommon::TablesToClassificationFlags(
575 const nsTArray<nsCString>& aList,
576 const std::vector<ClassificationData>& aData, uint32_t aDefaultFlag) {
577 uint32_t flags = 0;
578 for (const nsCString& table : aList) {
579 flags |= TableToClassificationFlag(table, aData);
580 }
581
582 if (flags == 0) {
583 flags |= aDefaultFlag;
584 }
585
586 return flags;
587 }
588
TableToClassificationFlag(const nsACString & aTable,const std::vector<ClassificationData> & aData)589 uint32_t UrlClassifierCommon::TableToClassificationFlag(
590 const nsACString& aTable, const std::vector<ClassificationData>& aData) {
591 for (const ClassificationData& data : aData) {
592 if (StringBeginsWith(aTable, data.mPrefix)) {
593 return data.mFlag;
594 }
595 }
596
597 return 0;
598 }
599
600 /* static */
IsPassiveContent(nsIChannel * aChannel)601 bool UrlClassifierCommon::IsPassiveContent(nsIChannel* aChannel) {
602 MOZ_ASSERT(aChannel);
603
604 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
605 nsContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
606
607 // Return true if aChannel is loading passive display content, as
608 // defined by the mixed content blocker.
609 // https://searchfox.org/mozilla-central/rev/c80fa7258c935223fe319c5345b58eae85d4c6ae/dom/security/nsMixedContentBlocker.cpp#532
610 return contentType == nsIContentPolicy::TYPE_IMAGE ||
611 contentType == nsIContentPolicy::TYPE_MEDIA ||
612 (contentType == nsIContentPolicy::TYPE_OBJECT_SUBREQUEST &&
613 !StaticPrefs::security_mixed_content_block_object_subrequest());
614 }
615
616 } // namespace net
617 } // namespace mozilla
618