mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	Depends on D199114 Differential Revision: https://phabricator.services.mozilla.com/D199115
		
			
				
	
	
		
			697 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			697 lines
		
	
	
	
		
			24 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/. */
 | 
						|
 | 
						|
#include "mozilla/dom/WindowContext.h"
 | 
						|
#include "mozilla/dom/WindowGlobalActorsBinding.h"
 | 
						|
#include "mozilla/dom/WindowGlobalChild.h"
 | 
						|
#include "mozilla/dom/WindowGlobalParent.h"
 | 
						|
#include "mozilla/dom/SyncedContextInlines.h"
 | 
						|
#include "mozilla/dom/BrowsingContext.h"
 | 
						|
#include "mozilla/dom/Document.h"
 | 
						|
#include "mozilla/dom/UserActivationIPCUtils.h"
 | 
						|
#include "mozilla/PermissionDelegateIPCUtils.h"
 | 
						|
#include "mozilla/RFPTargetIPCUtils.h"
 | 
						|
#include "mozilla/StaticPrefs_dom.h"
 | 
						|
#include "mozilla/StaticPtr.h"
 | 
						|
#include "mozilla/ClearOnShutdown.h"
 | 
						|
#include "nsGlobalWindowInner.h"
 | 
						|
#include "nsIScriptError.h"
 | 
						|
#include "nsIWebProgressListener.h"
 | 
						|
#include "nsIXULRuntime.h"
 | 
						|
#include "nsRefPtrHashtable.h"
 | 
						|
#include "nsContentUtils.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace dom {
 | 
						|
 | 
						|
// Explicit specialization of the `Transaction` type. Required by the `extern
 | 
						|
// template class` declaration in the header.
 | 
						|
template class syncedcontext::Transaction<WindowContext>;
 | 
						|
 | 
						|
static LazyLogModule gWindowContextLog("WindowContext");
 | 
						|
static LazyLogModule gWindowContextSyncLog("WindowContextSync");
 | 
						|
 | 
						|
extern mozilla::LazyLogModule gUserInteractionPRLog;
 | 
						|
 | 
						|
#define USER_ACTIVATION_LOG(msg, ...) \
 | 
						|
  MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
 | 
						|
 | 
						|
using WindowContextByIdMap = nsTHashMap<nsUint64HashKey, WindowContext*>;
 | 
						|
static StaticAutoPtr<WindowContextByIdMap> gWindowContexts;
 | 
						|
 | 
						|
/* static */
 | 
						|
LogModule* WindowContext::GetLog() { return gWindowContextLog; }
 | 
						|
 | 
						|
/* static */
 | 
						|
LogModule* WindowContext::GetSyncLog() { return gWindowContextSyncLog; }
 | 
						|
 | 
						|
/* static */
 | 
						|
already_AddRefed<WindowContext> WindowContext::GetById(
 | 
						|
    uint64_t aInnerWindowId) {
 | 
						|
  if (!gWindowContexts) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  return do_AddRef(gWindowContexts->Get(aInnerWindowId));
 | 
						|
}
 | 
						|
 | 
						|
BrowsingContextGroup* WindowContext::Group() const {
 | 
						|
  return mBrowsingContext->Group();
 | 
						|
}
 | 
						|
 | 
						|
WindowGlobalParent* WindowContext::Canonical() {
 | 
						|
  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
 | 
						|
  return static_cast<WindowGlobalParent*>(this);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::IsCurrent() const {
 | 
						|
  return mBrowsingContext->mCurrentWindowContext == this;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::IsInBFCache() {
 | 
						|
  if (mozilla::SessionHistoryInParent()) {
 | 
						|
    return mBrowsingContext->IsInBFCache();
 | 
						|
  }
 | 
						|
  return TopWindowContext()->GetWindowStateSaved();
 | 
						|
}
 | 
						|
 | 
						|
nsGlobalWindowInner* WindowContext::GetInnerWindow() const {
 | 
						|
  return mWindowGlobalChild ? mWindowGlobalChild->GetWindowGlobal() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
Document* WindowContext::GetDocument() const {
 | 
						|
  nsGlobalWindowInner* innerWindow = GetInnerWindow();
 | 
						|
  return innerWindow ? innerWindow->GetDocument() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
Document* WindowContext::GetExtantDoc() const {
 | 
						|
  nsGlobalWindowInner* innerWindow = GetInnerWindow();
 | 
						|
  return innerWindow ? innerWindow->GetExtantDoc() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
WindowGlobalChild* WindowContext::GetWindowGlobalChild() const {
 | 
						|
  return mWindowGlobalChild;
 | 
						|
}
 | 
						|
 | 
						|
WindowContext* WindowContext::GetParentWindowContext() {
 | 
						|
  return mBrowsingContext->GetParentWindowContext();
 | 
						|
}
 | 
						|
 | 
						|
WindowContext* WindowContext::TopWindowContext() {
 | 
						|
  WindowContext* current = this;
 | 
						|
  while (current->GetParentWindowContext()) {
 | 
						|
    current = current->GetParentWindowContext();
 | 
						|
  }
 | 
						|
  return current;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::IsTop() const { return mBrowsingContext->IsTop(); }
 | 
						|
 | 
						|
bool WindowContext::SameOriginWithTop() const {
 | 
						|
  return mBrowsingContext->SameOriginWithTop();
 | 
						|
}
 | 
						|
 | 
						|
nsIGlobalObject* WindowContext::GetParentObject() const {
 | 
						|
  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::AppendChildBrowsingContext(
 | 
						|
    BrowsingContext* aBrowsingContext) {
 | 
						|
  MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
 | 
						|
                        "Mismatched groups?");
 | 
						|
  MOZ_DIAGNOSTIC_ASSERT(!mChildren.Contains(aBrowsingContext));
 | 
						|
 | 
						|
  mChildren.AppendElement(aBrowsingContext);
 | 
						|
  if (!aBrowsingContext->IsEmbedderTypeObjectOrEmbed()) {
 | 
						|
    mNonSyntheticChildren.AppendElement(aBrowsingContext);
 | 
						|
  }
 | 
						|
 | 
						|
  // If we're the current WindowContext in our BrowsingContext, make sure to
 | 
						|
  // clear any cached `children` value.
 | 
						|
  if (IsCurrent()) {
 | 
						|
    BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::RemoveChildBrowsingContext(
 | 
						|
    BrowsingContext* aBrowsingContext) {
 | 
						|
  MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
 | 
						|
                        "Mismatched groups?");
 | 
						|
 | 
						|
  mChildren.RemoveElement(aBrowsingContext);
 | 
						|
  mNonSyntheticChildren.RemoveElement(aBrowsingContext);
 | 
						|
 | 
						|
  // If we're the current WindowContext in our BrowsingContext, make sure to
 | 
						|
  // clear any cached `children` value.
 | 
						|
  if (IsCurrent()) {
 | 
						|
    BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::UpdateChildSynthetic(BrowsingContext* aBrowsingContext,
 | 
						|
                                         bool aIsSynthetic) {
 | 
						|
  if (aIsSynthetic) {
 | 
						|
    mNonSyntheticChildren.RemoveElement(aBrowsingContext);
 | 
						|
  } else {
 | 
						|
    // The same BrowsingContext will be reused for error pages, so it can be in
 | 
						|
    // the list already.
 | 
						|
    if (!mNonSyntheticChildren.Contains(aBrowsingContext)) {
 | 
						|
      mNonSyntheticChildren.AppendElement(aBrowsingContext);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::SendCommitTransaction(ContentParent* aParent,
 | 
						|
                                          const BaseTransaction& aTxn,
 | 
						|
                                          uint64_t aEpoch) {
 | 
						|
  Unused << aParent->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::SendCommitTransaction(ContentChild* aChild,
 | 
						|
                                          const BaseTransaction& aTxn,
 | 
						|
                                          uint64_t aEpoch) {
 | 
						|
  aChild->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CheckOnlyOwningProcessCanSet(ContentParent* aSource) {
 | 
						|
  if (IsInProcess()) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (XRE_IsParentProcess() && aSource) {
 | 
						|
    return Canonical()->GetContentParent() == aSource;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsSecure>, const bool& aIsSecure,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_AllowMixedContent>,
 | 
						|
                           const bool& aAllowMixedContent,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_HasBeforeUnload>,
 | 
						|
                           const bool& aHasBeforeUnload,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_CookieBehavior>,
 | 
						|
                           const Maybe<uint32_t>& aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsOnContentBlockingAllowList>,
 | 
						|
                           const bool& aValue, ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsThirdPartyWindow>,
 | 
						|
                           const bool& IsThirdPartyWindow,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsThirdPartyTrackingResourceWindow>,
 | 
						|
                           const bool& aIsThirdPartyTrackingResourceWindow,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_UsingStorageAccess>,
 | 
						|
                           const bool& aUsingStorageAccess,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
 | 
						|
                           const bool& aShouldResistFingerprinting,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>,
 | 
						|
                           const Maybe<RFPTarget>& aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsSecureContext>,
 | 
						|
                           const bool& aIsSecureContext,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsOriginalFrameSource>,
 | 
						|
                           const bool& aIsOriginalFrameSource,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_DocTreeHadMedia>, const bool& aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return IsTop();
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_AutoplayPermission>,
 | 
						|
                           const uint32_t& aValue, ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_ShortcutsPermission>,
 | 
						|
                           const uint32_t& aValue, ContentParent* aSource) {
 | 
						|
  return IsTop() && CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_ActiveMediaSessionContextId>,
 | 
						|
                           const Maybe<uint64_t>& aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return IsTop();
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_PopupPermission>, const uint32_t&,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(
 | 
						|
    FieldIndex<IDX_DelegatedPermissions>,
 | 
						|
    const PermissionDelegateHandler::DelegatedPermissionList& aValue,
 | 
						|
    ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(
 | 
						|
    FieldIndex<IDX_DelegatedExactHostMatchPermissions>,
 | 
						|
    const PermissionDelegateHandler::DelegatedPermissionList& aValue,
 | 
						|
    ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_AllowJavascript>, bool aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return (XRE_IsParentProcess() && !aSource) ||
 | 
						|
         CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::DidSet(FieldIndex<IDX_AllowJavascript>, bool aOldValue) {
 | 
						|
  RecomputeCanExecuteScripts();
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_HasActivePeerConnections>, bool,
 | 
						|
                           ContentParent*) {
 | 
						|
  return XRE_IsParentProcess() && IsTop();
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::RecomputeCanExecuteScripts(bool aApplyChanges) {
 | 
						|
  const bool old = mCanExecuteScripts;
 | 
						|
  if (!AllowJavascript()) {
 | 
						|
    // Scripting has been explicitly disabled on our WindowContext.
 | 
						|
    mCanExecuteScripts = false;
 | 
						|
  } else {
 | 
						|
    // Otherwise, inherit.
 | 
						|
    mCanExecuteScripts = mBrowsingContext->CanExecuteScripts();
 | 
						|
  }
 | 
						|
 | 
						|
  if (aApplyChanges && old != mCanExecuteScripts) {
 | 
						|
    // Inform our active DOM window.
 | 
						|
    if (nsGlobalWindowInner* window = GetInnerWindow()) {
 | 
						|
      // Only update scriptability if the window is current. Windows will have
 | 
						|
      // scriptability disabled when entering the bfcache and updated when
 | 
						|
      // coming out.
 | 
						|
      if (window->IsCurrentInnerWindow()) {
 | 
						|
        auto& scriptability =
 | 
						|
            xpc::Scriptability::Get(window->GetGlobalJSObject());
 | 
						|
        scriptability.SetWindowAllowsScript(mCanExecuteScripts);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    for (const RefPtr<BrowsingContext>& child : Children()) {
 | 
						|
      child->RecomputeCanExecuteScripts();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>,
 | 
						|
                           bool aOldValue) {
 | 
						|
  MOZ_ASSERT(
 | 
						|
      TopWindowContext() == this,
 | 
						|
      "SHEntryHasUserInteraction can only be set on the top window context");
 | 
						|
  // This field is set when the child notifies us of new user interaction, so we
 | 
						|
  // also set the currently active shentry in the parent as having interaction.
 | 
						|
  if (XRE_IsParentProcess() && mBrowsingContext) {
 | 
						|
    SessionHistoryEntry* activeEntry =
 | 
						|
        mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
 | 
						|
    if (activeEntry && GetSHEntryHasUserInteraction()) {
 | 
						|
      activeEntry->SetHasUserInteraction(true);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::DidSet(FieldIndex<IDX_UserActivationStateAndModifiers>) {
 | 
						|
  MOZ_ASSERT_IF(!IsInProcess(), mUserGestureStart.IsNull());
 | 
						|
  USER_ACTIVATION_LOG("Set user gesture activation 0x%02" PRIu8
 | 
						|
                      " for %s browsing context 0x%08" PRIx64,
 | 
						|
                      GetUserActivationStateAndModifiers(),
 | 
						|
                      XRE_IsParentProcess() ? "Parent" : "Child", Id());
 | 
						|
  if (IsInProcess()) {
 | 
						|
    USER_ACTIVATION_LOG(
 | 
						|
        "Set user gesture start time for %s browsing context 0x%08" PRIx64,
 | 
						|
        XRE_IsParentProcess() ? "Parent" : "Child", Id());
 | 
						|
    if (GetUserActivationState() == UserActivation::State::FullActivated) {
 | 
						|
      mUserGestureStart = TimeStamp::Now();
 | 
						|
    } else if (GetUserActivationState() == UserActivation::State::None) {
 | 
						|
      mUserGestureStart = TimeStamp();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::DidSet(FieldIndex<IDX_HasReportedShadowDOMUsage>,
 | 
						|
                           bool aOldValue) {
 | 
						|
  if (!aOldValue && GetHasReportedShadowDOMUsage() && IsInProcess()) {
 | 
						|
    MOZ_ASSERT(TopWindowContext() == this);
 | 
						|
    if (mBrowsingContext) {
 | 
						|
      Document* topLevelDoc = mBrowsingContext->GetDocument();
 | 
						|
      if (topLevelDoc) {
 | 
						|
        nsAutoString uri;
 | 
						|
        Unused << topLevelDoc->GetDocumentURI(uri);
 | 
						|
        if (!uri.IsEmpty()) {
 | 
						|
          nsAutoString msg = u"Shadow DOM used in ["_ns + uri +
 | 
						|
                             u"] or in some of its subdocuments."_ns;
 | 
						|
          nsContentUtils::ReportToConsoleNonLocalized(
 | 
						|
              msg, nsIScriptError::infoFlag, "DOM"_ns, topLevelDoc);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanSet(FieldIndex<IDX_WindowStateSaved>, bool aValue,
 | 
						|
                           ContentParent* aSource) {
 | 
						|
  return !mozilla::SessionHistoryInParent() && IsTop() &&
 | 
						|
         CheckOnlyOwningProcessCanSet(aSource);
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::CreateFromIPC(IPCInitializer&& aInit) {
 | 
						|
  MOZ_RELEASE_ASSERT(XRE_IsContentProcess(),
 | 
						|
                     "Should be a WindowGlobalParent in the parent");
 | 
						|
 | 
						|
  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
 | 
						|
  MOZ_RELEASE_ASSERT(bc);
 | 
						|
 | 
						|
  if (bc->IsDiscarded()) {
 | 
						|
    // If we have already closed our browsing context, the
 | 
						|
    // WindowGlobalChild actor is bound to be destroyed soon and it's
 | 
						|
    // safe to ignore creating the WindowContext.
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<WindowContext> context = new WindowContext(
 | 
						|
      bc, aInit.mInnerWindowId, aInit.mOuterWindowId, std::move(aInit.mFields));
 | 
						|
  context->Init();
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::Init() {
 | 
						|
  MOZ_LOG(GetLog(), LogLevel::Debug,
 | 
						|
          ("Registering 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
 | 
						|
           mBrowsingContext->Id()));
 | 
						|
 | 
						|
  // Register the WindowContext in the `WindowContextByIdMap`.
 | 
						|
  if (!gWindowContexts) {
 | 
						|
    gWindowContexts = new WindowContextByIdMap();
 | 
						|
    ClearOnShutdown(&gWindowContexts);
 | 
						|
  }
 | 
						|
  auto& entry = gWindowContexts->LookupOrInsert(mInnerWindowId);
 | 
						|
  MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowContext for ID!");
 | 
						|
  entry = this;
 | 
						|
 | 
						|
  // Register this to the browsing context.
 | 
						|
  mBrowsingContext->RegisterWindowContext(this);
 | 
						|
  Group()->Register(this);
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::Discard() {
 | 
						|
  MOZ_LOG(GetLog(), LogLevel::Debug,
 | 
						|
          ("Discarding 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
 | 
						|
           mBrowsingContext->Id()));
 | 
						|
  if (mIsDiscarded) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mIsDiscarded = true;
 | 
						|
  if (gWindowContexts) {
 | 
						|
    gWindowContexts->Remove(InnerWindowId());
 | 
						|
  }
 | 
						|
  mBrowsingContext->UnregisterWindowContext(this);
 | 
						|
  Group()->Unregister(this);
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::AddSecurityState(uint32_t aStateFlags) {
 | 
						|
  MOZ_ASSERT(TopWindowContext() == this);
 | 
						|
  MOZ_ASSERT((aStateFlags &
 | 
						|
              (nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
 | 
						|
               nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
 | 
						|
               nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT |
 | 
						|
               nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT |
 | 
						|
               nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED |
 | 
						|
               nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADE_FAILED |
 | 
						|
               nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED_FIRST)) ==
 | 
						|
                 aStateFlags,
 | 
						|
             "Invalid flags specified!");
 | 
						|
 | 
						|
  if (XRE_IsParentProcess()) {
 | 
						|
    Canonical()->AddSecurityState(aStateFlags);
 | 
						|
  } else {
 | 
						|
    ContentChild* child = ContentChild::GetSingleton();
 | 
						|
    child->SendAddSecurityState(this, aStateFlags);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::NotifyUserGestureActivation(
 | 
						|
    UserActivation::Modifiers
 | 
						|
        aModifiers /* = UserActivation::Modifiers::None() */) {
 | 
						|
  UserActivation::StateAndModifiers stateAndModifiers;
 | 
						|
  stateAndModifiers.SetState(UserActivation::State::FullActivated);
 | 
						|
  stateAndModifiers.SetModifiers(aModifiers);
 | 
						|
  Unused << SetUserActivationStateAndModifiers(stateAndModifiers.GetRawData());
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::NotifyResetUserGestureActivation() {
 | 
						|
  UserActivation::StateAndModifiers stateAndModifiers;
 | 
						|
  stateAndModifiers.SetState(UserActivation::State::None);
 | 
						|
  Unused << SetUserActivationStateAndModifiers(stateAndModifiers.GetRawData());
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::HasBeenUserGestureActivated() {
 | 
						|
  return GetUserActivationState() != UserActivation::State::None;
 | 
						|
}
 | 
						|
 | 
						|
const TimeStamp& WindowContext::GetUserGestureStart() const {
 | 
						|
  MOZ_ASSERT(IsInProcess());
 | 
						|
  return mUserGestureStart;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::HasValidTransientUserGestureActivation() {
 | 
						|
  MOZ_ASSERT(IsInProcess());
 | 
						|
 | 
						|
  if (GetUserActivationState() != UserActivation::State::FullActivated) {
 | 
						|
    // mUserGestureStart should be null if the document hasn't ever been
 | 
						|
    // activated by user gesture
 | 
						|
    MOZ_ASSERT_IF(GetUserActivationState() == UserActivation::State::None,
 | 
						|
                  mUserGestureStart.IsNull());
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  MOZ_ASSERT(!mUserGestureStart.IsNull(),
 | 
						|
             "mUserGestureStart shouldn't be null if the document has ever "
 | 
						|
             "been activated by user gesture");
 | 
						|
  TimeDuration timeout = TimeDuration::FromMilliseconds(
 | 
						|
      StaticPrefs::dom_user_activation_transient_timeout());
 | 
						|
 | 
						|
  return timeout <= TimeDuration() ||
 | 
						|
         (TimeStamp::Now() - mUserGestureStart) <= timeout;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::ConsumeTransientUserGestureActivation() {
 | 
						|
  MOZ_ASSERT(IsInProcess());
 | 
						|
  MOZ_ASSERT(IsCurrent());
 | 
						|
 | 
						|
  if (!HasValidTransientUserGestureActivation()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  BrowsingContext* top = mBrowsingContext->Top();
 | 
						|
  top->PreOrderWalk([&](BrowsingContext* aBrowsingContext) {
 | 
						|
    WindowContext* windowContext = aBrowsingContext->GetCurrentWindowContext();
 | 
						|
    if (windowContext && windowContext->GetUserActivationState() ==
 | 
						|
                             UserActivation::State::FullActivated) {
 | 
						|
      auto stateAndModifiers = UserActivation::StateAndModifiers(
 | 
						|
          GetUserActivationStateAndModifiers());
 | 
						|
      stateAndModifiers.SetState(UserActivation::State::HasBeenActivated);
 | 
						|
      Unused << windowContext->SetUserActivationStateAndModifiers(
 | 
						|
          stateAndModifiers.GetRawData());
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::GetTransientUserGestureActivationModifiers(
 | 
						|
    UserActivation::Modifiers* aModifiers) {
 | 
						|
  if (!HasValidTransientUserGestureActivation()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  auto stateAndModifiers =
 | 
						|
      UserActivation::StateAndModifiers(GetUserActivationStateAndModifiers());
 | 
						|
  *aModifiers = stateAndModifiers.GetModifiers();
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool WindowContext::CanShowPopup() {
 | 
						|
  uint32_t permit = GetPopupPermission();
 | 
						|
  if (permit == nsIPermissionManager::ALLOW_ACTION) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  if (permit == nsIPermissionManager::DENY_ACTION) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return !StaticPrefs::dom_disable_open_during_load();
 | 
						|
}
 | 
						|
 | 
						|
void WindowContext::TransientSetHasActivePeerConnections() {
 | 
						|
  if (!IsTop()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mFields.SetWithoutSyncing<IDX_HasActivePeerConnections>(true);
 | 
						|
}
 | 
						|
 | 
						|
WindowContext::IPCInitializer WindowContext::GetIPCInitializer() {
 | 
						|
  IPCInitializer init;
 | 
						|
  init.mInnerWindowId = mInnerWindowId;
 | 
						|
  init.mOuterWindowId = mOuterWindowId;
 | 
						|
  init.mBrowsingContextId = mBrowsingContext->Id();
 | 
						|
  init.mFields = mFields.RawValues();
 | 
						|
  return init;
 | 
						|
}
 | 
						|
 | 
						|
WindowContext::WindowContext(BrowsingContext* aBrowsingContext,
 | 
						|
                             uint64_t aInnerWindowId, uint64_t aOuterWindowId,
 | 
						|
                             FieldValues&& aInit)
 | 
						|
    : mFields(std::move(aInit)),
 | 
						|
      mInnerWindowId(aInnerWindowId),
 | 
						|
      mOuterWindowId(aOuterWindowId),
 | 
						|
      mBrowsingContext(aBrowsingContext) {
 | 
						|
  MOZ_ASSERT(mBrowsingContext);
 | 
						|
  MOZ_ASSERT(mInnerWindowId);
 | 
						|
  MOZ_ASSERT(mOuterWindowId);
 | 
						|
  RecomputeCanExecuteScripts(/* aApplyChanges */ false);
 | 
						|
}
 | 
						|
 | 
						|
WindowContext::~WindowContext() {
 | 
						|
  if (gWindowContexts) {
 | 
						|
    gWindowContexts->Remove(InnerWindowId());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
JSObject* WindowContext::WrapObject(JSContext* cx,
 | 
						|
                                    JS::Handle<JSObject*> aGivenProto) {
 | 
						|
  return WindowContext_Binding::Wrap(cx, this, aGivenProto);
 | 
						|
}
 | 
						|
 | 
						|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowContext)
 | 
						|
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
 | 
						|
  NS_INTERFACE_MAP_ENTRY(nsISupports)
 | 
						|
NS_INTERFACE_MAP_END
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTING_ADDREF(WindowContext)
 | 
						|
NS_IMPL_CYCLE_COLLECTING_RELEASE(WindowContext)
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WindowContext)
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WindowContext)
 | 
						|
  if (gWindowContexts) {
 | 
						|
    gWindowContexts->Remove(tmp->InnerWindowId());
 | 
						|
  }
 | 
						|
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNonSyntheticChildren)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 | 
						|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WindowContext)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildren)
 | 
						|
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNonSyntheticChildren)
 | 
						|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 | 
						|
 | 
						|
}  // namespace dom
 | 
						|
 | 
						|
namespace ipc {
 | 
						|
 | 
						|
void IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Write(
 | 
						|
    IPC::MessageWriter* aWriter, IProtocol* aActor,
 | 
						|
    const dom::MaybeDiscarded<dom::WindowContext>& aParam) {
 | 
						|
  uint64_t id = aParam.ContextId();
 | 
						|
  WriteIPDLParam(aWriter, aActor, id);
 | 
						|
}
 | 
						|
 | 
						|
bool IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Read(
 | 
						|
    IPC::MessageReader* aReader, IProtocol* aActor,
 | 
						|
    dom::MaybeDiscarded<dom::WindowContext>* aResult) {
 | 
						|
  uint64_t id = 0;
 | 
						|
  if (!ReadIPDLParam(aReader, aActor, &id)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (id == 0) {
 | 
						|
    *aResult = nullptr;
 | 
						|
  } else if (RefPtr<dom::WindowContext> wc = dom::WindowContext::GetById(id)) {
 | 
						|
    *aResult = std::move(wc);
 | 
						|
  } else {
 | 
						|
    aResult->SetDiscarded(id);
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void IPDLParamTraits<dom::WindowContext::IPCInitializer>::Write(
 | 
						|
    IPC::MessageWriter* aWriter, IProtocol* aActor,
 | 
						|
    const dom::WindowContext::IPCInitializer& aInit) {
 | 
						|
  // Write actor ID parameters.
 | 
						|
  WriteIPDLParam(aWriter, aActor, aInit.mInnerWindowId);
 | 
						|
  WriteIPDLParam(aWriter, aActor, aInit.mOuterWindowId);
 | 
						|
  WriteIPDLParam(aWriter, aActor, aInit.mBrowsingContextId);
 | 
						|
  WriteIPDLParam(aWriter, aActor, aInit.mFields);
 | 
						|
}
 | 
						|
 | 
						|
bool IPDLParamTraits<dom::WindowContext::IPCInitializer>::Read(
 | 
						|
    IPC::MessageReader* aReader, IProtocol* aActor,
 | 
						|
    dom::WindowContext::IPCInitializer* aInit) {
 | 
						|
  // Read actor ID parameters.
 | 
						|
  return ReadIPDLParam(aReader, aActor, &aInit->mInnerWindowId) &&
 | 
						|
         ReadIPDLParam(aReader, aActor, &aInit->mOuterWindowId) &&
 | 
						|
         ReadIPDLParam(aReader, aActor, &aInit->mBrowsingContextId) &&
 | 
						|
         ReadIPDLParam(aReader, aActor, &aInit->mFields);
 | 
						|
}
 | 
						|
 | 
						|
template struct IPDLParamTraits<dom::WindowContext::BaseTransaction>;
 | 
						|
 | 
						|
}  // namespace ipc
 | 
						|
}  // namespace mozilla
 |