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