mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
2536630f8b
Differential Revision: https://phabricator.services.mozilla.com/D172271
400 lines
17 KiB
C++
400 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_dom_WindowContext_h
|
|
#define mozilla_dom_WindowContext_h
|
|
|
|
#include "mozilla/PermissionDelegateHandler.h"
|
|
#include "mozilla/WeakPtr.h"
|
|
#include "mozilla/Span.h"
|
|
#include "mozilla/dom/MaybeDiscarded.h"
|
|
#include "mozilla/dom/SyncedContext.h"
|
|
#include "mozilla/dom/UserActivation.h"
|
|
#include "nsDOMNavigationTiming.h"
|
|
#include "nsILoadInfo.h"
|
|
#include "nsWrapperCache.h"
|
|
|
|
class nsIGlobalObject;
|
|
|
|
class nsGlobalWindowInner;
|
|
|
|
namespace mozilla {
|
|
class LogModule;
|
|
|
|
namespace dom {
|
|
|
|
class WindowGlobalChild;
|
|
class WindowGlobalParent;
|
|
class WindowGlobalInit;
|
|
class BrowsingContext;
|
|
class BrowsingContextGroup;
|
|
|
|
#define MOZ_EACH_WC_FIELD(FIELD) \
|
|
/* Whether the SHEntry associated with the current top-level \
|
|
* window has already seen user interaction. \
|
|
* As such, this will be reset to false when a new SHEntry is \
|
|
* created without changing the WC (e.g. when using pushState or \
|
|
* sub-frame navigation) \
|
|
* This flag is set for optimization purposes, to avoid \
|
|
* having to get the top SHEntry and update it on every \
|
|
* user interaction. \
|
|
* This is only meaningful on the top-level WC. */ \
|
|
FIELD(SHEntryHasUserInteraction, bool) \
|
|
FIELD(CookieBehavior, Maybe<uint32_t>) \
|
|
FIELD(IsOnContentBlockingAllowList, bool) \
|
|
/* Whether the given window hierarchy is third party. See \
|
|
* ThirdPartyUtil::IsThirdPartyWindow for details */ \
|
|
FIELD(IsThirdPartyWindow, bool) \
|
|
/* Whether this window's channel has been marked as a third-party \
|
|
* tracking resource */ \
|
|
FIELD(IsThirdPartyTrackingResourceWindow, bool) \
|
|
FIELD(ShouldResistFingerprinting, bool) \
|
|
FIELD(IsSecureContext, bool) \
|
|
FIELD(IsOriginalFrameSource, bool) \
|
|
/* Mixed-Content: If the corresponding documentURI is https, \
|
|
* then this flag is true. */ \
|
|
FIELD(IsSecure, bool) \
|
|
/* Whether the user has overriden the mixed content blocker to allow \
|
|
* mixed content loads to happen */ \
|
|
FIELD(AllowMixedContent, bool) \
|
|
/* Whether this window has registered a "beforeunload" event \
|
|
* handler */ \
|
|
FIELD(HasBeforeUnload, bool) \
|
|
/* Controls whether the WindowContext is currently considered to be \
|
|
* activated by a gesture */ \
|
|
FIELD(UserActivationState, UserActivation::State) \
|
|
FIELD(EmbedderPolicy, nsILoadInfo::CrossOriginEmbedderPolicy) \
|
|
/* True if this document tree contained at least a HTMLMediaElement. \
|
|
* This should only be set on top level context. */ \
|
|
FIELD(DocTreeHadMedia, bool) \
|
|
FIELD(AutoplayPermission, uint32_t) \
|
|
FIELD(ShortcutsPermission, uint32_t) \
|
|
/* Store the Id of the browsing context where active media session \
|
|
* exists on the top level window context */ \
|
|
FIELD(ActiveMediaSessionContextId, Maybe<uint64_t>) \
|
|
/* ALLOW_ACTION if it is allowed to open popups for the sub-tree \
|
|
* starting and including the current WindowContext */ \
|
|
FIELD(PopupPermission, uint32_t) \
|
|
FIELD(DelegatedPermissions, \
|
|
PermissionDelegateHandler::DelegatedPermissionList) \
|
|
FIELD(DelegatedExactHostMatchPermissions, \
|
|
PermissionDelegateHandler::DelegatedPermissionList) \
|
|
FIELD(HasReportedShadowDOMUsage, bool) \
|
|
/* Whether the principal of this window is for a local \
|
|
* IP address */ \
|
|
FIELD(IsLocalIP, bool) \
|
|
/* Whether any of the windows in the subtree rooted at this window has \
|
|
* active peer connections or not (only set on the top window). */ \
|
|
FIELD(HasActivePeerConnections, bool) \
|
|
/* Whether we can execute scripts in this WindowContext. Has no effect \
|
|
* unless scripts are also allowed in the BrowsingContext. */ \
|
|
FIELD(AllowJavascript, bool) \
|
|
/* If this field is `true`, it means that this WindowContext's \
|
|
* WindowState was saved to be stored in the legacy (non-SHIP) BFCache \
|
|
* implementation. Always false for SHIP */ \
|
|
FIELD(WindowStateSaved, bool)
|
|
|
|
class WindowContext : public nsISupports, public nsWrapperCache {
|
|
MOZ_DECL_SYNCED_CONTEXT(WindowContext, MOZ_EACH_WC_FIELD)
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WindowContext)
|
|
|
|
public:
|
|
static already_AddRefed<WindowContext> GetById(uint64_t aInnerWindowId);
|
|
static LogModule* GetLog();
|
|
static LogModule* GetSyncLog();
|
|
|
|
BrowsingContext* GetBrowsingContext() const { return mBrowsingContext; }
|
|
BrowsingContextGroup* Group() const;
|
|
uint64_t Id() const { return InnerWindowId(); }
|
|
uint64_t InnerWindowId() const { return mInnerWindowId; }
|
|
uint64_t OuterWindowId() const { return mOuterWindowId; }
|
|
bool IsDiscarded() const { return mIsDiscarded; }
|
|
|
|
// Returns `true` if this WindowContext is the current WindowContext in its
|
|
// BrowsingContext.
|
|
bool IsCurrent() const;
|
|
|
|
// Returns `true` if this WindowContext is currently in the BFCache.
|
|
bool IsInBFCache();
|
|
|
|
bool IsInProcess() const { return mIsInProcess; }
|
|
|
|
bool HasBeforeUnload() const { return GetHasBeforeUnload(); }
|
|
|
|
bool IsLocalIP() const { return GetIsLocalIP(); }
|
|
|
|
bool ShouldResistFingerprinting() const {
|
|
return GetShouldResistFingerprinting();
|
|
}
|
|
|
|
nsGlobalWindowInner* GetInnerWindow() const;
|
|
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();
|
|
WindowContext* TopWindowContext();
|
|
|
|
bool SameOriginWithTop() const;
|
|
|
|
bool IsTop() const;
|
|
|
|
Span<RefPtr<BrowsingContext>> Children() { return mChildren; }
|
|
|
|
// The filtered version of `Children()`, which contains no browsing contexts
|
|
// for synthetic documents as created by object loading content.
|
|
Span<RefPtr<BrowsingContext>> NonSyntheticChildren() {
|
|
return mNonSyntheticChildren;
|
|
}
|
|
|
|
// Cast this object to it's parent-process canonical form.
|
|
WindowGlobalParent* Canonical();
|
|
|
|
nsIGlobalObject* GetParentObject() const;
|
|
JSObject* WrapObject(JSContext* cx,
|
|
JS::Handle<JSObject*> aGivenProto) override;
|
|
|
|
void Discard();
|
|
|
|
struct IPCInitializer {
|
|
uint64_t mInnerWindowId;
|
|
uint64_t mOuterWindowId;
|
|
uint64_t mBrowsingContextId;
|
|
|
|
FieldValues mFields;
|
|
};
|
|
IPCInitializer GetIPCInitializer();
|
|
|
|
static void CreateFromIPC(IPCInitializer&& aInit);
|
|
|
|
// Add new security state flags.
|
|
// These should be some of the nsIWebProgressListener 'HTTPS_ONLY_MODE' or
|
|
// 'MIXED' state flags, and should only be called on the top window context.
|
|
void AddSecurityState(uint32_t aStateFlags);
|
|
|
|
// This function would be called when its corresponding window is activated
|
|
// by user gesture.
|
|
void NotifyUserGestureActivation();
|
|
|
|
// This function would be called when we want to reset the user gesture
|
|
// activation flag.
|
|
void NotifyResetUserGestureActivation();
|
|
|
|
// Return true if its corresponding window has been activated by user
|
|
// gesture.
|
|
bool HasBeenUserGestureActivated();
|
|
|
|
// Return true if its corresponding window has transient user gesture
|
|
// activation and the transient user gesture activation haven't yet timed
|
|
// out.
|
|
bool HasValidTransientUserGestureActivation();
|
|
|
|
// See `mUserGestureStart`.
|
|
const TimeStamp& GetUserGestureStart() const;
|
|
|
|
// Return true if the corresponding window has valid transient user gesture
|
|
// activation and the transient user gesture activation had been consumed
|
|
// successfully.
|
|
bool ConsumeTransientUserGestureActivation();
|
|
|
|
bool CanShowPopup();
|
|
|
|
bool AllowJavascript() const { return GetAllowJavascript(); }
|
|
bool CanExecuteScripts() const { return mCanExecuteScripts; }
|
|
|
|
void TransientSetHasActivePeerConnections();
|
|
|
|
protected:
|
|
WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId,
|
|
uint64_t aOuterWindowId, FieldValues&& aFields);
|
|
virtual ~WindowContext();
|
|
|
|
virtual void Init();
|
|
|
|
private:
|
|
friend class BrowsingContext;
|
|
friend class WindowGlobalChild;
|
|
friend class WindowGlobalActor;
|
|
|
|
void AppendChildBrowsingContext(BrowsingContext* aBrowsingContext);
|
|
void RemoveChildBrowsingContext(BrowsingContext* aBrowsingContext);
|
|
|
|
// Update non-synthetic children based on whether `aBrowsingContext`
|
|
// is synthetic or not. Regardless the synthetic of `aBrowsingContext`, it is
|
|
// kept in this WindowContext's all children list.
|
|
void UpdateChildSynthetic(BrowsingContext* aBrowsingContext,
|
|
bool aIsSynthetic);
|
|
|
|
// Send a given `BaseTransaction` object to the correct remote.
|
|
void SendCommitTransaction(ContentParent* aParent,
|
|
const BaseTransaction& aTxn, uint64_t aEpoch);
|
|
void SendCommitTransaction(ContentChild* aChild, const BaseTransaction& aTxn,
|
|
uint64_t aEpoch);
|
|
|
|
bool CheckOnlyOwningProcessCanSet(ContentParent* aSource);
|
|
|
|
// Overload `CanSet` to get notifications for a particular field being set.
|
|
bool CanSet(FieldIndex<IDX_IsSecure>, const bool& aIsSecure,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_AllowMixedContent>, const bool& aAllowMixedContent,
|
|
ContentParent* aSource);
|
|
|
|
bool CanSet(FieldIndex<IDX_HasBeforeUnload>, const bool& aHasBeforeUnload,
|
|
ContentParent* aSource);
|
|
|
|
bool CanSet(FieldIndex<IDX_CookieBehavior>, const Maybe<uint32_t>& aValue,
|
|
ContentParent* aSource);
|
|
|
|
bool CanSet(FieldIndex<IDX_IsOnContentBlockingAllowList>, const bool& aValue,
|
|
ContentParent* aSource);
|
|
|
|
bool CanSet(FieldIndex<IDX_EmbedderPolicy>, const bool& aValue,
|
|
ContentParent* aSource) {
|
|
return true;
|
|
}
|
|
|
|
bool CanSet(FieldIndex<IDX_IsThirdPartyWindow>,
|
|
const bool& IsThirdPartyWindow, ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_IsThirdPartyTrackingResourceWindow>,
|
|
const bool& aIsThirdPartyTrackingResourceWindow,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
|
|
const bool& aShouldResistFingerprinting, ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>,
|
|
const bool& aIsOriginalFrameSource, ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_DocTreeHadMedia>, const bool& aValue,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_AutoplayPermission>, const uint32_t& aValue,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_ShortcutsPermission>, const uint32_t& aValue,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_ActiveMediaSessionContextId>,
|
|
const Maybe<uint64_t>& aValue, ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_PopupPermission>, const uint32_t&,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_SHEntryHasUserInteraction>,
|
|
const bool& aSHEntryHasUserInteraction, ContentParent* aSource) {
|
|
return true;
|
|
}
|
|
bool CanSet(FieldIndex<IDX_DelegatedPermissions>,
|
|
const PermissionDelegateHandler::DelegatedPermissionList& aValue,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_DelegatedExactHostMatchPermissions>,
|
|
const PermissionDelegateHandler::DelegatedPermissionList& aValue,
|
|
ContentParent* aSource);
|
|
bool CanSet(FieldIndex<IDX_UserActivationState>,
|
|
const UserActivation::State& aUserActivationState,
|
|
ContentParent* aSource) {
|
|
return true;
|
|
}
|
|
|
|
bool CanSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, const bool& aValue,
|
|
ContentParent* aSource) {
|
|
return true;
|
|
}
|
|
|
|
bool CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue,
|
|
ContentParent* aSource);
|
|
|
|
bool CanSet(FieldIndex<IDX_AllowJavascript>, bool aValue,
|
|
ContentParent* aSource);
|
|
void DidSet(FieldIndex<IDX_AllowJavascript>, bool aOldValue);
|
|
|
|
bool CanSet(FieldIndex<IDX_HasActivePeerConnections>, bool, ContentParent*);
|
|
|
|
void DidSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, bool aOldValue);
|
|
|
|
void DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>, bool aOldValue);
|
|
|
|
bool CanSet(FieldIndex<IDX_WindowStateSaved>, bool aValue,
|
|
ContentParent* aSource);
|
|
|
|
// Overload `DidSet` to get notifications for a particular field being set.
|
|
//
|
|
// You can also overload the variant that gets the old value if you need it.
|
|
template <size_t I>
|
|
void DidSet(FieldIndex<I>) {}
|
|
template <size_t I, typename T>
|
|
void DidSet(FieldIndex<I>, T&& aOldValue) {}
|
|
void DidSet(FieldIndex<IDX_UserActivationState>);
|
|
|
|
// Recomputes whether we can execute scripts in this WindowContext based on
|
|
// the value of AllowJavascript() and whether scripts are allowed in the
|
|
// BrowsingContext.
|
|
void RecomputeCanExecuteScripts(bool aApplyChanges = true);
|
|
|
|
const uint64_t mInnerWindowId;
|
|
const uint64_t mOuterWindowId;
|
|
RefPtr<BrowsingContext> mBrowsingContext;
|
|
WeakPtr<WindowGlobalChild> mWindowGlobalChild;
|
|
|
|
// --- NEVER CHANGE `mChildren` DIRECTLY! ---
|
|
// Changes to this list need to be synchronized to the list within our
|
|
// `mBrowsingContext`, and should only be performed through the
|
|
// `AppendChildBrowsingContext` and `RemoveChildBrowsingContext` methods.
|
|
nsTArray<RefPtr<BrowsingContext>> mChildren;
|
|
|
|
// --- NEVER CHANGE `mNonSyntheticChildren` DIRECTLY! ---
|
|
// Same reason as for mChildren.
|
|
// mNonSyntheticChildren contains the same browsing contexts except browsing
|
|
// contexts created by the synthetic document for object loading contents
|
|
// loading images. This is used to discern browsing contexts created when
|
|
// loading images in <object> or <embed> elements, so that they can be hidden
|
|
// from named targeting, `Window.frames` etc.
|
|
nsTArray<RefPtr<BrowsingContext>> mNonSyntheticChildren;
|
|
|
|
bool mIsDiscarded = false;
|
|
bool mIsInProcess = false;
|
|
|
|
// Determines if we can execute scripts in this WindowContext. True if
|
|
// AllowJavascript() is true and script execution is allowed in the
|
|
// BrowsingContext.
|
|
bool mCanExecuteScripts = true;
|
|
|
|
// The start time of user gesture, this is only available if the window
|
|
// context is in process.
|
|
TimeStamp mUserGestureStart;
|
|
};
|
|
|
|
using WindowContextTransaction = WindowContext::BaseTransaction;
|
|
using WindowContextInitializer = WindowContext::IPCInitializer;
|
|
using MaybeDiscardedWindowContext = MaybeDiscarded<WindowContext>;
|
|
|
|
// Don't specialize the `Transaction` object for every translation unit it's
|
|
// used in. This should help keep code size down.
|
|
extern template class syncedcontext::Transaction<WindowContext>;
|
|
|
|
} // namespace dom
|
|
|
|
namespace ipc {
|
|
template <>
|
|
struct IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>> {
|
|
static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor,
|
|
const dom::MaybeDiscarded<dom::WindowContext>& aParam);
|
|
static bool Read(IPC::MessageReader* aReader, IProtocol* aActor,
|
|
dom::MaybeDiscarded<dom::WindowContext>* aResult);
|
|
};
|
|
|
|
template <>
|
|
struct IPDLParamTraits<dom::WindowContext::IPCInitializer> {
|
|
static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor,
|
|
const dom::WindowContext::IPCInitializer& aInitializer);
|
|
|
|
static bool Read(IPC::MessageReader* aReader, IProtocol* aActor,
|
|
dom::WindowContext::IPCInitializer* aInitializer);
|
|
};
|
|
} // namespace ipc
|
|
} // namespace mozilla
|
|
|
|
#endif // !defined(mozilla_dom_WindowContext_h)
|