gecko-dev/dom/ipc/WindowGlobalParent.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

364 строки
13 KiB
C
Исходник Обычный вид История

/* -*- 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;
Bug 1656114 - Part 4: Accumulate page use counters in the parent process. r=emilio,nika This changes the way we deal with page use counters so that we can handle out of process iframes. Currently, when a parent document is being destroyed, we poke into all of the sub-documents to merge their use counters into the parent's page use counters, which we then report via Telemetry. With Fission enabled, the sub-documents may be out of process. We can't simply turn these into async IPC calls, since the parent document will be destroyed shortly, as might the content processes holding the sub-documents. So instead, each document during its initialization identifies which ancestor document it will contribute its page use counters to, and stores its WindowContext id to identify that ancestor. A message is sent to the parent process to notify it that page use counter data will be sent at some later point. That later point is when the document loses its window. It doesn't matter if the ancestor document has already been destroyed at this point, since all we need is its WindowContext id to uniquely identify it. Once the parent process has received all of the use counters it expects to accumulate to a given WindowContext Id, it reports them via Telemetry. Reporting of document use counters remains unchanged and is done by each document in their content process. While we're here, we also: * Limit use counters to be reported for a pre-defined set of document URL schemes, rather than be based on the document principal. * Add proper MOZ_LOG logging for use counters instead of printfs. Differential Revision: https://phabricator.services.mozilla.com/D87188
2020-10-12 01:03:43 +03:00
struct PageUseCounters;
class WindowSessionStoreState;
struct WindowSessionStoreUpdate;
/**
* 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<WindowGlobalParent> GetByInnerWindowId(
uint64_t aInnerWindowId);
static already_AddRefed<WindowGlobalParent> 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<WindowGlobalParent*>(
WindowContext::GetParentWindowContext());
}
WindowGlobalParent* TopWindowContext() {
return static_cast<WindowGlobalParent*>(WindowContext::TopWindowContext());
}
CanonicalBrowsingContext* GetBrowsingContext() {
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<WindowGlobalChild> GetChildActor();
// Get a JS actor object by name.
already_AddRefed<JSWindowActorParent> GetActor(JSContext* aCx,
const nsACString& aName,
ErrorResult& aRv);
// 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; }
// 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<nsFrameLoader> 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<ClientInfo> 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<mozilla::dom::Promise> PermitUnload(
PermitUnloadAction aAction, uint32_t aTimeout, mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::Promise> DrawSnapshot(
const DOMRect* aRect, double aScale, const nsACString& aBackgroundColor,
mozilla::ErrorResult& aRv);
already_AddRefed<Promise> GetSecurityInfo(ErrorResult& aRv);
static already_AddRefed<WindowGlobalParent> 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<JSObject*> aGivenProto) override;
void NotifyContentBlockingEvent(
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
const nsACString& aTrackingOrigin,
const nsTArray<nsCString>& 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;
nsresult UpdateSessionStore(const Maybe<FormData>& aFormData,
const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch);
protected:
already_AddRefed<JSActor> InitJSActor(JS::HandleObject aMaybeActor,
const nsACString& aName,
ErrorResult& aRv) override;
mozilla::ipc::IProtocol* AsNativeActor() override { return this; }
// IPC messages
mozilla::ipc::IPCResult RecvLoadURI(
const MaybeDiscarded<dom::BrowsingContext>& aTargetBC,
nsDocShellLoadState* aLoadState, bool aSetNavigating);
mozilla::ipc::IPCResult RecvInternalLoad(nsDocShellLoadState* aLoadState);
mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI);
mozilla::ipc::IPCResult RecvUpdateDocumentPrincipal(
nsIPrincipal* aNewDocumentPrincipal);
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<ClonedMessageData>& aData,
const Maybe<ClonedMessageData>& 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<IntRect>& 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);
Bug 1656114 - Part 4: Accumulate page use counters in the parent process. r=emilio,nika This changes the way we deal with page use counters so that we can handle out of process iframes. Currently, when a parent document is being destroyed, we poke into all of the sub-documents to merge their use counters into the parent's page use counters, which we then report via Telemetry. With Fission enabled, the sub-documents may be out of process. We can't simply turn these into async IPC calls, since the parent document will be destroyed shortly, as might the content processes holding the sub-documents. So instead, each document during its initialization identifies which ancestor document it will contribute its page use counters to, and stores its WindowContext id to identify that ancestor. A message is sent to the parent process to notify it that page use counter data will be sent at some later point. That later point is when the document loses its window. It doesn't matter if the ancestor document has already been destroyed at this point, since all we need is its WindowContext id to uniquely identify it. Once the parent process has received all of the use counters it expects to accumulate to a given WindowContext Id, it reports them via Telemetry. Reporting of document use counters remains unchanged and is done by each document in their content process. While we're here, we also: * Limit use counters to be reported for a pre-defined set of document URL schemes, rather than be based on the document principal. * Add proper MOZ_LOG logging for use counters instead of printfs. Differential Revision: https://phabricator.services.mozilla.com/D87188
2020-10-12 01:03:43 +03:00
mozilla::ipc::IPCResult RecvExpectPageUseCounters(
const MaybeDiscarded<dom::WindowContext>& aTop);
mozilla::ipc::IPCResult RecvAccumulatePageUseCounters(
const UseCounters& aUseCounters);
mozilla::ipc::IPCResult RecvRequestRestoreTabContent();
mozilla::ipc::IPCResult RecvUpdateSessionStore(
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch);
mozilla::ipc::IPCResult RecvResetSessionStore(uint32_t aEpoch);
private:
WindowGlobalParent(CanonicalBrowsingContext* aBrowsingContext,
uint64_t aInnerWindowId, uint64_t aOuterWindowId,
FieldValues&& aInit);
~WindowGlobalParent();
bool ShouldTrackSiteOriginTelemetry();
Bug 1656114 - Part 4: Accumulate page use counters in the parent process. r=emilio,nika This changes the way we deal with page use counters so that we can handle out of process iframes. Currently, when a parent document is being destroyed, we poke into all of the sub-documents to merge their use counters into the parent's page use counters, which we then report via Telemetry. With Fission enabled, the sub-documents may be out of process. We can't simply turn these into async IPC calls, since the parent document will be destroyed shortly, as might the content processes holding the sub-documents. So instead, each document during its initialization identifies which ancestor document it will contribute its page use counters to, and stores its WindowContext id to identify that ancestor. A message is sent to the parent process to notify it that page use counter data will be sent at some later point. That later point is when the document loses its window. It doesn't matter if the ancestor document has already been destroyed at this point, since all we need is its WindowContext id to uniquely identify it. Once the parent process has received all of the use counters it expects to accumulate to a given WindowContext Id, it reports them via Telemetry. Reporting of document use counters remains unchanged and is done by each document in their content process. While we're here, we also: * Limit use counters to be reported for a pre-defined set of document URL schemes, rather than be based on the document principal. * Add proper MOZ_LOG logging for use counters instead of printfs. Differential Revision: https://phabricator.services.mozilla.com/D87188
2020-10-12 01:03:43 +03:00
void FinishAccumulatingPageUseCounters();
nsresult ResetSessionStore(uint32_t aEpoch);
// NOTE: This document principal doesn't reflect possible |document.domain|
// mutations which may have been made in the actual document.
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
// The principal to use for the content blocking allow list.
nsCOMPtr<nsIPrincipal> mDocContentBlockingAllowListPrincipal;
nsCOMPtr<nsIURI> mDocumentURI;
Maybe<nsString> 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<ClientInfo> mClientInfo;
// Fields being mirrored from the corresponding document
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
uint32_t mSandboxFlags;
struct OriginCounter {
void UpdateSiteOriginsFrom(WindowGlobalParent* aParent, bool aIncrease);
void Accumulate();
nsTHashMap<nsCStringHashKey, int32_t> mOriginMap;
uint32_t mMaxOrigins = 0;
};
// Used to collect unique site origin telemetry.
//
// Is only Some() on top-level content windows.
Maybe<OriginCounter> mOriginCounter;
bool mDocumentHasLoaded;
bool mDocumentHasUserInteracted;
bool mDocumentTreeWouldPreloadResources = false;
bool mBlockAllMixedContent;
bool mUpgradeInsecureRequests;
// HTTPS-Only Mode flags
uint32_t mHttpsOnlyStatus;
Bug 1656114 - Part 4: Accumulate page use counters in the parent process. r=emilio,nika This changes the way we deal with page use counters so that we can handle out of process iframes. Currently, when a parent document is being destroyed, we poke into all of the sub-documents to merge their use counters into the parent's page use counters, which we then report via Telemetry. With Fission enabled, the sub-documents may be out of process. We can't simply turn these into async IPC calls, since the parent document will be destroyed shortly, as might the content processes holding the sub-documents. So instead, each document during its initialization identifies which ancestor document it will contribute its page use counters to, and stores its WindowContext id to identify that ancestor. A message is sent to the parent process to notify it that page use counter data will be sent at some later point. That later point is when the document loses its window. It doesn't matter if the ancestor document has already been destroyed at this point, since all we need is its WindowContext id to uniquely identify it. Once the parent process has received all of the use counters it expects to accumulate to a given WindowContext Id, it reports them via Telemetry. Reporting of document use counters remains unchanged and is done by each document in their content process. While we're here, we also: * Limit use counters to be reported for a pre-defined set of document URL schemes, rather than be based on the document principal. * Add proper MOZ_LOG logging for use counters instead of printfs. Differential Revision: https://phabricator.services.mozilla.com/D87188
2020-10-12 01:03:43 +03:00
// 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<WindowGlobalParent> mPageUseCountersWindow;
// Our page use counters, if we are a top-level document.
UniquePtr<PageUseCounters> mPageUseCounters;
// Whether we have sent our page use counters, and so should ignore any
// subsequent ExpectPageUseCounters calls.
bool mSentPageUseCounters = false;
};
} // namespace dom
} // namespace mozilla
inline nsISupports* ToSupports(
mozilla::dom::WindowGlobalParent* aWindowGlobal) {
return static_cast<mozilla::dom::WindowContext*>(aWindowGlobal);
}
#endif // !defined(mozilla_dom_WindowGlobalParent_h)