Bug 1616775 - P6. Add OnAllowAccessFor to process tasks that need a parent window. r=timhuang,baku

Differential Revision: https://phabricator.services.mozilla.com/D71015
This commit is contained in:
Dimi Lee 2020-04-23 14:25:31 +00:00
Родитель 456ce68f60
Коммит ae0eb1b968
5 изменённых файлов: 111 добавлений и 39 удалений

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/BackgroundHangMonitor.h" #include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/BenchmarkStorageChild.h" #include "mozilla/BenchmarkStorageChild.h"
#include "mozilla/ContentBlocking.h"
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#include "mozilla/MemoryTelemetry.h" #include "mozilla/MemoryTelemetry.h"
#include "mozilla/NullPrincipal.h" #include "mozilla/NullPrincipal.h"
@ -3575,6 +3576,18 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSHEntriesInDocShell(
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
const MaybeDiscarded<BrowsingContext>& aContext,
const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
const ContentBlockingNotifier::StorageAccessGrantedReason& aReason) {
MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
ContentBlocking::OnAllowAccessFor(aContext.GetMaybeDiscarded(),
aTrackingOrigin, aCookieBehavior, aReason);
return IPC_OK();
}
void ContentChild::OnChannelReceivedMessage(const Message& aMsg) { void ContentChild::OnChannelReceivedMessage(const Message& aMsg) {
if (aMsg.is_sync() && !aMsg.is_reply()) { if (aMsg.is_sync() && !aMsg.is_reply()) {
LSObject::OnSyncMessageReceived(); LSObject::OnSyncMessageReceived();

Просмотреть файл

@ -673,6 +673,11 @@ class ContentChild final
CrossProcessSHEntry* aOldEntry, CrossProcessSHEntry* aNewEntry, CrossProcessSHEntry* aOldEntry, CrossProcessSHEntry* aNewEntry,
const MaybeDiscarded<BrowsingContext>& aContext); const MaybeDiscarded<BrowsingContext>& aContext);
mozilla::ipc::IPCResult RecvOnAllowAccessFor(
const MaybeDiscarded<BrowsingContext>& aContext,
const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
const ContentBlockingNotifier::StorageAccessGrantedReason& aReason);
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
// Fetch the current number of pending input events. // Fetch the current number of pending input events.
// //

Просмотреть файл

@ -851,6 +851,11 @@ child:
CrossProcessSHEntry aNewEntry, CrossProcessSHEntry aNewEntry,
MaybeDiscardedBrowsingContext aContext); MaybeDiscardedBrowsingContext aContext);
async OnAllowAccessFor(MaybeDiscardedBrowsingContext aParentContext,
nsCString aTrackingOrigin,
uint32_t aCookieBehavior,
StorageAccessGrantedReason aReason);
parent: parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint); async InitBackground(Endpoint<PBackgroundParent> aEndpoint);

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/ContentBlockingUserInteraction.h" #include "mozilla/ContentBlockingUserInteraction.h"
#include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowContext.h"
#include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/net/CookieJarSettings.h" #include "mozilla/net/CookieJarSettings.h"
@ -340,14 +341,24 @@ ContentBlocking::AllowAccessFor(
ContentChild* cc = ContentChild::GetSingleton(); ContentChild* cc = ContentChild::GetSingleton();
MOZ_ASSERT(cc); MOZ_ASSERT(cc);
RefPtr<BrowsingContext> bc = aParentContext;
return cc return cc
->SendCompleteAllowAccessFor(aParentContext, topLevelWindowId, ->SendCompleteAllowAccessFor(aParentContext, topLevelWindowId,
IPC::Principal(trackingPrincipal), IPC::Principal(trackingPrincipal),
trackingOrigin, behavior, aReason) trackingOrigin, behavior, aReason)
->Then(GetCurrentThreadSerialEventTarget(), __func__, ->Then(GetCurrentThreadSerialEventTarget(), __func__,
[](const ContentChild::CompleteAllowAccessForPromise:: [bc, trackingOrigin, behavior,
ResolveOrRejectValue& aValue) { aReason](const ContentChild::CompleteAllowAccessForPromise::
ResolveOrRejectValue& aValue) {
if (aValue.IsResolve() && aValue.ResolveValue().isSome()) { if (aValue.IsResolve() && aValue.ResolveValue().isSome()) {
// we don't call OnAllowAccessFor in the parent when this is
// triggered by the opener heuristic, so we have to do it here.
// See storePermission below for the reason.
if (aReason == ContentBlockingNotifier::eOpener) {
MOZ_ASSERT(bc->IsInProcess());
ContentBlocking::OnAllowAccessFor(bc, trackingOrigin,
behavior, aReason);
}
return StorageAccessGrantPromise::CreateAndResolve( return StorageAccessGrantPromise::CreateAndResolve(
aValue.ResolveValue().value(), __func__); aValue.ResolveValue().value(), __func__);
} }
@ -456,45 +467,28 @@ ContentBlocking::CompleteAllowAccessFor(
return StorageAccessGrantPromise::CreateAndReject(false, __func__); return StorageAccessGrantPromise::CreateAndReject(false, __func__);
} }
// Check if we can get top-level outer/inner window when we still
// have a chance to report an error.
nsCOMPtr<nsPIDOMWindowOuter> topOuterWindow =
AntiTrackingUtils::GetTopWindow(parentInnerWindow);
if (!topOuterWindow) {
LOG(("Couldn't get the top window"));
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
}
nsCOMPtr<nsPIDOMWindowInner> topInnerWindow =
topOuterWindow->GetCurrentInnerWindow();
if (NS_WARN_IF(!topInnerWindow)) {
LOG(("No top inner window."));
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
}
auto storePermission = auto storePermission =
[parentInnerWindow, topInnerWindow, trackingOrigin, trackingPrincipal, [aParentContext, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
aReason, aCookieBehavior, aCookieBehavior,
aTopLevelWindowId](int aAllowMode) -> RefPtr<StorageAccessGrantPromise> { aReason](int aAllowMode) -> RefPtr<StorageAccessGrantPromise> {
nsAutoCString permissionKey; // Inform the window we granted permission for. This has to be done in the
AntiTrackingUtils::CreateStoragePermissionKey(trackingOrigin, // window's process.
permissionKey); if (aParentContext->IsInProcess()) {
ContentBlocking::OnAllowAccessFor(aParentContext, trackingOrigin,
aCookieBehavior, aReason);
} else {
MOZ_ASSERT(XRE_IsParentProcess());
// Let's store the permission in the current parent window. // We don't have the window, send an IPC to the content process that
topInnerWindow->SaveStorageAccessGranted(permissionKey); // owns the parent window. But there is a special case, for window.open,
// we'll return to the content process we need to inform when this
// Let's inform the parent window. // function is done. So we don't need to create an extra IPC for the case.
nsGlobalWindowInner::Cast(parentInnerWindow)->StorageAccessGranted(); if (aReason != ContentBlockingNotifier::eOpener) {
ContentParent* cp = aParentContext->Canonical()->GetContentParent();
ContentBlockingNotifier::OnEvent( Unused << cp->SendOnAllowAccessFor(aParentContext, trackingOrigin,
parentInnerWindow->GetExtantDoc()->GetChannel(), false, aCookieBehavior, aReason);
CookieJarSettings::IsRejectThirdPartyWithExceptions(aCookieBehavior) }
? nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN }
: nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER,
trackingOrigin, Some(aReason));
ContentBlockingNotifier::ReportUnblockingToConsole(
parentInnerWindow, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get())); LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get()));
@ -553,6 +547,54 @@ ContentBlocking::CompleteAllowAccessFor(
return storePermission(false); return storePermission(false);
} }
/* static */ void ContentBlocking::OnAllowAccessFor(
dom::BrowsingContext* aParentContext, const nsCString& aTrackingOrigin,
uint32_t aCookieBehavior,
ContentBlockingNotifier::StorageAccessGrantedReason aReason) {
MOZ_ASSERT(aParentContext->IsInProcess());
nsCOMPtr<nsPIDOMWindowInner> parentInner =
aParentContext->GetDOMWindow()->GetCurrentInnerWindow();
// TODO: This is not fission-compatible, will be fixed in another patch.
nsCOMPtr<nsPIDOMWindowOuter> topOuterWindow =
AntiTrackingUtils::GetTopWindow(parentInner);
if (!topOuterWindow) {
return;
}
nsCOMPtr<nsPIDOMWindowInner> topInnerWindow =
topOuterWindow->GetCurrentInnerWindow();
if (!topInnerWindow) {
return;
}
nsAutoCString permissionKey;
AntiTrackingUtils::CreateStoragePermissionKey(aTrackingOrigin, permissionKey);
// Let's store the permission in the current parent window.
topInnerWindow->SaveStorageAccessGranted(permissionKey);
// Let's inform the parent window.
nsGlobalWindowInner::Cast(parentInner)->StorageAccessGranted();
// Theoratically this can be done in the parent process. But right now,
// we need the channel while notifying content blocking events, and
// we don't have a trivial way to obtain the channel in the parent
// via BrowsingContext. So we just ask the child to do the work.
ContentBlockingNotifier::OnEvent(
parentInner->GetExtantDoc()->GetChannel(), false,
CookieJarSettings::IsRejectThirdPartyWithExceptions(aCookieBehavior)
? nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN
: nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER,
aTrackingOrigin, Some(aReason));
// TODO: When Bug 1611755 is done, we can remove reporting console
// from here and report it directly in the parent.
ContentBlockingNotifier::ReportUnblockingToConsole(
parentInner, NS_ConvertUTF8toUTF16(aTrackingOrigin), aReason);
}
/* static */ /* static */
RefPtr<mozilla::ContentBlocking::ParentAccessGrantPromise> RefPtr<mozilla::ContentBlocking::ParentAccessGrantPromise>
ContentBlocking::SaveAccessForOriginOnParentProcess( ContentBlocking::SaveAccessForOriginOnParentProcess(

Просмотреть файл

@ -95,6 +95,13 @@ class ContentBlocking final {
ContentBlockingNotifier::StorageAccessGrantedReason aReason, ContentBlockingNotifier::StorageAccessGrantedReason aReason,
const PerformFinalChecks& aPerformFinalChecks = nullptr); const PerformFinalChecks& aPerformFinalChecks = nullptr);
// This function handles tasks that have to be done in the process
// of the window that we just grant permission for.
static void OnAllowAccessFor(
dom::BrowsingContext* aParentContext, const nsCString& aTrackingOrigin,
uint32_t aCookieBehavior,
ContentBlockingNotifier::StorageAccessGrantedReason aReason);
// For IPC only. // For IPC only.
typedef MozPromise<nsresult, bool, true> ParentAccessGrantPromise; typedef MozPromise<nsresult, bool, true> ParentAccessGrantPromise;
static RefPtr<ParentAccessGrantPromise> SaveAccessForOriginOnParentProcess( static RefPtr<ParentAccessGrantPromise> SaveAccessForOriginOnParentProcess(