/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ /* 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_WindowGlobalParent_h #define mozilla_dom_WindowGlobalParent_h #include "mozilla/ContentBlockingLog.h" #include "mozilla/ContentBlockingNotifier.h" #include "mozilla/Maybe.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" #include "mozilla/dom/ClientInfo.h" #include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/DOMRect.h" #include "mozilla/dom/PWindowGlobalParent.h" #include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowGlobalActorsBinding.h" #include "nsTHashMap.h" #include "nsRefPtrHashtable.h" #include "nsWrapperCache.h" #include "nsISupports.h" #include "nsIDOMProcessParent.h" #include "mozilla/dom/WindowGlobalActor.h" #include "mozilla/dom/CanonicalBrowsingContext.h" #include "mozilla/net/CookieJarSettings.h" class nsIPrincipal; class nsIURI; class nsFrameLoader; namespace mozilla { namespace gfx { class CrossProcessPaint; } // namespace gfx namespace dom { class BrowserParent; class WindowGlobalChild; class JSWindowActorParent; class JSActorMessageMeta; struct PageUseCounters; class WindowSessionStoreState; struct WindowSessionStoreUpdate; class SSCacheQueryResult; /** * A handle in the parent process to a specific nsGlobalWindowInner object. */ class WindowGlobalParent final : public WindowContext, public WindowGlobalActor, public PWindowGlobalParent { friend class gfx::CrossProcessPaint; friend class PWindowGlobalParent; public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WindowGlobalParent, WindowContext) static already_AddRefed GetByInnerWindowId( uint64_t aInnerWindowId); static already_AddRefed GetByInnerWindowId( const GlobalObject& aGlobal, uint64_t aInnerWindowId) { return GetByInnerWindowId(aInnerWindowId); } // The same as the corresponding methods on `WindowContext`, except that the // return types are already cast to their parent-process type variants, such // as `WindowGlobalParent` or `CanonicalBrowsingContext`. WindowGlobalParent* GetParentWindowContext() { return static_cast( WindowContext::GetParentWindowContext()); } WindowGlobalParent* TopWindowContext() { return static_cast(WindowContext::TopWindowContext()); } CanonicalBrowsingContext* GetBrowsingContext() const { return CanonicalBrowsingContext::Cast(WindowContext::GetBrowsingContext()); } Element* GetRootOwnerElement(); // Has this actor been shut down bool IsClosed() { return !CanSend(); } // Get the other side of this actor if it is an in-process actor. Returns // |nullptr| if the actor has been torn down, or is not in-process. already_AddRefed GetChildActor(); // Get a JS actor object by name. already_AddRefed GetActor(JSContext* aCx, const nsACString& aName, ErrorResult& aRv); already_AddRefed GetExistingActor( const nsACString& aName); // Get this actor's manager if it is not an in-process actor. Returns // |nullptr| if the actor has been torn down, or is in-process. BrowserParent* GetBrowserParent(); ContentParent* GetContentParent(); // The principal of this WindowGlobal. This value will not change over the // lifetime of the WindowGlobal object, even to reflect changes in // |document.domain|. nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; } nsIPrincipal* DocumentStoragePrincipal() { return mDocumentStoragePrincipal; } // The BrowsingContext which this WindowGlobal has been loaded into. // FIXME: It's quite awkward that this method has a slightly different name // than the one on WindowContext. CanonicalBrowsingContext* BrowsingContext() override { return GetBrowsingContext(); } // Get the root nsFrameLoader object for the tree of BrowsingContext nodes // which this WindowGlobal is a part of. This will be the nsFrameLoader // holding the BrowserParent for remote tabs, and the root content frameloader // for non-remote tabs. already_AddRefed GetRootFrameLoader(); // The current URI which loaded in the document. nsIURI* GetDocumentURI() override { return mDocumentURI; } void GetDocumentTitle(nsAString& aTitle) const { aTitle = mDocumentTitle.valueOr(nsString()); } nsIPrincipal* GetContentBlockingAllowListPrincipal() const { return mDocContentBlockingAllowListPrincipal; } Maybe GetClientInfo() { return mClientInfo; } uint64_t ContentParentId(); int32_t OsPid(); bool IsCurrentGlobal(); bool IsProcessRoot(); uint32_t ContentBlockingEvents(); void GetContentBlockingLog(nsAString& aLog); bool IsInitialDocument() { return mIsInitialDocument; } already_AddRefed PermitUnload( PermitUnloadAction aAction, uint32_t aTimeout, mozilla::ErrorResult& aRv); void PermitUnload(std::function&& aResolver); already_AddRefed DrawSnapshot( const DOMRect* aRect, double aScale, const nsACString& aBackgroundColor, bool aResetScrollPosition, mozilla::ErrorResult& aRv); static already_AddRefed CreateDisconnected( const WindowGlobalInit& aInit); // Initialize the mFrameLoader fields for a created WindowGlobalParent. Must // be called after setting the Manager actor. void Init() final; nsIGlobalObject* GetParentObject(); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; void NotifyContentBlockingEvent( uint32_t aEvent, nsIRequest* aRequest, bool aBlocked, const nsACString& aTrackingOrigin, const nsTArray& aTrackingFullHashes, const Maybe< ContentBlockingNotifier::StorageAccessPermissionGrantedReason>& aReason = Nothing()); ContentBlockingLog* GetContentBlockingLog() { return &mContentBlockingLog; } nsIDOMProcessParent* GetDomProcess(); nsICookieJarSettings* CookieJarSettings() { return mCookieJarSettings; } nsICookieJarSettings* GetCookieJarSettings() const { return mCookieJarSettings; } bool DocumentHasLoaded() { return mDocumentHasLoaded; } bool DocumentHasUserInteracted() { return mDocumentHasUserInteracted; } uint32_t SandboxFlags() { return mSandboxFlags; } bool GetDocumentBlockAllMixedContent() { return mBlockAllMixedContent; } bool GetDocumentUpgradeInsecureRequests() { return mUpgradeInsecureRequests; } void DidBecomeCurrentWindowGlobal(bool aCurrent); uint32_t HttpsOnlyStatus() { return mHttpsOnlyStatus; } void AddSecurityState(uint32_t aStateFlags); uint32_t GetSecurityFlags() { return mSecurityState; } nsITransportSecurityInfo* GetSecurityInfo() { return mSecurityInfo; } const nsACString& GetRemoteType() override; void NotifySessionStoreUpdatesComplete(Element* aEmbedder); Maybe GetSingleChannelId() { return mSingleChannelId; } uint32_t GetBFCacheStatus() { return mBFCacheStatus; } bool HasActivePeerConnections(); bool Fullscreen() { return mFullscreen; } void SetFullscreen(bool aFullscreen) { mFullscreen = aFullscreen; } void ExitTopChromeDocumentFullscreen(); protected: already_AddRefed InitJSActor(JS::Handle aMaybeActor, const nsACString& aName, ErrorResult& aRv) override; mozilla::ipc::IProtocol* AsNativeActor() override { return this; } // IPC messages mozilla::ipc::IPCResult RecvLoadURI( const MaybeDiscarded& aTargetBC, nsDocShellLoadState* aLoadState, bool aSetNavigating); mozilla::ipc::IPCResult RecvInternalLoad(nsDocShellLoadState* aLoadState); mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI); mozilla::ipc::IPCResult RecvUpdateDocumentPrincipal( nsIPrincipal* aNewDocumentPrincipal, nsIPrincipal* aNewDocumentStoragePrincipal); mozilla::ipc::IPCResult RecvUpdateDocumentHasLoaded(bool aDocumentHasLoaded); mozilla::ipc::IPCResult RecvUpdateDocumentHasUserInteracted( bool aDocumentHasUserInteracted); mozilla::ipc::IPCResult RecvUpdateSandboxFlags(uint32_t aSandboxFlags); mozilla::ipc::IPCResult RecvUpdateDocumentCspSettings( bool aBlockAllMixedContent, bool aUpgradeInsecureRequests); mozilla::ipc::IPCResult RecvUpdateDocumentTitle(const nsString& aTitle); mozilla::ipc::IPCResult RecvUpdateHttpsOnlyStatus(uint32_t aHttpsOnlyStatus); mozilla::ipc::IPCResult RecvSetIsInitialDocument(bool aIsInitialDocument) { mIsInitialDocument = aIsInitialDocument; return IPC_OK(); } mozilla::ipc::IPCResult RecvUpdateDocumentSecurityInfo( nsITransportSecurityInfo* aSecurityInfo); mozilla::ipc::IPCResult RecvSetClientInfo( const IPCClientInfo& aIPCClientInfo); mozilla::ipc::IPCResult RecvDestroy(); mozilla::ipc::IPCResult RecvRawMessage( const JSActorMessageMeta& aMeta, const Maybe& aData, const Maybe& aStack); mozilla::ipc::IPCResult RecvGetContentBlockingEvents( GetContentBlockingEventsResolver&& aResolver); mozilla::ipc::IPCResult RecvUpdateCookieJarSettings( const CookieJarSettingsArgs& aCookieJarSettingsArgs); void ActorDestroy(ActorDestroyReason aWhy) override; void DrawSnapshotInternal(gfx::CrossProcessPaint* aPaint, const Maybe& aRect, float aScale, nscolor aBackgroundColor, uint32_t aFlags); // WebShare API - try to share mozilla::ipc::IPCResult RecvShare(IPCWebShareData&& aData, ShareResolver&& aResolver); mozilla::ipc::IPCResult RecvCheckPermitUnload( bool aHasInProcessBlocker, XPCOMPermitUnloadAction aAction, CheckPermitUnloadResolver&& aResolver); mozilla::ipc::IPCResult RecvExpectPageUseCounters( const MaybeDiscarded& aTop); mozilla::ipc::IPCResult RecvAccumulatePageUseCounters( const UseCounters& aUseCounters); mozilla::ipc::IPCResult RecvRequestRestoreTabContent(); mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint32_t& aOnFlags, const uint32_t& aOffFlags); // This IPC method is to notify the parent process that the caller process // creates the first active peer connection (aIsAdded = true) or closes the // last active peer connection (aIsAdded = false). mozilla::ipc::IPCResult RecvUpdateActivePeerConnectionStatus(bool aIsAdded); public: mozilla::ipc::IPCResult RecvSetSingleChannelId( const Maybe& aSingleChannelId); mozilla::ipc::IPCResult RecvSetDocumentDomain(nsIURI* aDomain); mozilla::ipc::IPCResult RecvReloadWithHttpsOnlyException(); mozilla::ipc::IPCResult RecvDiscoverIdentityCredentialFromExternalSource( const IdentityCredentialRequestOptions& aOptions, const DiscoverIdentityCredentialFromExternalSourceResolver& aResolver); private: WindowGlobalParent(CanonicalBrowsingContext* aBrowsingContext, uint64_t aInnerWindowId, uint64_t aOuterWindowId, FieldValues&& aInit); ~WindowGlobalParent(); bool ShouldTrackSiteOriginTelemetry(); void FinishAccumulatingPageUseCounters(); // Returns failure if the new storage principal cannot be validated // against the current document principle. nsresult SetDocumentStoragePrincipal( nsIPrincipal* aNewDocumentStoragePrincipal); // NOTE: Neither this document principal nor the document storage // principal doesn't reflect possible |document.domain| mutations // which may have been made in the actual document. nsCOMPtr mDocumentPrincipal; nsCOMPtr mDocumentStoragePrincipal; // The principal to use for the content blocking allow list. nsCOMPtr mDocContentBlockingAllowListPrincipal; nsCOMPtr mDocumentURI; Maybe mDocumentTitle; bool mIsInitialDocument; // True if this window has a "beforeunload" event listener. bool mHasBeforeUnload; // The log of all content blocking actions taken on the document related to // this WindowGlobalParent. This is only stored on top-level documents and // includes the activity log for all of the nested subdocuments as well. ContentBlockingLog mContentBlockingLog; uint32_t mSecurityState = 0; Maybe mClientInfo; // Fields being mirrored from the corresponding document nsCOMPtr mCookieJarSettings; nsCOMPtr mSecurityInfo; uint32_t mSandboxFlags; struct OriginCounter { void UpdateSiteOriginsFrom(WindowGlobalParent* aParent, bool aIncrease); void Accumulate(); nsTHashMap mOriginMap; uint32_t mMaxOrigins = 0; }; // Used to collect unique site origin telemetry. // // Is only Some() on top-level content windows. Maybe mOriginCounter; bool mDocumentHasLoaded; bool mDocumentHasUserInteracted; bool mDocumentTreeWouldPreloadResources = false; bool mBlockAllMixedContent; bool mUpgradeInsecureRequests; // HTTPS-Only Mode flags uint32_t mHttpsOnlyStatus; // The window of the document whose page use counters our document's use // counters will contribute to. (If we are a top-level document, this // will point to ourselves.) RefPtr mPageUseCountersWindow; // Our page use counters, if we are a top-level document. UniquePtr mPageUseCounters; // Whether we have sent our page use counters, and so should ignore any // subsequent ExpectPageUseCounters calls. bool mSentPageUseCounters = false; uint32_t mBFCacheStatus = 0; // If this WindowGlobalParent is a top window, this field indicates how many // child processes have active peer connections for this window and its // descendants. uint32_t mNumOfProcessesWithActivePeerConnections = 0; // mSingleChannelId records whether the loadgroup contains a single request // with an id. If there is one channel in the loadgroup and it has an id then // mSingleChannelId is set to Some(id) (ids are non-zero). If there is one // request in the loadgroup and it's not a channel or it doesn't have an id, // or there are multiple requests in the loadgroup, then mSingleChannelId is // set to Some(0). If there are no requests in the loadgroup then // mSingleChannelId is set to Nothing(). // Note: We ignore favicon loads when considering the requests in the // loadgroup. Maybe mSingleChannelId; // True if the current loaded document is in fullscreen. bool mFullscreen = false; }; } // namespace dom } // namespace mozilla inline nsISupports* ToSupports( mozilla::dom::WindowGlobalParent* aWindowGlobal) { return static_cast(aWindowGlobal); } #endif // !defined(mozilla_dom_WindowGlobalParent_h)