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