Bug 1616353 - Part 6.1: Implement nsILoadContext on BrowsingContext, r=smaug

This also moves nsDocShell's implementation of nsILoadContext to be based on its
BrowsingContext.

This patch does not, by itself, fix all places which try to mutate
`nsILoadContext`. Those are fixed by the other parts of this patch stack.

Differential Revision: https://phabricator.services.mozilla.com/D67045

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2020-04-07 21:39:12 +00:00
Родитель 146e915363
Коммит 570fcda0e2
7 изменённых файлов: 466 добавлений и 343 удалений

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

@ -215,6 +215,11 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
BrowsingContext* inherit = aParent ? aParent : aOpener; BrowsingContext* inherit = aParent ? aParent : aOpener;
if (inherit) { if (inherit) {
context->mPrivateBrowsingId = inherit->mPrivateBrowsingId;
context->mUseRemoteTabs = inherit->mUseRemoteTabs;
context->mUseRemoteSubframes = inherit->mUseRemoteSubframes;
context->mOriginAttributes = inherit->mOriginAttributes;
// CORPP 3.1.3 https://mikewest.github.io/corpp/#integration-html // CORPP 3.1.3 https://mikewest.github.io/corpp/#integration-html
context->mFields.SetWithoutSyncing<IDX_EmbedderPolicy>( context->mFields.SetWithoutSyncing<IDX_EmbedderPolicy>(
inherit->GetEmbedderPolicy()); inherit->GetEmbedderPolicy());
@ -320,6 +325,13 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateFromIPC(
context->mWindowless = aInit.mWindowless; context->mWindowless = aInit.mWindowless;
// NOTE: Call through the `Set` methods for these values to ensure that any
// relevant process-local state is also updated.
context->SetOriginAttributes(aInit.mOriginAttributes);
context->SetRemoteTabs(aInit.mUseRemoteTabs);
context->SetRemoteSubframes(aInit.mUseRemoteSubframes);
// NOTE: Private browsing ID is set by `SetOriginAttributes`.
Register(context); Register(context);
// Caller handles attaching us to the tree. // Caller handles attaching us to the tree.
@ -340,13 +352,16 @@ BrowsingContext::BrowsingContext(BrowsingContext* aParent,
mBrowsingContextId(aBrowsingContextId), mBrowsingContextId(aBrowsingContextId),
mGroup(aGroup), mGroup(aGroup),
mParent(aParent), mParent(aParent),
mPrivateBrowsingId(0),
mEverAttached(false), mEverAttached(false),
mIsInProcess(false), mIsInProcess(false),
mIsDiscarded(false), mIsDiscarded(false),
mWindowless(false), mWindowless(false),
mDanglingRemoteOuterProxies(false), mDanglingRemoteOuterProxies(false),
mPendingInitialization(false), mPendingInitialization(false),
mEmbeddedByThisProcess(false) { mEmbeddedByThisProcess(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false) {
MOZ_RELEASE_ASSERT(!mParent || mParent->Group() == mGroup); MOZ_RELEASE_ASSERT(!mParent || mParent->Group() == mGroup);
MOZ_RELEASE_ASSERT(mBrowsingContextId != 0); MOZ_RELEASE_ASSERT(mBrowsingContextId != 0);
MOZ_RELEASE_ASSERT(mGroup); MOZ_RELEASE_ASSERT(mGroup);
@ -442,10 +457,16 @@ void BrowsingContext::Attach(bool aFromIPC) {
MOZ_DIAGNOSTIC_ASSERT(!mEverAttached); MOZ_DIAGNOSTIC_ASSERT(!mEverAttached);
mEverAttached = true; mEverAttached = true;
MOZ_LOG(GetLog(), LogLevel::Debug, if (MOZ_LOG_TEST(GetLog(), LogLevel::Debug)) {
("%s: Connecting 0x%08" PRIx64 " to 0x%08" PRIx64, nsAutoCString suffix;
XRE_IsParentProcess() ? "Parent" : "Child", Id(), mOriginAttributes.CreateSuffix(suffix);
mParent ? mParent->Id() : 0)); MOZ_LOG(GetLog(), LogLevel::Debug,
("%s: Connecting 0x%08" PRIx64 " to 0x%08" PRIx64
" (private=%d, remote=%d, fission=%d, oa=%s)",
XRE_IsParentProcess() ? "Parent" : "Child", Id(),
mParent ? mParent->Id() : 0, (int)mPrivateBrowsingId,
(int)mUseRemoteTabs, (int)mUseRemoteSubframes, suffix.get()));
}
MOZ_DIAGNOSTIC_ASSERT(mGroup); MOZ_DIAGNOSTIC_ASSERT(mGroup);
MOZ_DIAGNOSTIC_ASSERT(!mGroup->IsContextCached(this)); MOZ_DIAGNOSTIC_ASSERT(!mGroup->IsContextCached(this));
@ -562,6 +583,8 @@ void BrowsingContext::Detach(bool aFromIPC) {
mFields.SetWithoutSyncing<IDX_IsPopupSpam>(false); mFields.SetWithoutSyncing<IDX_IsPopupSpam>(false);
} }
AssertOriginAttributesMatchPrivateBrowsing();
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
Canonical()->CanonicalDiscard(); Canonical()->CanonicalDiscard();
} }
@ -985,6 +1008,239 @@ bool BrowsingContext::ConsumeTransientUserGestureActivation() {
return true; return true;
} }
bool BrowsingContext::CanSetOriginAttributes() {
// A discarded BrowsingContext has already been destroyed, and cannot modify
// its OriginAttributes.
if (NS_WARN_IF(IsDiscarded())) {
return false;
}
// Before attaching is the safest time to set OriginAttributes, and the only
// allowed time for content BrowsingContexts.
if (!EverAttached()) {
return true;
}
// Attached content BrowsingContexts may have been synced to other processes.
if (NS_WARN_IF(IsContent())) {
MOZ_CRASH();
return false;
}
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
// Cannot set OriginAttributes after we've created our child BrowsingContext.
if (NS_WARN_IF(!Children().IsEmpty())) {
return false;
}
// Only allow setting OriginAttributes if we have no associated document, or
// the document is still `about:blank`.
// TODO: Bug 1273058 - should have no document when setting origin attributes.
if (WindowGlobalParent* window = Canonical()->GetCurrentWindowGlobal()) {
if (nsIURI* uri = window->GetDocumentURI()) {
MOZ_ASSERT(NS_IsAboutBlank(uri));
return NS_IsAboutBlank(uri);
}
}
return true;
}
NS_IMETHODIMP BrowsingContext::GetAssociatedWindow(
mozIDOMWindowProxy** aAssociatedWindow) {
nsCOMPtr<mozIDOMWindowProxy> win = GetDOMWindow();
win.forget(aAssociatedWindow);
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetTopWindow(mozIDOMWindowProxy** aTopWindow) {
return Top()->GetAssociatedWindow(aTopWindow);
}
NS_IMETHODIMP BrowsingContext::GetTopFrameElement(Element** aTopFrameElement) {
RefPtr<Element> topFrameElement = Top()->GetEmbedderElement();
topFrameElement.forget(aTopFrameElement);
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetNestedFrameId(uint64_t* aNestedFrameId) {
// FIXME: nestedFrameId should be removed, as it was only used by B2G.
*aNestedFrameId = 0;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetIsContent(bool* aIsContent) {
*aIsContent = IsContent();
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetUsePrivateBrowsing(
bool* aUsePrivateBrowsing) {
*aUsePrivateBrowsing = mPrivateBrowsingId > 0;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
if (!CanSetOriginAttributes()) {
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
if (changed) {
NS_WARNING("SetUsePrivateBrowsing when !CanSetOriginAttributes()");
}
return changed ? NS_ERROR_FAILURE : NS_OK;
}
return SetPrivateBrowsing(aUsePrivateBrowsing);
}
NS_IMETHODIMP BrowsingContext::SetPrivateBrowsing(bool aPrivateBrowsing) {
if (!CanSetOriginAttributes()) {
NS_WARNING("Attempt to set PrivateBrowsing when !CanSetOriginAttributes");
return NS_ERROR_FAILURE;
}
bool changed = aPrivateBrowsing != (mPrivateBrowsingId > 0);
if (changed) {
mPrivateBrowsingId = aPrivateBrowsing ? 1 : 0;
if (IsContent()) {
mOriginAttributes.SyncAttributesWithPrivateBrowsing(aPrivateBrowsing);
}
}
AssertOriginAttributesMatchPrivateBrowsing();
if (changed && mDocShell) {
nsDocShell::Cast(mDocShell)->NotifyPrivateBrowsingChanged();
}
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetUseRemoteTabs(bool* aUseRemoteTabs) {
*aUseRemoteTabs = mUseRemoteTabs;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::SetRemoteTabs(bool aUseRemoteTabs) {
if (!CanSetOriginAttributes()) {
NS_WARNING("Attempt to set RemoteTabs when !CanSetOriginAttributes");
return NS_ERROR_FAILURE;
}
static bool annotated = false;
if (aUseRemoteTabs && !annotated) {
annotated = true;
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::DOMIPCEnabled,
true);
}
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(!aUseRemoteTabs && mUseRemoteSubframes)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteTabs = aUseRemoteTabs;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetUseRemoteSubframes(
bool* aUseRemoteSubframes) {
*aUseRemoteSubframes = mUseRemoteSubframes;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::SetRemoteSubframes(bool aUseRemoteSubframes) {
if (!CanSetOriginAttributes()) {
NS_WARNING("Attempt to set RemoteSubframes when !CanSetOriginAttributes");
return NS_ERROR_FAILURE;
}
static bool annotated = false;
if (aUseRemoteSubframes && !annotated) {
annotated = true;
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::DOMFissionEnabled, true);
}
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(aUseRemoteSubframes && !mUseRemoteTabs)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteSubframes = aUseRemoteSubframes;
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetUseTrackingProtection(
bool* aUseTrackingProtection) {
*aUseTrackingProtection = false;
if (GetForceEnableTrackingProtection() ||
StaticPrefs::privacy_trackingprotection_enabled() ||
(UsePrivateBrowsing() &&
StaticPrefs::privacy_trackingprotection_pbmode_enabled())) {
*aUseTrackingProtection = true;
return NS_OK;
}
if (mParent) {
return mParent->GetUseTrackingProtection(aUseTrackingProtection);
}
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::SetUseTrackingProtection(
bool aUseTrackingProtection) {
SetForceEnableTrackingProtection(aUseTrackingProtection);
return NS_OK;
}
NS_IMETHODIMP BrowsingContext::GetScriptableOriginAttributes(
JSContext* aCx, JS::MutableHandle<JS::Value> aVal) {
AssertOriginAttributesMatchPrivateBrowsing();
bool ok = ToJSValue(aCx, mOriginAttributes, aVal);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP_(void)
BrowsingContext::GetOriginAttributes(OriginAttributes& aAttrs) {
aAttrs = mOriginAttributes;
AssertOriginAttributesMatchPrivateBrowsing();
}
nsresult BrowsingContext::SetOriginAttributes(const OriginAttributes& aAttrs) {
if (!CanSetOriginAttributes()) {
NS_WARNING("Attempt to set OriginAttributes when !CanSetOriginAttributes");
return NS_ERROR_FAILURE;
}
AssertOriginAttributesMatchPrivateBrowsing();
mOriginAttributes = aAttrs;
bool isPrivate = mOriginAttributes.mPrivateBrowsingId !=
nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
// Chrome Browsing Context can not contain OriginAttributes.mPrivateBrowsingId
if (IsChrome() && isPrivate) {
mOriginAttributes.mPrivateBrowsingId =
nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
}
SetPrivateBrowsing(isPrivate);
AssertOriginAttributesMatchPrivateBrowsing();
return NS_OK;
}
void BrowsingContext::AssertOriginAttributesMatchPrivateBrowsing() {
// Chrome browsing contexts must not have a private browsing OriginAttribute
// Content browsing contexts must maintain the equality:
// mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
if (IsChrome()) {
MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
} else {
MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId ==
mPrivateBrowsingId);
}
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowsingContext) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowsingContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
@ -1354,6 +1610,9 @@ BrowsingContext::IPCInitializer BrowsingContext::GetIPCInitializer() {
init.mParentId = mParent ? mParent->Id() : 0; init.mParentId = mParent ? mParent->Id() : 0;
init.mCached = IsCached(); init.mCached = IsCached();
init.mWindowless = mWindowless; init.mWindowless = mWindowless;
init.mUseRemoteTabs = mUseRemoteTabs;
init.mUseRemoteSubframes = mUseRemoteSubframes;
init.mOriginAttributes = mOriginAttributes;
init.mFields = mFields.Fields(); init.mFields = mFields.Fields();
return init; return init;
} }
@ -1734,6 +1993,9 @@ void IPDLParamTraits<dom::BrowsingContext::IPCInitializer>::Write(
WriteIPDLParam(aMessage, aActor, aInit.mParentId); WriteIPDLParam(aMessage, aActor, aInit.mParentId);
WriteIPDLParam(aMessage, aActor, aInit.mCached); WriteIPDLParam(aMessage, aActor, aInit.mCached);
WriteIPDLParam(aMessage, aActor, aInit.mWindowless); WriteIPDLParam(aMessage, aActor, aInit.mWindowless);
WriteIPDLParam(aMessage, aActor, aInit.mUseRemoteTabs);
WriteIPDLParam(aMessage, aActor, aInit.mUseRemoteSubframes);
WriteIPDLParam(aMessage, aActor, aInit.mOriginAttributes);
WriteIPDLParam(aMessage, aActor, aInit.mFields); WriteIPDLParam(aMessage, aActor, aInit.mFields);
} }
@ -1745,6 +2007,10 @@ bool IPDLParamTraits<dom::BrowsingContext::IPCInitializer>::Read(
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mParentId) || !ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mParentId) ||
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mCached) || !ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mCached) ||
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mWindowless) || !ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mWindowless) ||
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mUseRemoteTabs) ||
!ReadIPDLParam(aMessage, aIterator, aActor,
&aInit->mUseRemoteSubframes) ||
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mOriginAttributes) ||
!ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mFields)) { !ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mFields)) {
return false; return false;
} }

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

@ -29,6 +29,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "nsILoadInfo.h" #include "nsILoadInfo.h"
#include "nsILoadContext.h"
class nsDocShellLoadState; class nsDocShellLoadState;
class nsGlobalWindowOuter; class nsGlobalWindowOuter;
@ -108,6 +109,7 @@ class WindowProxyHolder;
FIELD(AllowPlugins, bool) \ FIELD(AllowPlugins, bool) \
FIELD(AllowContentRetargeting, bool) \ FIELD(AllowContentRetargeting, bool) \
FIELD(AllowContentRetargetingOnChildren, bool) \ FIELD(AllowContentRetargetingOnChildren, bool) \
FIELD(ForceEnableTrackingProtection, bool) \
/* These field are used to store the states of autoplay media request on \ /* These field are used to store the states of autoplay media request on \
* GeckoView only, and it would only be modified on the top level browsing \ * GeckoView only, and it would only be modified on the top level browsing \
* context. */ \ * context. */ \
@ -136,7 +138,7 @@ class WindowProxyHolder;
// Trees of BrowsingContexts should only ever contain nodes of the // Trees of BrowsingContexts should only ever contain nodes of the
// same BrowsingContext::Type. This is enforced by asserts in the // same BrowsingContext::Type. This is enforced by asserts in the
// BrowsingContext::Create* methods. // BrowsingContext::Create* methods.
class BrowsingContext : public nsISupports, public nsWrapperCache { class BrowsingContext : public nsILoadContext, public nsWrapperCache {
MOZ_DECL_SYNCED_CONTEXT(BrowsingContext, MOZ_EACH_BC_FIELD) MOZ_DECL_SYNCED_CONTEXT(BrowsingContext, MOZ_EACH_BC_FIELD)
public: public:
@ -436,6 +438,7 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BrowsingContext) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BrowsingContext)
NS_DECL_NSILOADCONTEXT
const Children& GetChildren() { return mChildren; } const Children& GetChildren() { return mChildren; }
const nsTArray<RefPtr<WindowContext>>& GetWindowContexts() { const nsTArray<RefPtr<WindowContext>>& GetWindowContexts() {
@ -504,19 +507,22 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
* This object may be serialized over IPC. * This object may be serialized over IPC.
*/ */
struct IPCInitializer { struct IPCInitializer {
uint64_t mId; uint64_t mId = 0;
// IDs are used for Parent and Opener to allow for this object to be // IDs are used for Parent and Opener to allow for this object to be
// deserialized before other BrowsingContext in the BrowsingContextGroup // deserialized before other BrowsingContext in the BrowsingContextGroup
// have been initialized. // have been initialized.
uint64_t mParentId; uint64_t mParentId = 0;
already_AddRefed<BrowsingContext> GetParent(); already_AddRefed<BrowsingContext> GetParent();
already_AddRefed<BrowsingContext> GetOpener(); already_AddRefed<BrowsingContext> GetOpener();
uint64_t GetOpenerId() const { return mozilla::Get<IDX_OpenerId>(mFields); } uint64_t GetOpenerId() const { return mozilla::Get<IDX_OpenerId>(mFields); }
bool mCached; bool mCached = false;
bool mWindowless; bool mWindowless = false;
bool mUseRemoteTabs = false;
bool mUseRemoteSubframes = false;
OriginAttributes mOriginAttributes;
FieldTuple mFields; FieldTuple mFields;
}; };
@ -542,6 +548,9 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
bool PendingInitialization() const { return mPendingInitialization; }; bool PendingInitialization() const { return mPendingInitialization; };
void SetPendingInitialization(bool aVal) { mPendingInitialization = aVal; }; void SetPendingInitialization(bool aVal) { mPendingInitialization = aVal; };
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
nsresult SetOriginAttributes(const OriginAttributes& aAttrs);
protected: protected:
virtual ~BrowsingContext(); virtual ~BrowsingContext();
BrowsingContext(BrowsingContext* aParent, BrowsingContextGroup* aGroup, BrowsingContext(BrowsingContext* aParent, BrowsingContextGroup* aGroup,
@ -554,6 +563,12 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
BrowsingContext* FindWithSpecialName(const nsAString& aName, BrowsingContext* FindWithSpecialName(const nsAString& aName,
BrowsingContext& aRequestingContext); BrowsingContext& aRequestingContext);
// Is it early enough in the BrowsingContext's lifecycle that it is still
// OK to set OriginAttributes?
bool CanSetOriginAttributes();
void AssertOriginAttributesMatchPrivateBrowsing();
friend class ::nsOuterWindowProxy; friend class ::nsOuterWindowProxy;
friend class ::nsGlobalWindowOuter; friend class ::nsGlobalWindowOuter;
friend class WindowContext; friend class WindowContext;
@ -699,6 +714,16 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
JS::Heap<JSObject*> mWindowProxy; JS::Heap<JSObject*> mWindowProxy;
LocationProxy mLocation; LocationProxy mLocation;
// OriginAttributes for this BrowsingContext. May not be changed after this
// BrowsingContext is attached.
OriginAttributes mOriginAttributes;
// Determines if private browsing should be used. May not be changed after
// this BrowsingContext is attached. This field matches mOriginAttributes in
// content Browsing Contexts. Currently treated as a binary value: 1 - in
// private mode, 0 - not private mode.
uint32_t mPrivateBrowsingId;
// True if Attach() has been called on this BrowsingContext already. // True if Attach() has been called on this BrowsingContext already.
bool mEverAttached : 1; bool mEverAttached : 1;
@ -727,6 +752,14 @@ class BrowsingContext : public nsISupports, public nsWrapperCache {
// process. // process.
bool mEmbeddedByThisProcess : 1; bool mEmbeddedByThisProcess : 1;
// Determines if remote (out-of-process) tabs should be used. May not be
// changed after this BrowsingContext is attached.
bool mUseRemoteTabs : 1;
// Determines if out-of-process iframes should be used. May not be changed
// after this BrowsingContext is attached.
bool mUseRemoteSubframes : 1;
// The start time of user gesture, this is only available if the browsing // The start time of user gesture, this is only available if the browsing
// context is in process. // context is in process.
TimeStamp mUserGestureStart; TimeStamp mUserGestureStart;

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

@ -360,7 +360,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mDefaultLoadFlags(nsIRequest::LOAD_NORMAL), mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
mFailedLoadType(0), mFailedLoadType(0),
mFrameType(FRAME_TYPE_REGULAR), mFrameType(FRAME_TYPE_REGULAR),
mPrivateBrowsingId(0),
mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER), mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER),
mJSRunToCompletionDepth(0), mJSRunToCompletionDepth(0),
mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE), mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE),
@ -387,13 +386,9 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mDisableMetaRefreshWhenInactive(false), mDisableMetaRefreshWhenInactive(false),
mIsAppTab(false), mIsAppTab(false),
mUseGlobalHistory(false), mUseGlobalHistory(false),
mUseRemoteTabs(false),
mUseRemoteSubframes(false),
mUseTrackingProtection(false),
mDeviceSizeIsPageSize(false), mDeviceSizeIsPageSize(false),
mWindowDraggingAllowed(false), mWindowDraggingAllowed(false),
mInFrameSwap(false), mInFrameSwap(false),
mInheritPrivateBrowsingId(true),
mCanExecuteScripts(false), mCanExecuteScripts(false),
mFiredUnloadEvent(false), mFiredUnloadEvent(false),
mEODForCurrentDocument(false), mEODForCurrentDocument(false),
@ -412,8 +407,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mWillChangeProcess(false), mWillChangeProcess(false),
mWatchedByDevtools(false), mWatchedByDevtools(false),
mIsNavigating(false) { mIsNavigating(false) {
AssertOriginAttributesMatchPrivateBrowsing();
// If no outer window ID was provided, generate a new one. // If no outer window ID was provided, generate a new one.
if (aContentWindowID == 0) { if (aContentWindowID == 0) {
mContentWindowID = nsContentUtils::GenerateWindowId(); mContentWindowID = nsContentUtils::GenerateWindowId();
@ -533,6 +526,12 @@ already_AddRefed<nsDocShell> nsDocShell::Create(
return nullptr; return nullptr;
} }
// If our BrowsingContext has private browsing enabled, update the number of
// private browsing docshells.
if (aBrowsingContext->UsePrivateBrowsing()) {
ds->NotifyPrivateBrowsingChanged();
}
// If our parent is present in this process, set up our parent now. // If our parent is present in this process, set up our parent now.
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent(); RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
if (parent && parent->GetDocShell()) { if (parent && parent->GetDocShell()) {
@ -801,10 +800,12 @@ nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
BrowsingContext::Type bcType = mBrowsingContext->GetType(); BrowsingContext::Type bcType = mBrowsingContext->GetType();
// Set up the inheriting principal in LoadState. // Set up the inheriting principal in LoadState.
nsresult rv = aLoadState->SetupInheritingPrincipal(bcType, mOriginAttributes); nsresult rv = aLoadState->SetupInheritingPrincipal(
bcType, mBrowsingContext->OriginAttributesRef());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = aLoadState->SetupTriggeringPrincipal(mOriginAttributes); rv = aLoadState->SetupTriggeringPrincipal(
mBrowsingContext->OriginAttributesRef());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
aLoadState->CalculateLoadURIFlags(); aLoadState->CalculateLoadURIFlags();
@ -1523,66 +1524,40 @@ nsDocShell::SetAllowJavascript(bool aAllowJavascript) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing);
AssertOriginAttributesMatchPrivateBrowsing(); return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
*aUsePrivateBrowsing = mPrivateBrowsingId > 0; }
return NS_OK;
void nsDocShell::NotifyPrivateBrowsingChanged() {
MOZ_ASSERT(!mIsBeingDestroyed);
if (mAffectPrivateSessionLifetime) {
if (UsePrivateBrowsing()) {
IncreasePrivateDocShellCount();
} else {
DecreasePrivateDocShellCount();
}
}
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
while (iter.HasMore()) {
nsWeakPtr ref = iter.GetNext();
nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
if (!obs) {
mPrivacyObservers.RemoveElement(ref);
} else {
obs->PrivateModeChanged(UsePrivateBrowsing());
}
}
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) { nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
if (!CanSetOriginAttributes()) { return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
return changed ? NS_ERROR_FAILURE : NS_OK;
}
return SetPrivateBrowsing(aUsePrivateBrowsing);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) { nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
MOZ_ASSERT(!mIsBeingDestroyed); return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
if (changed) {
mPrivateBrowsingId = aUsePrivateBrowsing ? 1 : 0;
if (mItemType != typeChrome) {
mOriginAttributes.SyncAttributesWithPrivateBrowsing(aUsePrivateBrowsing);
}
if (mAffectPrivateSessionLifetime) {
if (aUsePrivateBrowsing) {
IncreasePrivateDocShellCount();
} else {
DecreasePrivateDocShellCount();
}
}
}
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
while (iter.HasMore()) {
nsCOMPtr<nsILoadContext> shell = do_QueryObject(iter.GetNext());
if (shell) {
shell->SetPrivateBrowsing(aUsePrivateBrowsing);
}
}
if (changed) {
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
while (iter.HasMore()) {
nsWeakPtr ref = iter.GetNext();
nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
if (!obs) {
mPrivacyObservers.RemoveElement(ref);
} else {
obs->PrivateModeChanged(aUsePrivateBrowsing);
}
}
}
AssertOriginAttributesMatchPrivateBrowsing();
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1596,52 +1571,23 @@ nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) { nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
NS_ENSURE_ARG_POINTER(aUseRemoteTabs); NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
*aUseRemoteTabs = mUseRemoteTabs;
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
if (aUseRemoteTabs) { return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::DOMIPCEnabled,
true);
}
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(!aUseRemoteTabs && mUseRemoteSubframes)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteTabs = aUseRemoteTabs;
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) { nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
NS_ENSURE_ARG_POINTER(aUseRemoteSubframes); NS_ENSURE_ARG_POINTER(aUseRemoteSubframes);
return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
*aUseRemoteSubframes = mUseRemoteSubframes;
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) { nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
static bool annotated = false; return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
if (aUseRemoteSubframes && !annotated) {
annotated = true;
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::DOMFissionEnabled, true);
}
// Don't allow non-remote tabs with remote subframes.
if (NS_WARN_IF(aUseRemoteSubframes && !mUseRemoteTabs)) {
return NS_ERROR_UNEXPECTED;
}
mUseRemoteSubframes = aUseRemoteSubframes;
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1650,7 +1596,6 @@ nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime) {
bool change = aAffectLifetime != mAffectPrivateSessionLifetime; bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
if (change && UsePrivateBrowsing()) { if (change && UsePrivateBrowsing()) {
AssertOriginAttributesMatchPrivateBrowsing();
if (aAffectLifetime) { if (aAffectLifetime) {
IncreasePrivateDocShellCount(); IncreasePrivateDocShellCount();
} else { } else {
@ -1839,18 +1784,6 @@ nsDocShell::SetAllowContentRetargetingOnChildren(
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsDocShell::GetInheritPrivateBrowsingId(bool* aInheritPrivateBrowsingId) {
*aInheritPrivateBrowsingId = mInheritPrivateBrowsingId;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetInheritPrivateBrowsingId(bool aInheritPrivateBrowsingId) {
mInheritPrivateBrowsingId = aInheritPrivateBrowsingId;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed) { nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed) {
NS_ENSURE_ARG_POINTER(aFullscreenAllowed); NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
@ -2629,9 +2562,6 @@ void nsDocShell::RecomputeCanExecuteScripts() {
nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) { nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
bool wasFrame = IsFrame(); bool wasFrame = IsFrame();
#ifdef DEBUG
bool wasPrivate = UsePrivateBrowsing();
#endif
nsresult rv = nsDocLoader::SetDocLoaderParent(aParent); nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -2678,10 +2608,8 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
value = false; value = false;
} }
SetAllowDNSPrefetch(mAllowDNSPrefetch && value); SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
if (mInheritPrivateBrowsingId) { SetAffectPrivateSessionLifetime(
value = parentAsDocShell->GetAffectPrivateSessionLifetime(); parentAsDocShell->GetAffectPrivateSessionLifetime());
SetAffectPrivateSessionLifetime(value);
}
uint32_t flags; uint32_t flags;
if (NS_SUCCEEDED(parentAsDocShell->GetDefaultLoadFlags(&flags))) { if (NS_SUCCEEDED(parentAsDocShell->GetDefaultLoadFlags(&flags))) {
SetDefaultLoadFlags(flags); SetDefaultLoadFlags(flags);
@ -2694,12 +2622,6 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
// like this that might be embedded within it. // like this that might be embedded within it.
} }
nsCOMPtr<nsILoadContext> parentAsLoadContext(do_QueryInterface(parent));
if (parentAsLoadContext && mInheritPrivateBrowsingId &&
NS_SUCCEEDED(parentAsLoadContext->GetUsePrivateBrowsing(&value))) {
SetPrivateBrowsing(value);
}
nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
if (parentURIListener) { if (parentURIListener) {
mContentListener->SetParentContentListener(parentURIListener); mContentListener->SetParentContentListener(parentURIListener);
@ -2713,9 +2635,6 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
MaybeClearStorageAccessFlag(); MaybeClearStorageAccessFlag();
} }
NS_ASSERTION(mInheritPrivateBrowsingId || wasPrivate == UsePrivateBrowsing(),
"Private browsing state changed while inheritance was disabled");
return NS_OK; return NS_OK;
} }
@ -2829,18 +2748,6 @@ nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserBoundaries(
return NS_OK; return NS_OK;
} }
void nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
// Chrome docshells must not have a private browsing OriginAttribute
// Content docshells must maintain the equality:
// mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
if (mItemType == typeChrome) {
MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
} else {
MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId ==
mPrivateBrowsingId);
}
}
bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) { bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) {
// If no target then not sandboxed. // If no target then not sandboxed.
if (!aTargetBC) { if (!aTargetBC) {
@ -3059,9 +2966,6 @@ nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
childDocShell->SetUseGlobalHistory(true); childDocShell->SetUseGlobalHistory(true);
} }
Cast(childDocShell)->SetRemoteTabs(mUseRemoteTabs);
Cast(childDocShell)->SetRemoteSubframes(mUseRemoteSubframes);
if (aChild->ItemType() != mItemType) { if (aChild->ItemType() != mItemType) {
return NS_OK; return NS_OK;
} }
@ -3678,19 +3582,20 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
do_GetService(NS_SSSERVICE_CONTRACTID, &rv); do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags, rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
mOriginAttributes, nullptr, nullptr, &isStsHost); GetOriginAttributes(), nullptr, nullptr,
&isStsHost);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI, flags, rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI, flags,
mOriginAttributes, nullptr, nullptr, GetOriginAttributes(), nullptr, nullptr,
&isPinnedHost); &isPinnedHost);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else { } else {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton(); mozilla::dom::ContentChild::GetSingleton();
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags, cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
mOriginAttributes, &isStsHost); GetOriginAttributes(), &isStsHost);
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI, flags, cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI, flags,
mOriginAttributes, &isPinnedHost); GetOriginAttributes(), &isPinnedHost);
} }
if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert", if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
@ -4449,8 +4354,6 @@ nsDocShell::Destroy() {
NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome, NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
"Unexpected item type in docshell"); "Unexpected item type in docshell");
AssertOriginAttributesMatchPrivateBrowsing();
nsCOMPtr<nsIObserverService> serv = services::GetObserverService(); nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
if (serv) { if (serv) {
const char* msg = mItemType == typeContent const char* msg = mItemType == typeContent
@ -4558,12 +4461,8 @@ nsDocShell::Destroy() {
// to break the cycle between us and the timers. // to break the cycle between us and the timers.
CancelRefreshURITimers(); CancelRefreshURITimers();
if (UsePrivateBrowsing()) { if (UsePrivateBrowsing() && mAffectPrivateSessionLifetime) {
mPrivateBrowsingId = nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID; DecreasePrivateDocShellCount();
mOriginAttributes.SyncAttributesWithPrivateBrowsing(false);
if (mAffectPrivateSessionLifetime) {
DecreasePrivateDocShellCount();
}
} }
return NS_OK; return NS_OK;
@ -5100,7 +4999,6 @@ nsDocShell::SetTitle(const nsAString& aTitle) {
} }
} }
AssertOriginAttributesMatchPrivateBrowsing();
if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) { if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
UpdateGlobalHistoryTitle(mCurrentURI); UpdateGlobalHistoryTitle(mCurrentURI);
} }
@ -6498,7 +6396,8 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
if (aPrincipal && !aPrincipal->IsSystemPrincipal() && if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
mItemType != typeChrome) { mItemType != typeChrome) {
MOZ_ASSERT(aPrincipal->OriginAttributesRef() == mOriginAttributes); MOZ_ASSERT(aPrincipal->OriginAttributesRef() ==
mBrowsingContext->OriginAttributesRef());
} }
// Make sure timing is created. But first record whether we had it // Make sure timing is created. But first record whether we had it
@ -11950,63 +11849,27 @@ nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) { nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow(); return mBrowsingContext->GetTopWindow(aWindow);
if (win) {
win = win->GetInProcessTop();
}
win.forget(aWindow);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetTopFrameElement(Element** aElement) { nsDocShell::GetTopFrameElement(Element** aElement) {
*aElement = nullptr; return mBrowsingContext->GetTopFrameElement(aElement);
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
if (!win) {
return NS_OK;
}
nsCOMPtr<nsPIDOMWindowOuter> top = win->GetInProcessScriptableTop();
NS_ENSURE_TRUE(top, NS_ERROR_FAILURE);
// GetFrameElementInternal, /not/ GetScriptableFrameElement -- if |top| is
// inside <iframe mozbrowser>, we want to return the iframe, not null.
// And we want to cross the content/chrome boundary.
RefPtr<Element> elt = top->GetFrameElementInternal();
elt.forget(aElement);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetNestedFrameId(uint64_t* aId) { nsDocShell::GetNestedFrameId(uint64_t* aId) {
*aId = 0; return mBrowsingContext->GetNestedFrameId(aId);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) { nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
*aUseTrackingProtection = false; return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
if (mUseTrackingProtection ||
StaticPrefs::privacy_trackingprotection_enabled() ||
(UsePrivateBrowsing() &&
StaticPrefs::privacy_trackingprotection_pbmode_enabled())) {
*aUseTrackingProtection = true;
return NS_OK;
}
RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
if (parent) {
return parent->GetUseTrackingProtection(aUseTrackingProtection);
}
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) { nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
mUseTrackingProtection = aUseTrackingProtection; return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -12642,42 +12505,14 @@ NS_IMETHODIMP nsDocShell::GetIsTopLevelContentDocShell(
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetScriptableOriginAttributes(JSContext* aCx, nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) { JS::MutableHandle<JS::Value> aVal) {
return GetOriginAttributes(aCx, aVal); return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
} }
// Implements nsIDocShell.GetOriginAttributes() // Implements nsIDocShell.GetOriginAttributes()
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetOriginAttributes(JSContext* aCx, nsDocShell::GetOriginAttributes(JSContext* aCx,
JS::MutableHandle<JS::Value> aVal) { JS::MutableHandle<JS::Value> aVal) {
bool ok = ToJSValue(aCx, mOriginAttributes, aVal); return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
return NS_OK;
}
bool nsDocShell::CanSetOriginAttributes() {
MOZ_ASSERT(mChildList.IsEmpty());
if (!mChildList.IsEmpty()) {
return false;
}
// TODO: Bug 1273058 - mContentViewer should be null when setting origin
// attributes.
if (mContentViewer) {
Document* doc = mContentViewer->GetDocument();
if (doc) {
nsIURI* uri = doc->GetDocumentURI();
if (!uri) {
return false;
}
nsCString uriSpec = uri->GetSpecOrDefault();
MOZ_ASSERT(uriSpec.EqualsLiteral("about:blank"));
if (!uriSpec.EqualsLiteral("about:blank")) {
return false;
}
}
}
return true;
} }
bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal, bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
@ -12703,26 +12538,7 @@ bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) { nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
MOZ_ASSERT(!mIsBeingDestroyed); MOZ_ASSERT(!mIsBeingDestroyed);
return mBrowsingContext->SetOriginAttributes(aAttrs);
if (!CanSetOriginAttributes()) {
return NS_ERROR_FAILURE;
}
AssertOriginAttributesMatchPrivateBrowsing();
mOriginAttributes = aAttrs;
bool isPrivate = mOriginAttributes.mPrivateBrowsingId !=
nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
// Chrome docshell can not contain OriginAttributes.mPrivateBrowsingId
if (mItemType == typeChrome && isPrivate) {
mOriginAttributes.mPrivateBrowsingId =
nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID;
}
SetPrivateBrowsing(isPrivate);
AssertOriginAttributesMatchPrivateBrowsing();
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -13029,7 +12845,7 @@ nsDocShell::GetAwaitingLargeAlloc(bool* aResult) {
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) { nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
aAttrs = mOriginAttributes; mBrowsingContext->GetOriginAttributes(aAttrs);
} }
HTMLEditor* nsIDocShell::GetHTMLEditor() { HTMLEditor* nsIDocShell::GetHTMLEditor() {

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

@ -430,7 +430,7 @@ class nsDocShell final : public nsDocLoader,
} }
const mozilla::OriginAttributes& GetOriginAttributes() { const mozilla::OriginAttributes& GetOriginAttributes() {
return mOriginAttributes; return mBrowsingContext->OriginAttributesRef();
} }
// Determine whether this docshell corresponds to the given history entry, // Determine whether this docshell corresponds to the given history entry,
@ -989,10 +989,6 @@ class nsDocShell final : public nsDocLoader,
// Convenience method for getting our parent docshell. Can return null // Convenience method for getting our parent docshell. Can return null
already_AddRefed<nsDocShell> GetInProcessParentDocshell(); already_AddRefed<nsDocShell> GetInProcessParentDocshell();
// Helper assertion to enforce that mInPrivateBrowsing is in sync with
// OriginAttributes.mPrivateBrowsingId
void AssertOriginAttributesMatchPrivateBrowsing();
// Internal implementation of nsIDocShell::FirePageHideNotification. // Internal implementation of nsIDocShell::FirePageHideNotification.
// If aSkipCheckingDynEntries is true, it will not try to remove dynamic // If aSkipCheckingDynEntries is true, it will not try to remove dynamic
// subframe entries. This is to avoid redundant RemoveDynEntries calls in all // subframe entries. This is to avoid redundant RemoveDynEntries calls in all
@ -1096,6 +1092,9 @@ class nsDocShell final : public nsDocLoader,
nsresult HandleSameDocumentNavigation(nsDocShellLoadState* aLoadState, nsresult HandleSameDocumentNavigation(nsDocShellLoadState* aLoadState,
SameDocumentNavigationState& aState); SameDocumentNavigationState& aState);
// Called when the Private Browsing state of a nsDocShell changes.
void NotifyPrivateBrowsingChanged();
private: // data members private: // data members
static nsIURIFixup* sURIFixup; static nsIURIFixup* sURIFixup;
@ -1111,7 +1110,6 @@ class nsDocShell final : public nsDocLoader,
nsTObserverArray<nsWeakPtr> mPrivacyObservers; nsTObserverArray<nsWeakPtr> mPrivacyObservers;
nsTObserverArray<nsWeakPtr> mReflowObservers; nsTObserverArray<nsWeakPtr> mReflowObservers;
nsTObserverArray<nsWeakPtr> mScrollObservers; nsTObserverArray<nsWeakPtr> mScrollObservers;
mozilla::OriginAttributes mOriginAttributes;
mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource; mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
nsCOMPtr<nsINetworkInterceptController> mInterceptController; nsCOMPtr<nsINetworkInterceptController> mInterceptController;
RefPtr<nsDOMNavigationTiming> mTiming; RefPtr<nsDOMNavigationTiming> mTiming;
@ -1242,13 +1240,6 @@ class nsDocShell final : public nsDocLoader,
// Are we a regular frame, a browser frame, or an app frame? // Are we a regular frame, a browser frame, or an app frame?
FrameType mFrameType; FrameType mFrameType;
// This represents the state of private browsing in the docshell.
// Currently treated as a binary value: 1 - in private mode, 0 - not private
// mode On content docshells mPrivateBrowsingId ==
// mOriginAttributes.mPrivateBrowsingId On chrome docshells this value will be
// set, but not have the corresponding origin attribute set.
uint32_t mPrivateBrowsingId;
// This represents the CSS display-mode we are currently using. This is mostly // This represents the CSS display-mode we are currently using. This is mostly
// used for media queries. // used for media queries.
DisplayMode mDisplayMode; DisplayMode mDisplayMode;
@ -1308,13 +1299,9 @@ class nsDocShell final : public nsDocLoader,
bool mDisableMetaRefreshWhenInactive : 1; bool mDisableMetaRefreshWhenInactive : 1;
bool mIsAppTab : 1; bool mIsAppTab : 1;
bool mUseGlobalHistory : 1; bool mUseGlobalHistory : 1;
bool mUseRemoteTabs : 1;
bool mUseRemoteSubframes : 1;
bool mUseTrackingProtection : 1;
bool mDeviceSizeIsPageSize : 1; bool mDeviceSizeIsPageSize : 1;
bool mWindowDraggingAllowed : 1; bool mWindowDraggingAllowed : 1;
bool mInFrameSwap : 1; bool mInFrameSwap : 1;
bool mInheritPrivateBrowsingId : 1;
// Because scriptability depends on the mAllowJavascript values of our // Because scriptability depends on the mAllowJavascript values of our
// ancestors, we cache the effective scriptability and recompute it when // ancestors, we cache the effective scriptability and recompute it when

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

@ -238,15 +238,6 @@ interface nsIDocShell : nsIDocShellTreeItem
*/ */
[infallible] attribute boolean allowContentRetargetingOnChildren; [infallible] attribute boolean allowContentRetargetingOnChildren;
/**
* True if this docShell should inherit the private browsing ID from
* its parent when reparented.
*
* NOTE: This should *not* be set false in new code, or for docShells
* inserted anywhere other than as children of panels.
*/
[infallible] attribute boolean inheritPrivateBrowsingId;
/** /**
* Get an array of this docShell and its children. * Get an array of this docShell and its children.
* *

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

@ -2049,7 +2049,9 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
mPendingBrowsingContext->EnsureAttached(); if (!EnsureBrowsingContextAttached()) {
return NS_ERROR_FAILURE;
}
// nsDocShell::Create will attach itself to the passed browsing // nsDocShell::Create will attach itself to the passed browsing
// context inside of nsDocShell::Create // context inside of nsDocShell::Create
@ -2137,37 +2139,6 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
OriginAttributes attrs;
if (parentDocShell->ItemType() == docShell->ItemType()) {
attrs = parentDocShell->GetOriginAttributes();
}
// Inherit origin attributes from parent document if
// 1. It's in a content docshell.
// 2. its nodePrincipal is not a SystemPrincipal.
// 3. It's not a mozbrowser frame.
//
// For example, firstPartyDomain is computed from top-level document, it
// doesn't exist in the top-level docshell.
if (parentIsContent && !doc->NodePrincipal()->IsSystemPrincipal() &&
!OwnerIsMozBrowserFrame()) {
OriginAttributes oa = doc->NodePrincipal()->OriginAttributesRef();
// Assert on the firstPartyDomain from top-level docshell should be empty
MOZ_ASSERT_IF(mIsTopLevelContent, attrs.mFirstPartyDomain.IsEmpty());
// So far we want to make sure Inherit doesn't override any other origin
// attribute than firstPartyDomain.
MOZ_ASSERT(
attrs.mUserContextId == oa.mUserContextId,
"docshell and document should have the same userContextId attribute.");
MOZ_ASSERT(attrs.mPrivateBrowsingId == oa.mPrivateBrowsingId,
"docshell and document should have the same privateBrowsingId "
"attribute.");
attrs = oa;
}
if (OwnerIsMozBrowserFrame()) { if (OwnerIsMozBrowserFrame()) {
docShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER); docShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
} else if (mPendingBrowsingContext->GetParent()) { } else if (mPendingBrowsingContext->GetParent()) {
@ -2185,19 +2156,6 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
} }
ApplySandboxFlags(sandboxFlags); ApplySandboxFlags(sandboxFlags);
// Grab the userContextId from owner
nsresult rv = PopulateOriginContextIdsFromAttributes(attrs);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool isPrivate = false;
rv = parentDocShell->GetUsePrivateBrowsing(&isPrivate);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
if (OwnerIsMozBrowserFrame()) { if (OwnerIsMozBrowserFrame()) {
// For inproc frames, set the docshell properties. // For inproc frames, set the docshell properties.
nsAutoString name; nsAutoString name;
@ -2208,25 +2166,8 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) || mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
mOwnerContent->HasAttr(kNameSpaceID_None, mOwnerContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozallowfullscreen)); nsGkAtoms::mozallowfullscreen));
bool isPrivate = mOwnerContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozprivatebrowsing);
if (isPrivate) {
if (docShell->GetHasLoadedNonBlankURI()) {
nsContentUtils::ReportToConsoleNonLocalized(
NS_LITERAL_STRING("We should not switch to Private Browsing after "
"loading a document."),
nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("mozprivatebrowsing"), nullptr);
} else {
// This handles the case where a frames private browsing is set by
// chrome flags and not inherited by its parent.
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
}
}
} }
docShell->SetOriginAttributes(attrs);
// Typically there will be a window, however for some cases such as printing // Typically there will be a window, however for some cases such as printing
// the document is cloned with a docshell that has no window. We check // the document is cloned with a docshell that has no window. We check
// that the window exists to ensure we don't try to gather ancestors for // that the window exists to ensure we don't try to gather ancestors for
@ -2537,7 +2478,9 @@ bool nsFrameLoader::TryRemoteBrowserInternal() {
return false; return false;
} }
mPendingBrowsingContext->EnsureAttached(); if (!EnsureBrowsingContextAttached()) {
return false;
}
RefPtr<ContentParent> openerContentParent; RefPtr<ContentParent> openerContentParent;
RefPtr<nsIPrincipal> openerContentPrincipal; RefPtr<nsIPrincipal> openerContentPrincipal;
@ -3576,3 +3519,88 @@ void nsFrameLoader::MaybeNotifyCrashed(BrowsingContext* aBrowsingContext,
EventDispatcher::DispatchDOMEvent(mOwnerContent, nullptr, event, nullptr, EventDispatcher::DispatchDOMEvent(mOwnerContent, nullptr, event, nullptr,
nullptr); nullptr);
} }
bool nsFrameLoader::EnsureBrowsingContextAttached() {
nsresult rv;
Document* parentDoc = mOwnerContent->OwnerDoc();
MOZ_ASSERT(parentDoc);
BrowsingContext* parentContext = parentDoc->GetBrowsingContext();
MOZ_ASSERT(parentContext);
// Inherit the `use` flags from our parent BrowsingContext.
bool usePrivateBrowsing = parentContext->UsePrivateBrowsing();
bool useRemoteSubframes = parentContext->UseRemoteSubframes();
bool useRemoteTabs = parentContext->UseRemoteTabs();
// Determine the exact OriginAttributes which should be used for our
// BrowsingContext. This will be used to initialize OriginAttributes if the
// BrowsingContext has not already been created.
OriginAttributes attrs;
if (mPendingBrowsingContext->IsContent()) {
if (mPendingBrowsingContext->GetParent()) {
MOZ_ASSERT(mPendingBrowsingContext->GetParent() == parentContext);
parentContext->GetOriginAttributes(attrs);
}
// Inherit the `mFirstPartyDomain` flag from our parent document's result
// principal, if it was set.
if (parentContext->IsContent() &&
!parentDoc->NodePrincipal()->IsSystemPrincipal() &&
!OwnerIsMozBrowserFrame()) {
OriginAttributes docAttrs =
parentDoc->NodePrincipal()->OriginAttributesRef();
// We only want to inherit firstPartyDomain here, other attributes should
// be constant.
MOZ_ASSERT(attrs.EqualsIgnoringFPD(docAttrs));
attrs.mFirstPartyDomain = docAttrs.mFirstPartyDomain;
}
// Inherit the PrivateBrowsing flag across content/chrome boundaries.
attrs.SyncAttributesWithPrivateBrowsing(usePrivateBrowsing);
// A <browser> element may have overridden userContextId or
// geckoViewUserContextId.
rv = PopulateOriginContextIdsFromAttributes(attrs);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
// <iframe mozbrowser> is allowed to set `mozprivatebrowsing` to
// force-enable private browsing.
if (OwnerIsMozBrowserFrame()) {
if (mOwnerContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozprivatebrowsing)) {
attrs.SyncAttributesWithPrivateBrowsing(true);
usePrivateBrowsing = true;
}
}
}
// If we've already been attached, return.
if (mPendingBrowsingContext->EverAttached()) {
MOZ_DIAGNOSTIC_ASSERT(mPendingBrowsingContext->UsePrivateBrowsing() ==
usePrivateBrowsing);
MOZ_DIAGNOSTIC_ASSERT(mPendingBrowsingContext->UseRemoteTabs() ==
useRemoteTabs);
MOZ_DIAGNOSTIC_ASSERT(mPendingBrowsingContext->UseRemoteSubframes() ==
useRemoteSubframes);
// Don't assert that our OriginAttributes match, as we could have different
// OriginAttributes in the case where we were opened using window.open.
return true;
}
// Initialize non-synced OriginAttributes and related fields.
rv = mPendingBrowsingContext->SetOriginAttributes(attrs);
NS_ENSURE_SUCCESS(rv, false);
rv = mPendingBrowsingContext->SetUsePrivateBrowsing(usePrivateBrowsing);
NS_ENSURE_SUCCESS(rv, false);
rv = mPendingBrowsingContext->SetRemoteTabs(useRemoteTabs);
NS_ENSURE_SUCCESS(rv, false);
rv = mPendingBrowsingContext->SetRemoteSubframes(useRemoteSubframes);
NS_ENSURE_SUCCESS(rv, false);
// Finish attaching.
mPendingBrowsingContext->EnsureAttached();
return true;
}

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

@ -470,6 +470,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
nsresult PopulateOriginContextIdsFromAttributes( nsresult PopulateOriginContextIdsFromAttributes(
mozilla::OriginAttributes& aAttr); mozilla::OriginAttributes& aAttr);
bool EnsureBrowsingContextAttached();
RefPtr<mozilla::dom::BrowsingContext> mPendingBrowsingContext; RefPtr<mozilla::dom::BrowsingContext> mPendingBrowsingContext;
nsCOMPtr<nsIURI> mURIToLoad; nsCOMPtr<nsIURI> mURIToLoad;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;