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 file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "AntiTrackingUtils.h"
8 
9 #include "AntiTrackingLog.h"
10 #include "mozilla/dom/BrowsingContext.h"
11 #include "mozilla/dom/CanonicalBrowsingContext.h"
12 #include "mozilla/net/CookieJarSettings.h"
13 #include "mozilla/dom/Document.h"
14 #include "mozilla/dom/WindowGlobalParent.h"
15 #include "mozilla/dom/WindowContext.h"
16 #include "mozilla/net/NeckoChannelParams.h"
17 #include "mozilla/PermissionManager.h"
18 #include "mozIThirdPartyUtil.h"
19 #include "nsIChannel.h"
20 #include "nsIPermission.h"
21 #include "nsIURI.h"
22 #include "nsNetUtil.h"
23 #include "nsPIDOMWindow.h"
24 #include "nsSandboxFlags.h"
25 #include "nsScriptSecurityManager.h"
26 
27 #define ANTITRACKING_PERM_KEY "3rdPartyStorage"
28 
29 using namespace mozilla;
30 using namespace mozilla::dom;
31 
32 /* static */ already_AddRefed<nsPIDOMWindowInner>
GetInnerWindow(BrowsingContext * aBrowsingContext)33 AntiTrackingUtils::GetInnerWindow(BrowsingContext* aBrowsingContext) {
34   MOZ_ASSERT(aBrowsingContext);
35 
36   nsCOMPtr<nsPIDOMWindowOuter> outer = aBrowsingContext->GetDOMWindow();
37   if (!outer) {
38     return nullptr;
39   }
40 
41   nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow();
42   return inner.forget();
43 }
44 
45 /* static */ already_AddRefed<nsPIDOMWindowOuter>
GetTopWindow(nsPIDOMWindowInner * aWindow)46 AntiTrackingUtils::GetTopWindow(nsPIDOMWindowInner* aWindow) {
47   Document* document = aWindow->GetExtantDoc();
48   if (!document) {
49     return nullptr;
50   }
51 
52   nsIChannel* channel = document->GetChannel();
53   if (!channel) {
54     return nullptr;
55   }
56 
57   nsCOMPtr<nsPIDOMWindowOuter> pwin =
58       aWindow->GetBrowsingContext()->Top()->GetDOMWindow();
59 
60   if (!pwin) {
61     return nullptr;
62   }
63 
64   return pwin.forget();
65 }
66 
67 /* static */
MaybeGetDocumentURIBeingLoaded(nsIChannel * aChannel)68 already_AddRefed<nsIURI> AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(
69     nsIChannel* aChannel) {
70   nsCOMPtr<nsIURI> uriBeingLoaded;
71   nsLoadFlags loadFlags = 0;
72   nsresult rv = aChannel->GetLoadFlags(&loadFlags);
73   if (NS_WARN_IF(NS_FAILED(rv))) {
74     return nullptr;
75   }
76   if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
77     // If the channel being loaded is a document channel, this call may be
78     // coming from an OnStopRequest notification, which might mean that our
79     // document may still be in the loading process, so we may need to pass in
80     // the uriBeingLoaded argument explicitly.
81     rv = aChannel->GetURI(getter_AddRefs(uriBeingLoaded));
82     if (NS_WARN_IF(NS_FAILED(rv))) {
83       return nullptr;
84     }
85   }
86   return uriBeingLoaded.forget();
87 }
88 
89 // static
CreateStoragePermissionKey(const nsACString & aTrackingOrigin,nsACString & aPermissionKey)90 void AntiTrackingUtils::CreateStoragePermissionKey(
91     const nsACString& aTrackingOrigin, nsACString& aPermissionKey) {
92   MOZ_ASSERT(aPermissionKey.IsEmpty());
93 
94   static const nsLiteralCString prefix =
95       NS_LITERAL_CSTRING(ANTITRACKING_PERM_KEY "^");
96 
97   aPermissionKey.SetCapacity(prefix.Length() + aTrackingOrigin.Length());
98   aPermissionKey.Append(prefix);
99   aPermissionKey.Append(aTrackingOrigin);
100 }
101 
102 // static
CreateStoragePermissionKey(nsIPrincipal * aPrincipal,nsACString & aKey)103 bool AntiTrackingUtils::CreateStoragePermissionKey(nsIPrincipal* aPrincipal,
104                                                    nsACString& aKey) {
105   if (!aPrincipal) {
106     return false;
107   }
108 
109   nsAutoCString origin;
110   nsresult rv = aPrincipal->GetOriginNoSuffix(origin);
111   if (NS_WARN_IF(NS_FAILED(rv))) {
112     return false;
113   }
114 
115   CreateStoragePermissionKey(origin, aKey);
116   return true;
117 }
118 
119 // static
IsStorageAccessPermission(nsIPermission * aPermission,nsIPrincipal * aPrincipal)120 bool AntiTrackingUtils::IsStorageAccessPermission(nsIPermission* aPermission,
121                                                   nsIPrincipal* aPrincipal) {
122   MOZ_ASSERT(aPermission);
123   MOZ_ASSERT(aPrincipal);
124 
125   // The permission key may belong either to a tracking origin on the same
126   // origin as the granted origin, or on another origin as the granted origin
127   // (for example when a tracker in a third-party context uses window.open to
128   // open another origin where that second origin would be the granted origin.)
129   // But even in the second case, the type of the permission would still be
130   // formed by concatenating the granted origin to the end of the type name
131   // (see CreatePermissionKey).  Therefore, we pass in the same argument to
132   // both tracking origin and granted origin here in order to compute the
133   // shorter permission key and will then do a prefix match on the type of the
134   // input permission to see if it is a storage access permission or not.
135   nsAutoCString permissionKey;
136   bool result = CreateStoragePermissionKey(aPrincipal, permissionKey);
137   if (NS_WARN_IF(!result)) {
138     return false;
139   }
140 
141   nsAutoCString type;
142   nsresult rv = aPermission->GetType(type);
143   if (NS_WARN_IF(NS_FAILED(rv))) {
144     return false;
145   }
146 
147   return StringBeginsWith(type, permissionKey);
148 }
149 
150 // static
CheckStoragePermission(nsIPrincipal * aPrincipal,const nsAutoCString & aType,bool aIsInPrivateBrowsing,uint32_t * aRejectedReason,uint32_t aBlockedReason)151 bool AntiTrackingUtils::CheckStoragePermission(nsIPrincipal* aPrincipal,
152                                                const nsAutoCString& aType,
153                                                bool aIsInPrivateBrowsing,
154                                                uint32_t* aRejectedReason,
155                                                uint32_t aBlockedReason) {
156   PermissionManager* permManager = PermissionManager::GetInstance();
157   if (NS_WARN_IF(!permManager)) {
158     LOG(("Failed to obtain the permission manager"));
159     return false;
160   }
161 
162   uint32_t result = 0;
163   if (aIsInPrivateBrowsing) {
164     LOG_PRIN(("Querying the permissions for private modei looking for a "
165               "permission of type %s for %s",
166               aType.get(), _spec),
167              aPrincipal);
168     if (!permManager->PermissionAvailable(aPrincipal, aType)) {
169       LOG(
170           ("Permission isn't available for this principal in the current "
171            "process"));
172       return false;
173     }
174     nsTArray<RefPtr<nsIPermission>> permissions;
175     nsresult rv = permManager->GetAllForPrincipal(aPrincipal, permissions);
176     if (NS_WARN_IF(NS_FAILED(rv))) {
177       LOG(("Failed to get the list of permissions"));
178       return false;
179     }
180 
181     bool found = false;
182     for (const auto& permission : permissions) {
183       if (!permission) {
184         LOG(("Couldn't get the permission for unknown reasons"));
185         continue;
186       }
187 
188       nsAutoCString permissionType;
189       if (NS_SUCCEEDED(permission->GetType(permissionType)) &&
190           permissionType != aType) {
191         LOG(("Non-matching permission type: %s", aType.get()));
192         continue;
193       }
194 
195       uint32_t capability = 0;
196       if (NS_SUCCEEDED(permission->GetCapability(&capability)) &&
197           capability != nsIPermissionManager::ALLOW_ACTION) {
198         LOG(("Non-matching permission capability: %d", capability));
199         continue;
200       }
201 
202       uint32_t expirationType = 0;
203       if (NS_SUCCEEDED(permission->GetExpireType(&expirationType)) &&
204           expirationType != nsIPermissionManager ::EXPIRE_SESSION) {
205         LOG(("Non-matching permission expiration type: %d", expirationType));
206         continue;
207       }
208 
209       int64_t expirationTime = 0;
210       if (NS_SUCCEEDED(permission->GetExpireTime(&expirationTime)) &&
211           expirationTime != 0) {
212         LOG(("Non-matching permission expiration time: %" PRId64,
213              expirationTime));
214         continue;
215       }
216 
217       LOG(("Found a matching permission"));
218       found = true;
219       break;
220     }
221 
222     if (!found) {
223       if (aRejectedReason) {
224         *aRejectedReason = aBlockedReason;
225       }
226       return false;
227     }
228   } else {
229     nsresult rv = permManager->TestPermissionWithoutDefaultsFromPrincipal(
230         aPrincipal, aType, &result);
231     if (NS_WARN_IF(NS_FAILED(rv))) {
232       LOG(("Failed to test the permission"));
233       return false;
234     }
235 
236     LOG_PRIN(
237         ("Testing permission type %s for %s resulted in %d (%s)", aType.get(),
238          _spec, int(result),
239          result == nsIPermissionManager::ALLOW_ACTION ? "success" : "failure"),
240         aPrincipal);
241 
242     if (result != nsIPermissionManager::ALLOW_ACTION) {
243       if (aRejectedReason) {
244         *aRejectedReason = aBlockedReason;
245       }
246       return false;
247     }
248   }
249 
250   return true;
251 }
252 
HasStoragePermissionInParent(nsIChannel * aChannel)253 /* static */ bool AntiTrackingUtils::HasStoragePermissionInParent(
254     nsIChannel* aChannel) {
255   MOZ_ASSERT(aChannel);
256   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
257 
258   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
259   nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
260 
261   auto policyType = loadInfo->GetExternalContentPolicyType();
262 
263   // The channel is for the document load of the top-level window. The top-level
264   // window should always has 'hasStoragePermission' flag as false. So, we can
265   // return here directly.
266   if (policyType == nsIContentPolicy::TYPE_DOCUMENT) {
267     return false;
268   }
269 
270   nsresult rv =
271       loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
272   if (NS_WARN_IF(NS_FAILED(rv))) {
273     return false;
274   }
275 
276   int32_t cookieBehavior = cookieJarSettings->GetCookieBehavior();
277 
278   bool rejectForeignWithExceptions =
279       net::CookieJarSettings::IsRejectThirdPartyWithExceptions(cookieBehavior);
280 
281   // We only need to check the storage permission if the cookie behavior is
282   // BEHAVIOR_REJECT_TRACKER, BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN or
283   // BEHAVIOR_REJECT_FOREIGN with exceptions. Because ContentBlocking wouldn't
284   // update or check the storage permission if the cookie behavior is not
285   // belongs to these three.
286   if (!net::CookieJarSettings::IsRejectThirdPartyContexts(cookieBehavior)) {
287     return false;
288   }
289 
290   RefPtr<BrowsingContext> bc;
291   rv = loadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
292   if (NS_WARN_IF(NS_FAILED(rv)) || !bc) {
293     return false;
294   }
295 
296   uint64_t targetWindowId =
297       (cookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER ||
298        rejectForeignWithExceptions)
299           ? GetTopLevelStorageAreaWindowId(bc)
300           : GetTopLevelAntiTrackingWindowId(bc);
301   nsCOMPtr<nsIPrincipal> targetPrincipal;
302 
303   if (targetWindowId) {
304     RefPtr<WindowGlobalParent> wgp =
305         WindowGlobalParent::GetByInnerWindowId(targetWindowId);
306 
307     if (NS_WARN_IF(!wgp)) {
308       return false;
309     }
310 
311     targetPrincipal = wgp->DocumentPrincipal();
312   } else {
313     // We try to use the loading principal if there is no AntiTrackingWindowId.
314     targetPrincipal = loadInfo->GetLoadingPrincipal();
315   }
316 
317   if (!targetPrincipal) {
318     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
319 
320     if (httpChannel) {
321       // We don't have a loading principal, let's see if this is a document
322       // channel which belongs to a top-level window.
323       bool isDocument = false;
324       rv = httpChannel->GetIsMainDocumentChannel(&isDocument);
325       if (NS_SUCCEEDED(rv) && isDocument) {
326         nsIScriptSecurityManager* ssm =
327             nsScriptSecurityManager::GetScriptSecurityManager();
328         Unused << ssm->GetChannelResultPrincipal(
329             aChannel, getter_AddRefs(targetPrincipal));
330       }
331     }
332   }
333 
334   // Let's use the triggering principal if we still have nothing on the hand.
335   if (!targetPrincipal) {
336     targetPrincipal = loadInfo->TriggeringPrincipal();
337   }
338 
339   // Cannot get the target principal, bail out.
340   if (NS_WARN_IF(!targetPrincipal)) {
341     return false;
342   }
343 
344   nsCOMPtr<nsIURI> trackingURI;
345   rv = aChannel->GetURI(getter_AddRefs(trackingURI));
346   if (NS_WARN_IF(NS_FAILED(rv))) {
347     return false;
348   }
349 
350   nsAutoCString trackingOrigin;
351   rv = nsContentUtils::GetASCIIOrigin(trackingURI, trackingOrigin);
352   if (NS_WARN_IF(NS_FAILED(rv))) {
353     return false;
354   }
355 
356   nsAutoCString type;
357   AntiTrackingUtils::CreateStoragePermissionKey(trackingOrigin, type);
358 
359   uint32_t unusedReason = 0;
360 
361   return AntiTrackingUtils::CheckStoragePermission(
362       targetPrincipal, type, NS_UsePrivateBrowsing(aChannel), &unusedReason,
363       unusedReason);
364 }
365 
GetTopLevelAntiTrackingWindowId(BrowsingContext * aBrowsingContext)366 uint64_t AntiTrackingUtils::GetTopLevelAntiTrackingWindowId(
367     BrowsingContext* aBrowsingContext) {
368   MOZ_ASSERT(aBrowsingContext);
369 
370   RefPtr<WindowContext> winContext =
371       aBrowsingContext->GetCurrentWindowContext();
372   if (!winContext || winContext->GetCookieBehavior().isNothing()) {
373     return 0;
374   }
375 
376   // Do not check BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN her because when
377   // a third-party subresource is inside the main frame, we need to return the
378   // top-level window id to partition its cookies correctly.
379   uint32_t behavior = *winContext->GetCookieBehavior();
380   if (behavior == nsICookieService::BEHAVIOR_REJECT_TRACKER &&
381       aBrowsingContext->IsTop()) {
382     return 0;
383   }
384 
385   return aBrowsingContext->Top()->GetCurrentInnerWindowId();
386 }
387 
GetTopLevelStorageAreaWindowId(BrowsingContext * aBrowsingContext)388 uint64_t AntiTrackingUtils::GetTopLevelStorageAreaWindowId(
389     BrowsingContext* aBrowsingContext) {
390   MOZ_ASSERT(aBrowsingContext);
391 
392   if (Document::StorageAccessSandboxed(aBrowsingContext->GetSandboxFlags())) {
393     return 0;
394   }
395 
396   BrowsingContext* parentBC = aBrowsingContext->GetParent();
397   if (!parentBC) {
398     // No parent browsing context available!
399     return 0;
400   }
401 
402   if (!parentBC->IsTop()) {
403     return 0;
404   }
405 
406   return parentBC->GetCurrentInnerWindowId();
407 }
408 
409 /* static */
GetPrincipal(BrowsingContext * aBrowsingContext)410 already_AddRefed<nsIPrincipal> AntiTrackingUtils::GetPrincipal(
411     BrowsingContext* aBrowsingContext) {
412   MOZ_ASSERT(aBrowsingContext);
413 
414   nsCOMPtr<nsIPrincipal> principal;
415 
416   if (XRE_IsContentProcess()) {
417     // Passing an out-of-process browsing context in child processes to
418     // this API won't get any result, so just assert.
419     MOZ_ASSERT(aBrowsingContext->IsInProcess());
420 
421     nsPIDOMWindowOuter* outer = aBrowsingContext->GetDOMWindow();
422     if (NS_WARN_IF(!outer)) {
423       return nullptr;
424     }
425 
426     nsPIDOMWindowInner* inner = outer->GetCurrentInnerWindow();
427     if (NS_WARN_IF(!inner)) {
428       return nullptr;
429     }
430 
431     principal = nsGlobalWindowInner::Cast(inner)->GetPrincipal();
432   } else {
433     WindowGlobalParent* wgp =
434         aBrowsingContext->Canonical()->GetCurrentWindowGlobal();
435     if (NS_WARN_IF(!wgp)) {
436       return nullptr;
437     }
438 
439     principal = wgp->DocumentPrincipal();
440   }
441   return principal.forget();
442 }
443 
444 /* static */
GetPrincipalAndTrackingOrigin(BrowsingContext * aBrowsingContext,nsIPrincipal ** aPrincipal,nsACString & aTrackingOrigin)445 bool AntiTrackingUtils::GetPrincipalAndTrackingOrigin(
446     BrowsingContext* aBrowsingContext, nsIPrincipal** aPrincipal,
447     nsACString& aTrackingOrigin) {
448   MOZ_ASSERT(aBrowsingContext);
449 
450   // Passing an out-of-process browsing context in child processes to
451   // this API won't get any result, so just assert.
452   MOZ_ASSERT_IF(XRE_IsContentProcess(), aBrowsingContext->IsInProcess());
453 
454   // Let's take the principal and the origin of the tracker.
455   nsCOMPtr<nsIPrincipal> principal =
456       AntiTrackingUtils::GetPrincipal(aBrowsingContext);
457   if (NS_WARN_IF(!principal)) {
458     return false;
459   }
460 
461   nsresult rv = principal->GetOriginNoSuffix(aTrackingOrigin);
462   if (NS_WARN_IF(NS_FAILED(rv))) {
463     return false;
464   }
465 
466   if (aPrincipal) {
467     principal.forget(aPrincipal);
468   }
469 
470   return true;
471 };
472 
473 /* static */
IsFirstLevelSubContext(BrowsingContext * aBrowsingContext)474 bool AntiTrackingUtils::IsFirstLevelSubContext(
475     BrowsingContext* aBrowsingContext) {
476   MOZ_ASSERT(aBrowsingContext);
477 
478   RefPtr<BrowsingContext> parentBC = aBrowsingContext->GetParent();
479 
480   if (!parentBC) {
481     // No parent means it is the top.
482     return false;
483   }
484 
485   // We can know if it is first-level sub context by checking whether the
486   // parent is the top.
487   return parentBC->IsTopContent();
488 }
489 
490 /* static */
GetCookieBehavior(BrowsingContext * aBrowsingContext)491 uint32_t AntiTrackingUtils::GetCookieBehavior(
492     BrowsingContext* aBrowsingContext) {
493   MOZ_ASSERT(aBrowsingContext);
494 
495   RefPtr<dom::WindowContext> win = aBrowsingContext->GetCurrentWindowContext();
496   if (!win || win->GetCookieBehavior().isNothing()) {
497     return nsICookieService::BEHAVIOR_REJECT;
498   }
499 
500   return *win->GetCookieBehavior();
501 }
502 
503 /* static */
504 already_AddRefed<WindowGlobalParent>
GetTopWindowExcludingExtensionAccessibleContentFrames(CanonicalBrowsingContext * aBrowsingContext,nsIURI * aURIBeingLoaded)505 AntiTrackingUtils::GetTopWindowExcludingExtensionAccessibleContentFrames(
506     CanonicalBrowsingContext* aBrowsingContext, nsIURI* aURIBeingLoaded) {
507   MOZ_ASSERT(XRE_IsParentProcess());
508   MOZ_ASSERT(aBrowsingContext);
509 
510   CanonicalBrowsingContext* bc = aBrowsingContext;
511   RefPtr<WindowGlobalParent> prev;
512   while (RefPtr<WindowGlobalParent> parent = bc->GetParentWindowContext()) {
513     CanonicalBrowsingContext* parentBC = parent->BrowsingContext();
514 
515     nsIPrincipal* parentPrincipal = parent->DocumentPrincipal();
516     nsIURI* uri = prev ? prev->GetDocumentURI() : aURIBeingLoaded;
517 
518     // If the new parent has permission to load the current page, we're
519     // at a moz-extension:// frame which has a host permission that allows
520     // it to load the document that we've loaded.  In that case, stop at
521     // this frame and consider it the top-level frame.
522     if (uri &&
523         BasePrincipal::Cast(parentPrincipal)->AddonAllowsLoad(uri, true)) {
524       break;
525     }
526 
527     bc = parentBC;
528     prev = parent;
529   }
530   if (!prev) {
531     prev = bc->GetCurrentWindowGlobal();
532   }
533   return prev.forget();
534 }
535 
536 /* static */
ComputeIsThirdPartyToTopWindow(nsIChannel * aChannel)537 void AntiTrackingUtils::ComputeIsThirdPartyToTopWindow(nsIChannel* aChannel) {
538   MOZ_ASSERT(aChannel);
539   MOZ_ASSERT(XRE_IsParentProcess());
540 
541   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
542   RefPtr<BrowsingContext> bc;
543   loadInfo->GetBrowsingContext(getter_AddRefs(bc));
544 
545   // In xpcshell-tests we don't always have a browsingContext.
546   if (!bc) {
547     return;
548   }
549 
550   nsCOMPtr<nsIURI> uri;
551   Unused << aChannel->GetURI(getter_AddRefs(uri));
552 
553   RefPtr<WindowGlobalParent> topWindow =
554       GetTopWindowExcludingExtensionAccessibleContentFrames(bc->Canonical(),
555                                                             uri);
556 
557   if (NS_WARN_IF(!topWindow)) {
558     return;
559   }
560 
561   nsCOMPtr<nsIPrincipal> topWindowPrincipal = topWindow->DocumentPrincipal();
562   if (topWindowPrincipal && !topWindowPrincipal->GetIsNullPrincipal()) {
563     auto* basePrin = BasePrincipal::Cast(topWindowPrincipal);
564     bool isThirdParty = true;
565     basePrin->IsThirdPartyURI(uri, &isThirdParty);
566 
567     loadInfo->SetIsThirdPartyContextToTopWindow(isThirdParty);
568   }
569 }
570 
571 /* static */
IsThirdPartyChannel(nsIChannel * aChannel)572 bool AntiTrackingUtils::IsThirdPartyChannel(nsIChannel* aChannel) {
573   MOZ_ASSERT(aChannel);
574 
575   // We assume that the channel is a third-party by default.
576   bool thirdParty = true;
577 
578   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
579   if (!thirdPartyUtil) {
580     return thirdParty;
581   }
582 
583   // Check that if the channel is a third-party to its parent.
584   nsresult rv =
585       thirdPartyUtil->IsThirdPartyChannel(aChannel, nullptr, &thirdParty);
586   if (NS_FAILED(rv)) {
587     // Assume third-party in case of failure
588     thirdParty = true;
589   }
590 
591   // We check the top-level window to prevent the top-level navigation from
592   // being detected as third-party.
593   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
594   return thirdParty && loadInfo->GetIsThirdPartyContextToTopWindow();
595 }
596 
597 /* static */
IsThirdPartyWindow(nsPIDOMWindowInner * aWindow,nsIURI * aURI)598 bool AntiTrackingUtils::IsThirdPartyWindow(nsPIDOMWindowInner* aWindow,
599                                            nsIURI* aURI) {
600   MOZ_ASSERT(aWindow);
601   MOZ_ASSERT(aURI);
602 
603   // We assume that the window is foreign to the URI by default.
604   bool thirdParty = true;
605 
606   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
607   Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(), aURI,
608                                                &thirdParty);
609 
610   return thirdParty;
611 }
612