Commit c75e1105 authored by Kashav Madan's avatar Kashav Madan
Browse files

Bug 1703692 - Store the latest embedder's permanent key on CanonicalBrowsingContext, r=nika,mccr8

And include it in Session Store flushes to avoid dropping updates in case the
browser is unavailable.

Differential Revision: https://phabricator.services.mozilla.com/D118385
parent fc8fcbdd
Loading
Loading
Loading
Loading
+36 −9
Original line number Diff line number Diff line
@@ -408,10 +408,16 @@ var SessionStore = {
    return SessionStoreInternal.reviveAllCrashedTabs();
  },

  updateSessionStoreFromTablistener(aBrowser, aBrowsingContext, aData) {
  updateSessionStoreFromTablistener(
    aBrowser,
    aBrowsingContext,
    aPermanentKey,
    aData
  ) {
    return SessionStoreInternal.updateSessionStoreFromTablistener(
      aBrowser,
      aBrowsingContext,
      aPermanentKey,
      aData
    );
  },
@@ -1202,13 +1208,34 @@ var SessionStoreInternal = {
    Services.obs.notifyObservers(browser, NOTIFY_BROWSER_SHUTDOWN_FLUSH);
  },

  updateSessionStoreFromTablistener(aBrowser, aBrowsingContext, aData) {
    if (aBrowser.permanentKey == undefined) {
  updateSessionStoreFromTablistener(
    aBrowser,
    aBrowsingContext,
    aPermanentKey,
    aData
  ) {
    let browser = aBrowser;

    if (!browser || browser.permanentKey === undefined) {
      if (!aPermanentKey) {
        return;
      }

      // A little weird, but this lets us use |aPermanentKey| as an argument
      // to functions that take a browser element, since most only need the
      // permanent key.
      //
      // This should only be around as long as we're still depending on
      // permanent key in Session Store, see bug 1716788.
      browser = {
        permanentKey: aPermanentKey,
        ownerGlobal:
          aBrowsingContext.currentWindowGlobal?.browsingContext?.window,
      };
    }

    // Ignore sessionStore update from previous epochs
    if (!this.isCurrentEpoch(aBrowser, aData.epoch)) {
    if (!this.isCurrentEpoch(browser, aData.epoch)) {
      return;
    }

@@ -1222,10 +1249,10 @@ var SessionStoreInternal = {
      aBrowsingContext.sessionHistory
    ) {
      let listener =
        this._browserSHistoryListener.get(aBrowser.permanentKey) ??
        this.addSHistoryListener(aBrowser, aBrowsingContext);
        this._browserSHistoryListener.get(browser.permanentKey) ??
        this.addSHistoryListener(browser, aBrowsingContext);

      let historychange = listener.collect(aBrowser, aBrowsingContext, {
      let historychange = listener.collect(browser, aBrowsingContext, {
        collectFull: !!aData.sHistoryNeeded,
        writeToCache: false,
      });
@@ -1235,7 +1262,7 @@ var SessionStoreInternal = {
      }
    }

    this.onTabStateUpdate(aBrowser, aData);
    this.onTabStateUpdate(browser, aData);
  },

  /**
+4 −0
Original line number Diff line number Diff line
@@ -693,6 +693,10 @@ void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
    MOZ_ALWAYS_SUCCEEDS(txn.Commit(this));
  }

  if (XRE_IsParentProcess() && IsTopContent()) {
    Canonical()->MaybeSetPermanentKey(aEmbedder);
  }

  mEmbedderElement = aEmbedder;

  if (mEmbedderElement) {
+50 −18
Original line number Diff line number Diff line
@@ -78,7 +78,8 @@ CanonicalBrowsingContext::CanonicalBrowsingContext(WindowContext* aParentWindow,
    : BrowsingContext(aParentWindow, aGroup, aBrowsingContextId, aType,
                      std::move(aInit)),
      mProcessId(aOwnerProcessId),
      mEmbedderProcessId(aEmbedderProcessId) {
      mEmbedderProcessId(aEmbedderProcessId),
      mPermanentKey(JS::NullValue()) {
  // You are only ever allowed to create CanonicalBrowsingContexts in the
  // parent process.
  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
@@ -86,6 +87,12 @@ CanonicalBrowsingContext::CanonicalBrowsingContext(WindowContext* aParentWindow,
  // The initial URI in a BrowsingContext is always "about:blank".
  MOZ_ALWAYS_SUCCEEDS(
      NS_NewURI(getter_AddRefs(mCurrentRemoteURI), "about:blank"));

  mozilla::HoldJSObjects(this);
}

CanonicalBrowsingContext::~CanonicalBrowsingContext() {
  mozilla::DropJSObjects(this);
}

/* static */
@@ -288,6 +295,9 @@ void CanonicalBrowsingContext::ReplacedBy(
  mLoadingEntries.SwapElements(aNewContext->mLoadingEntries);
  MOZ_ASSERT(!aNewContext->mActiveEntry);
  mActiveEntry.swap(aNewContext->mActiveEntry);

  aNewContext->mPermanentKey = mPermanentKey;
  mPermanentKey = JS::NullValue();
}

void CanonicalBrowsingContext::UpdateSecurityState() {
@@ -1765,6 +1775,19 @@ CanonicalBrowsingContext::ChangeRemoteness(
  return promise.forget();
}

void CanonicalBrowsingContext::MaybeSetPermanentKey(Element* aEmbedder) {
  MOZ_DIAGNOSTIC_ASSERT(IsTop());

  if (aEmbedder) {
    if (nsCOMPtr<nsIBrowser> browser = aEmbedder->AsBrowser()) {
      JS::RootedValue key(RootingCx());
      if (NS_SUCCEEDED(browser->GetPermanentKey(&key)) && key.isObject()) {
        mPermanentKey = key;
      }
    }
  }
}

MediaController* CanonicalBrowsingContext::GetMediaController() {
  // We would only create one media controller per tab, so accessing the
  // controller via the top-level browsing context.
@@ -2083,17 +2106,6 @@ void CanonicalBrowsingContext::RestoreState::Resolve() {

nsresult CanonicalBrowsingContext::WriteSessionStorageToSessionStore(
    const nsTArray<SSCacheCopy>& aSesssionStorage, uint32_t aEpoch) {
  RefPtr<WindowGlobalParent> windowParent = GetCurrentWindowGlobal();

  if (!windowParent) {
    return NS_OK;
  }

  Element* frameElement = windowParent->GetRootOwnerElement();
  if (!frameElement) {
    return NS_OK;
  }

  nsCOMPtr<nsISessionStoreFunctions> funcs =
      do_ImportModule("resource://gre/modules/SessionStoreFunctions.jsm");
  if (!funcs) {
@@ -2119,8 +2131,10 @@ nsresult CanonicalBrowsingContext::WriteSessionStorageToSessionStore(
    update.setNull();
  }

  return funcs->UpdateSessionStoreForStorage(frameElement, this, aEpoch,
                                             update);
  JS::RootedValue key(jsapi.cx(), Top()->PermanentKey());

  return funcs->UpdateSessionStoreForStorage(Top()->GetEmbedderElement(), this,
                                             key, aEpoch, update);
}

void CanonicalBrowsingContext::UpdateSessionStoreSessionStorage(
@@ -2407,10 +2421,28 @@ void CanonicalBrowsingContext::SetTouchEventsOverride(
  SetTouchEventsOverrideInternal(aOverride, aRv);
}

NS_IMPL_CYCLE_COLLECTION_INHERITED(CanonicalBrowsingContext, BrowsingContext,
                                   mSessionHistory, mContainerFeaturePolicy,
NS_IMPL_CYCLE_COLLECTION_CLASS(CanonicalBrowsingContext)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CanonicalBrowsingContext,
                                                BrowsingContext)
  tmp->mPermanentKey.setNull();

  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionHistory, mContainerFeaturePolicy,
                                  mCurrentBrowserParent, mWebProgress,
                                  mSessionStoreSessionStorageUpdateTimer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CanonicalBrowsingContext,
                                                  BrowsingContext)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionHistory, mContainerFeaturePolicy,
                                    mCurrentBrowserParent, mWebProgress,
                                    mSessionStoreSessionStorageUpdateTimer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(CanonicalBrowsingContext,
                                               BrowsingContext)
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPermanentKey)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_IMPL_ADDREF_INHERITED(CanonicalBrowsingContext, BrowsingContext)
NS_IMPL_RELEASE_INHERITED(CanonicalBrowsingContext, BrowsingContext)
+8 −3
Original line number Diff line number Diff line
@@ -67,8 +67,8 @@ struct RemotenessChangeOptions {
class CanonicalBrowsingContext final : public BrowsingContext {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CanonicalBrowsingContext,
                                           BrowsingContext)
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
      CanonicalBrowsingContext, BrowsingContext)

  static already_AddRefed<CanonicalBrowsingContext> Get(uint64_t aId);
  static CanonicalBrowsingContext* Cast(BrowsingContext* aContext);
@@ -327,6 +327,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {

  bool IsReplaced() const { return mIsReplaced; }

  const JS::Heap<JS::Value>& PermanentKey() { return mPermanentKey; }
  void MaybeSetPermanentKey(Element* aEmbedder);

 protected:
  // Called when the browsing context is being discarded.
  void CanonicalDiscard();
@@ -342,7 +345,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
 private:
  friend class BrowsingContext;

  ~CanonicalBrowsingContext() = default;
  virtual ~CanonicalBrowsingContext();

  class PendingRemotenessChange {
   public:
@@ -482,6 +485,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
  nsCOMPtr<nsITimer> mSessionStoreSessionStorageUpdateTimer;

  bool mIsReplaced = false;

  JS::Heap<JS::Value> mPermanentKey;
};

}  // namespace dom
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@ interface nsIBrowser : nsISupports
   */
  readonly attribute boolean isRemoteBrowser;

  /**
   * The browser's permanent key. This was added temporarily for Session Store,
   * and will be removed in bug 1716788.
   */
  readonly attribute jsval permanentKey;

  readonly attribute nsIPrincipal contentPrincipal;
  readonly attribute nsIPrincipal contentPartitionedPrincipal;
  readonly attribute nsIContentSecurityPolicy csp;
Loading