Bug 1612147 - Don't store FeaturePolicy in BrowsingContext. r=smaug

Syncing the container FeaturePolicy across BrowsingContext is actually
a bit more heavy-handed than necessary. We only ever need a container
FeaturePolicy when inheriting a FeaturePolicy in exactly the document
the container contains. Not every process that the tree the container
is a part of. So instead of storing a FeaturePolicy in a synced field,
we manually send it to the correct WindowGlobalChild (which
corresponds to a document) and retrieve it from there.

Differential Revision: https://phabricator.services.mozilla.com/D61479
This commit is contained in:
Andreas Farre 2021-01-14 11:15:24 +00:00
parent 83df9df213
commit 78e800dabe
15 changed files with 94 additions and 46 deletions

View File

@ -27,7 +27,6 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FeaturePolicyUtils.h"
#include "mozilla/dom/HTMLEmbedElement.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/Location.h"

View File

@ -16,7 +16,6 @@
#include "mozilla/Span.h"
#include "mozilla/Tuple.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "mozilla/dom/LocationBase.h"
#include "mozilla/dom/MaybeDiscarded.h"
#include "mozilla/dom/UserActivation.h"
@ -120,7 +119,6 @@ enum class ExplicitActiveStatus : uint8_t {
/* Hold the audio muted state and should be used on top level browsing \
* contexts only */ \
FIELD(Muted, bool) \
FIELD(FeaturePolicy, RefPtr<mozilla::dom::FeaturePolicy>) \
/* See nsSandboxFlags.h for the possible flags. */ \
FIELD(SandboxFlags, uint32_t) \
FIELD(InitialSandboxFlags, uint32_t) \

View File

@ -1663,6 +1663,15 @@ void CanonicalBrowsingContext::ResetScalingZoom() {
}
}
void CanonicalBrowsingContext::SetContainerFeaturePolicy(
FeaturePolicy* aContainerFeaturePolicy) {
mContainerFeaturePolicy = aContainerFeaturePolicy;
if (WindowGlobalParent* current = GetCurrentWindowGlobal()) {
Unused << current->SendSetContainerFeaturePolicy(mContainerFeaturePolicy);
}
}
void CanonicalBrowsingContext::SetCrossGroupOpenerId(uint64_t aOpenerId) {
MOZ_DIAGNOSTIC_ASSERT(IsTopContent());
MOZ_DIAGNOSTIC_ASSERT(mCrossGroupOpenerId == 0,
@ -1671,7 +1680,7 @@ void CanonicalBrowsingContext::SetCrossGroupOpenerId(uint64_t aOpenerId) {
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(CanonicalBrowsingContext, BrowsingContext,
mSessionHistory)
mSessionHistory, mContainerFeaturePolicy)
NS_IMPL_ADDREF_INHERITED(CanonicalBrowsingContext, BrowsingContext)
NS_IMPL_RELEASE_INHERITED(CanonicalBrowsingContext, BrowsingContext)

View File

@ -37,6 +37,7 @@ class DocumentLoadListener;
namespace dom {
class BrowserParent;
class FeaturePolicy;
struct LoadURIOptions;
class MediaController;
struct LoadingSessionHistoryInfo;
@ -263,6 +264,11 @@ class CanonicalBrowsingContext final : public BrowsingContext {
void ResetScalingZoom();
void SetContainerFeaturePolicy(FeaturePolicy* aContainerFeaturePolicy);
FeaturePolicy* GetContainerFeaturePolicy() const {
return mContainerFeaturePolicy;
}
protected:
// Called when the browsing context is being discarded.
void CanonicalDiscard();
@ -367,6 +373,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<nsSecureBrowserUI> mSecureBrowserUI;
RefPtr<BrowsingContextWebProgress> mWebProgress;
RefPtr<nsBrowserStatusFilter> mStatusFilter;
RefPtr<FeaturePolicy> mContainerFeaturePolicy;
};
} // namespace dom

View File

@ -81,6 +81,13 @@ Document* WindowContext::GetExtantDoc() const {
return innerWindow ? innerWindow->GetExtantDoc() : nullptr;
}
WindowGlobalChild* WindowContext::GetWindowGlobalChild() const {
MOZ_ASSERT(XRE_IsContentProcess());
NS_ENSURE_TRUE(XRE_IsContentProcess(), nullptr);
nsGlobalWindowInner* innerWindow = GetInnerWindow();
return innerWindow ? innerWindow->GetWindowGlobalChild() : nullptr;
}
WindowContext* WindowContext::GetParentWindowContext() {
return mBrowsingContext->GetParentWindowContext();
}

View File

@ -24,6 +24,7 @@ class LogModule;
namespace dom {
class WindowGlobalChild;
class WindowGlobalParent;
class WindowGlobalInit;
class BrowsingContext;
@ -112,6 +113,8 @@ class WindowContext : public nsISupports, public nsWrapperCache {
Document* GetDocument() const;
Document* GetExtantDoc() const;
WindowGlobalChild* GetWindowGlobalChild() const;
// Get the parent WindowContext of this WindowContext, taking the BFCache into
// account. This will not cross chrome/content <browser> boundaries.
WindowContext* GetParentWindowContext();

View File

@ -3711,36 +3711,27 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
}
already_AddRefed<dom::FeaturePolicy> Document::GetParentFeaturePolicy() {
if (!mDocumentContainer) {
return nullptr;
BrowsingContext* browsingContext = GetBrowsingContext();
NS_ENSURE_TRUE(browsingContext, nullptr);
NS_ENSURE_TRUE(browsingContext->IsContentSubframe(), nullptr);
HTMLIFrameElement* iframe =
HTMLIFrameElement::FromNodeOrNull(browsingContext->GetEmbedderElement());
if (iframe) {
return do_AddRef(iframe->FeaturePolicy());
}
nsPIDOMWindowOuter* containerWindow = mDocumentContainer->GetWindow();
if (!containerWindow) {
return nullptr;
if (XRE_IsParentProcess()) {
return do_AddRef(browsingContext->Canonical()->GetContainerFeaturePolicy());
}
BrowsingContext* context = containerWindow->GetBrowsingContext();
if (!context) {
return nullptr;
}
WindowContext* windowContext = browsingContext->GetCurrentWindowContext();
NS_ENSURE_TRUE(windowContext, nullptr);
RefPtr<dom::FeaturePolicy> parentPolicy;
if (context->IsContentSubframe() && !context->GetParent()->IsInProcess()) {
// We are in cross process, so try to get feature policy from
// container's BrowsingContext
parentPolicy = context->GetFeaturePolicy();
return parentPolicy.forget();
}
WindowGlobalChild* child = windowContext->GetWindowGlobalChild();
NS_ENSURE_TRUE(child, nullptr);
nsCOMPtr<nsINode> node = containerWindow->GetFrameElementInternal();
HTMLIFrameElement* iframe = HTMLIFrameElement::FromNodeOrNull(node);
if (!iframe) {
return nullptr;
}
parentPolicy = iframe->FeaturePolicy();
return parentPolicy.forget();
return do_AddRef(child->GetContainerFeaturePolicy());
}
nsresult Document::InitFeaturePolicy(nsIChannel* aChannel) {

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLIFrameElementBinding.h"
#include "mozilla/dom/FeaturePolicy.h"
@ -234,24 +235,10 @@ void HTMLIFrameElement::MaybeStoreCrossOriginFeaturePolicy() {
return;
}
// If we are in subframe cross origin, store the featurePolicy to
// browsingContext
nsPIDOMWindowOuter* topWindow = browsingContext->Top()->GetDOMWindow();
if (NS_WARN_IF(!topWindow)) {
return;
if (ContentChild* cc = ContentChild::GetSingleton()) {
Unused << cc->SendSetContainerFeaturePolicy(browsingContext,
mFeaturePolicy);
}
Document* topLevelDocument = topWindow->GetExtantDoc();
if (NS_WARN_IF(!topLevelDocument)) {
return;
}
if (!NS_SUCCEEDED(nsContentUtils::CheckSameOrigin(topLevelDocument, this))) {
return;
}
// Return value of setting synced field should be checked. See bug 1656492.
Unused << browsingContext->SetFeaturePolicy(mFeaturePolicy);
}
already_AddRefed<nsIPrincipal>

View File

@ -7310,6 +7310,19 @@ IPCResult ContentParent::RecvFOGData(ByteBuf&& buf) {
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetContainerFeaturePolicy(
const MaybeDiscardedBrowsingContext& aContainerContext,
FeaturePolicy* aContainerFeaturePolicy) {
if (aContainerContext.IsNullOrDiscarded()) {
return IPC_OK();
}
auto* context = aContainerContext.get_canonical();
context->SetContainerFeaturePolicy(aContainerFeaturePolicy);
return IPC_OK();
}
NS_IMETHODIMP ContentParent::GetCanSend(bool* aCanSend) {
*aCanSend = CanSend();
return NS_OK;

View File

@ -1411,6 +1411,10 @@ class ContentParent final
mozilla::ipc::IPCResult RecvFOGData(ByteBuf&& buf);
mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy(
const MaybeDiscardedBrowsingContext& aContainerContext,
FeaturePolicy* aContainerFeaturePolicy);
public:
void SendGetFilesResponseAndForget(const nsID& aID,
const GetFilesResponseResult& aResult);

View File

@ -76,6 +76,7 @@ include "mozilla/GfxMessageUtils.h";
include "mozilla/dom/BindingIPCUtils.h";
include "mozilla/dom/CSPMessageUtils.h";
include "mozilla/dom/DocShellMessageUtils.h";
include "mozilla/dom/FeaturePolicyUtils.h";
include "mozilla/dom/MediaSessionIPCUtils.h";
include "mozilla/dom/ReferrerInfoUtils.h";
include "mozilla/ipc/ByteBufUtils.h";
@ -148,6 +149,7 @@ using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHi
using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
using mozilla::RemoteDecodeIn from "mozilla/RemoteDecoderManagerChild.h";
using mozilla::dom::PerformanceTimingData from "mozilla/dom/PerformanceTiming.h";
using refcounted mozilla::dom::FeaturePolicy from "mozilla/dom/FeaturePolicy.h";
union ChromeRegistryItem
{
@ -1853,6 +1855,10 @@ child:
// Tells the child to flush any pending data. Used in tests and ping
// assembly. Buffer contains bincoded Rust structs.
async FlushFOGData() returns (ByteBuf buf);
parent:
async SetContainerFeaturePolicy(MaybeDiscardedBrowsingContext aContainerContext,
FeaturePolicy aContainerFeaturePolicy);
};
}

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include "mozilla/dom/DocShellMessageUtils.h";
include "mozilla/dom/FeaturePolicyUtils.h";
include "mozilla/dom/PermissionMessageUtils.h";
include "mozilla/ipc/TransportSecurityInfoUtils.h";
include "mozilla/ipc/URIUtils.h";
@ -30,6 +31,7 @@ using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
using refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h";
using mozilla::UseCounters from "mozilla/UseCounter.h";
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
using refcounted mozilla::dom::FeaturePolicy from "mozilla/dom/FeaturePolicy.h";
namespace mozilla {
namespace dom {
@ -86,6 +88,8 @@ child:
*/
async ResetScalingZoom();
async SetContainerFeaturePolicy(FeaturePolicy aContainerFeaturePolicy);
both:
async RawMessage(JSActorMessageMeta aMetadata, ClonedMessageData? aData,
ClonedMessageData? aStack);

View File

@ -554,6 +554,12 @@ mozilla::ipc::IPCResult WindowGlobalChild::RecvResetScalingZoom() {
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalChild::RecvSetContainerFeaturePolicy(
dom::FeaturePolicy* aContainerFeaturePolicy) {
mContainerFeaturePolicy = aContainerFeaturePolicy;
return IPC_OK();
}
IPCResult WindowGlobalChild::RecvRawMessage(
const JSActorMessageMeta& aMeta, const Maybe<ClonedMessageData>& aData,
const Maybe<ClonedMessageData>& aStack) {
@ -680,7 +686,8 @@ void WindowGlobalChild::MaybeSendUpdateDocumentWouldPreloadResources() {
}
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WindowGlobalChild, mWindowGlobal)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WindowGlobalChild, mWindowGlobal,
mContainerFeaturePolicy)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalChild)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -20,6 +20,7 @@ namespace mozilla {
namespace dom {
class BrowsingContext;
class FeaturePolicy;
class WindowContext;
class WindowGlobalParent;
class JSWindowActorChild;
@ -123,6 +124,10 @@ class WindowGlobalChild final : public WindowGlobalActor,
void MaybeSendUpdateDocumentWouldPreloadResources();
dom::FeaturePolicy* GetContainerFeaturePolicy() const {
return mContainerFeaturePolicy;
}
protected:
const nsACString& GetRemoteType() override;
@ -164,6 +169,9 @@ class WindowGlobalChild final : public WindowGlobalActor,
mozilla::ipc::IPCResult RecvResetScalingZoom();
mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy(
dom::FeaturePolicy* aContainerFeaturePolicy);
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
private:
@ -175,6 +183,7 @@ class WindowGlobalChild final : public WindowGlobalActor,
RefPtr<nsGlobalWindowInner> mWindowGlobal;
RefPtr<dom::WindowContext> mWindowContext;
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
RefPtr<dom::FeaturePolicy> mContainerFeaturePolicy;
nsCOMPtr<nsIURI> mDocumentURI;
int64_t mBeforeUnloadListeners = 0;
bool mDocumentWouldPreloadResources = false;

View File

@ -150,6 +150,9 @@ void WindowGlobalParent::Init() {
if (!BrowsingContext()->IsDiscarded()) {
MOZ_ALWAYS_SUCCEEDS(
BrowsingContext()->SetCurrentInnerWindowId(InnerWindowId()));
Unused << SendSetContainerFeaturePolicy(
BrowsingContext()->GetContainerFeaturePolicy());
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();