Commit 40fe0b40 authored by Dorel Luca's avatar Dorel Luca
Browse files

Backed out 3 changesets (bug 1703692) for Browser-chrome failures in...

Backed out 3 changesets (bug 1703692) for Browser-chrome failures in browser/components/sessionstore/test/browser_broadcast.js. CLOSED TREE

Backed out changeset fe5703d7b580 (bug 1703692)
Backed out changeset eec4a4138ca7 (bug 1703692)
Backed out changeset 6745b363a745 (bug 1703692)
parent bc6f2486
Loading
Loading
Loading
Loading
+115 −132
Original line number Diff line number Diff line
@@ -408,16 +408,10 @@ var SessionStore = {
    return SessionStoreInternal.reviveAllCrashedTabs();
  },

  updateSessionStoreFromTablistener(
    aBrowser,
    aBrowsingContext,
    aPermanentKey,
    aData
  ) {
  updateSessionStoreFromTablistener(aBrowser, aBrowsingContext, aData) {
    return SessionStoreInternal.updateSessionStoreFromTablistener(
      aBrowser,
      aBrowsingContext,
      aPermanentKey,
      aData
    );
  },
@@ -459,7 +453,7 @@ var SessionStore = {
  },

  getCurrentEpoch(browser) {
    return SessionStoreInternal.getCurrentEpoch(browser.permanentKey);
    return SessionStoreInternal.getCurrentEpoch(browser);
  },

  /**
@@ -996,12 +990,9 @@ var SessionStoreInternal = {
            aSubject &&
            aSubject === aSubject.top &&
            aSubject.isContent &&
            aSubject.embedderElement &&
            aSubject.embedderElement.permanentKey
            aSubject.embedderElement
          ) {
            let permanentKey = aSubject.embedderElement.permanentKey;
            this._browserSHistoryListener.get(permanentKey)?.unregister();
            this.getOrCreateSHistoryListener(permanentKey, aSubject, true);
            this.addSHistoryListener(aSubject.embedderElement, aSubject, true);
          }
        }
        break;
@@ -1009,7 +1000,7 @@ var SessionStoreInternal = {
        if (Services.appinfo.sessionHistoryInParent) {
          let permanentKey = aSubject?.embedderElement?.permanentKey;
          if (permanentKey) {
            this._browserSHistoryListener.get(permanentKey)?.unregister();
            this._browserSHistoryListener.get(permanentKey)?.uninstall();
          }
        }
        break;
@@ -1022,34 +1013,36 @@ var SessionStoreInternal = {
    }
  },

  getOrCreateSHistoryListener(
    permanentKey,
    browsingContext,
    collectImmediately = false
  ) {
  // Add a new SessionHistory listener to the provided browsing context and save
  // a reference to that listener in the _browserSHistoryListener map.
  addSHistoryListener(aBrowser, aBrowsingContext, aCollectImmediately = false) {
    class SHistoryListener {
      constructor() {
        this.QueryInterface = ChromeUtils.generateQI([
          "nsISHistoryListener",
          "nsISupportsWeakReference",
        ]);

        this._browserId = browsingContext.browserId;
        this._browserId = aBrowsingContext.browserId;
        this._permanentKey = aBrowser.permanentKey;
        this._fromIndex = kNoIndex;
      }

      unregister() {
      uninstall() {
        let bc = BrowsingContext.getCurrentTopByBrowserId(this._browserId);
        bc?.sessionHistory?.removeSHistoryListener(this);
        SessionStoreInternal._browserSHistoryListener.delete(permanentKey);
        SessionStoreInternal._browserSHistoryListener.delete(
          this._permanentKey
        );
      }

      collect(
        permanentKey, // eslint-disable-line no-shadow
        browsingContext, // eslint-disable-line no-shadow
        { collectFull = true, writeToCache = false }
        browser,
        browsingContext,
        { immediate = true, collectFull = true, writeToCache = false }
      ) {
        // Don't bother doing anything if we haven't seen any navigations.
        if (!immediate) {
          // Queue a tab state update on the |browser.sessionstore.interval|
          // timer. We'll eventually call this again with |immediate=true|.
          browser.frameLoader?.requestSHistoryUpdate();
          return null;
        }

        // Don't bother doing anything if we haven't actually seen any history
        // changes.
        if (!collectFull && this._fromIndex === kNoIndex) {
          return null;
        }
@@ -1065,18 +1058,13 @@ var SessionStoreInternal = {
        );

        if (writeToCache) {
          let win =
            browsingContext.embedderElement?.ownerGlobal ||
            browsingContext.currentWindowGlobal?.browsingContext?.window;

          SessionStoreInternal.onTabStateUpdate(permanentKey, win, {
          SessionStoreInternal.onTabStateUpdate(browser, {
            data: { historychange },
          });
        }

        return historychange;
      }

      collectFrom(index) {
        if (this._fromIndex <= index) {
          // If we already know that we need to update history from index N we
@@ -1091,15 +1079,11 @@ var SessionStoreInternal = {
        }

        let bc = BrowsingContext.getCurrentTopByBrowserId(this._browserId);
        if (bc?.embedderElement?.frameLoader) {
        if (bc?.embedderElement) {
          this._fromIndex = index;

          // Queue a tab state update on the |browser.sessionstore.interval|
          // timer. We'll call this.collect() when we receive the update.
          bc.embedderElement.frameLoader.requestSHistoryUpdate();
          this.collect(bc.embedderElement, bc, { immediate: false });
        }
      }

      OnHistoryNewEntry(newURI, oldIndex) {
        // We use oldIndex - 1 to collect the current entry as well. This makes
        // sure to collect any changes that were made to the entry while the
@@ -1120,56 +1104,56 @@ var SessionStoreInternal = {
        this.collectFrom(-1);
      }
    }
    SHistoryListener.prototype.QueryInterface = ChromeUtils.generateQI([
      "nsISHistoryListener",
      "nsISupportsWeakReference",
    ]);

    if (!Services.appinfo.sessionHistoryInParent) {
      throw new Error("This function should only be used with SHIP");
    }

    if (!permanentKey || browsingContext !== browsingContext.top) {
      return null;
    }
    let sessionHistory = aBrowsingContext.sessionHistory;

    let sessionHistory = browsingContext.sessionHistory;
    if (!sessionHistory) {
    if (!aBrowser || !aBrowser.permanentKey || !sessionHistory) {
      return null;
    }

    let listener = this._browserSHistoryListener.get(permanentKey);
    if (listener) {
      return listener;
    // XXX: Maybe investigate unregistering the previous listener?
    if (this._browserSHistoryListener.has(aBrowser.permanentKey)) {
      return null;
    }

    listener = new SHistoryListener();
    let listener = new SHistoryListener();
    sessionHistory.addSHistoryListener(listener);
    this._browserSHistoryListener.set(permanentKey, listener);
    this._browserSHistoryListener.set(aBrowser.permanentKey, listener);

    let isAboutBlank = browsingContext.currentURI?.spec === "about:blank";

    if (collectImmediately && (!isAboutBlank || sessionHistory.count !== 0)) {
      listener.collect(permanentKey, browsingContext, { writeToCache: true });
    if (aCollectImmediately) {
      let uri = aBrowsingContext.currentURI?.spec;
      if (uri !== "about:blank" || sessionHistory.count !== 0) {
        listener.collect(aBrowser, aBrowsingContext, { writeToCache: true });
      }
    }

    return listener;
  },

  onTabStateUpdate(permanentKey, win, update) {
  onTabStateUpdate(browser, data) {
    // Ignore messages from <browser> elements that have crashed
    // and not yet been revived.
    if (this._crashedBrowsers.has(permanentKey)) {
      return;
    }

    TabState.update(permanentKey, update);
    this.saveStateDelayed(win);
    if (!this._crashedBrowsers.has(browser.permanentKey)) {
      TabState.update(browser, data);
      this.saveStateDelayed(browser.ownerGlobal);

      // Handle any updates sent by the child after the tab was closed. This
      // might be the final update as sent by the "unload" handler but also
      // any async update message that was sent before the child unloaded.
    let closedTab = this._closedTabs.get(permanentKey);
      let closedTab = this._closedTabs.get(browser.permanentKey);
      if (closedTab) {
        // Update the closed tab's state. This will be reflected in its
        // window's list of closed tabs as that refers to the same object.
      TabState.copyFromCache(permanentKey, closedTab.tabData.state);
        TabState.copyFromCache(browser, closedTab.tabData.state);
      }
    }
  },

@@ -1212,55 +1196,46 @@ var SessionStoreInternal = {
    // switching a browser's remoteness there isn't too much data to skip.
    TabStateFlusher.resolveAll(browser);

    this._browserSHistoryListener.get(permanentKey)?.unregister();
    this._browserSHistoryListener.get(permanentKey)?.uninstall();
    this._restoreListeners.get(permanentKey)?.unregister();

    Services.obs.notifyObservers(browser, NOTIFY_BROWSER_SHUTDOWN_FLUSH);
  },

  updateSessionStoreFromTablistener(
    browser,
    browsingContext,
    permanentKey,
    update
  ) {
    permanentKey = browser?.permanentKey ?? permanentKey;
    if (!permanentKey) {
  updateSessionStoreFromTablistener(aBrowser, aBrowsingContext, aData) {
    if (aBrowser.permanentKey == undefined) {
      return;
    }

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

    if (browsingContext.isReplaced) {
    if (aBrowsingContext.isReplaced) {
      return;
    }

    if (Services.appinfo.sessionHistoryInParent) {
      let listener = this.getOrCreateSHistoryListener(
        permanentKey,
        browsingContext
      );
    if (
      Services.appinfo.sessionHistoryInParent &&
      aBrowsingContext === aBrowsingContext.top &&
      aBrowsingContext.sessionHistory
    ) {
      let listener =
        this._browserSHistoryListener.get(aBrowser.permanentKey) ??
        this.addSHistoryListener(aBrowser, aBrowsingContext);

      if (listener) {
        let historychange = listener.collect(permanentKey, browsingContext, {
          collectFull: !!update.sHistoryNeeded,
      let historychange = listener.collect(aBrowser, aBrowsingContext, {
        collectFull: !!aData.sHistoryNeeded,
        writeToCache: false,
      });

      if (historychange) {
          update.data.historychange = historychange;
        }
        aData.data.historychange = historychange;
      }
    }

    let win =
      browser?.ownerGlobal ??
      browsingContext.currentWindowGlobal?.browsingContext?.window;

    this.onTabStateUpdate(permanentKey, win, update);
    this.onTabStateUpdate(aBrowser, aData);
  },

  /**
@@ -1294,7 +1269,7 @@ var SessionStoreInternal = {
    }

    // Ignore messages from previous epochs.
    if (hasEpoch && !this.isCurrentEpoch(browser.permanentKey, data.epoch)) {
    if (hasEpoch && !this.isCurrentEpoch(browser, data.epoch)) {
      return;
    }

@@ -1312,7 +1287,7 @@ var SessionStoreInternal = {
          return;
        }

        this.onTabStateUpdate(browser.permanentKey, browser.ownerGlobal, data);
        this.onTabStateUpdate(browser, data);

        if (data.isFinal) {
          this.onFinalTabStateUpdateComplete(browser);
@@ -1400,7 +1375,7 @@ var SessionStoreInternal = {
            target.permanentKey,
            target.frameLoader
          );
          this.resetEpoch(target.permanentKey, target.frameLoader);
          this.resetEpoch(target);
        }
        break;
      default:
@@ -1862,7 +1837,7 @@ var SessionStoreInternal = {
        for (let browser of browsers) {
          if (this._closedWindowTabs.has(browser.permanentKey)) {
            let tabData = this._closedWindowTabs.get(browser.permanentKey);
            TabState.copyFromCache(browser.permanentKey, tabData);
            TabState.copyFromCache(browser, tabData);
            this._closedWindowTabs.delete(browser.permanentKey);
          }
        }
@@ -2370,7 +2345,7 @@ var SessionStoreInternal = {
    if (
      TAB_LAZY_STATES.has(aTab) &&
      !TAB_STATE_FOR_BROWSER.has(browser) &&
      TabStateCache.get(browser.permanentKey)
      TabStateCache.get(browser)
    ) {
      let tabState = TabState.clone(aTab, TAB_CUSTOM_VALUES.get(aTab));
      this.restoreTab(aTab, tabState);
@@ -2481,13 +2456,13 @@ var SessionStoreInternal = {

    let { userTypedValue = "", userTypedClear = 0 } = browser;

    let cacheState = TabStateCache.get(browser.permanentKey);
    let cacheState = TabStateCache.get(browser);
    if (cacheState === undefined && userTypedValue) {
      // Discard was likely called before state can be cached.  Update
      // the persistent tab state cache with browser information so a
      // restore will be successful.  This information is necessary for
      // restoreTabContent in ContentRestore.jsm to work properly.
      TabStateCache.update(browser.permanentKey, {
      TabStateCache.update(browser, {
        userTypedValue,
        userTypedClear: 1,
      });
@@ -3008,7 +2983,7 @@ var SessionStoreInternal = {
      // the tab to duplicate may have already been closed. In that case we
      // only have access to the <xul:browser>.
      let options = { includePrivateData: true };
      TabState.copyFromCache(browser.permanentKey, tabState, options);
      TabState.copyFromCache(browser, tabState, options);

      tabState.index += aDelta;
      tabState.index = Math.max(
@@ -3408,7 +3383,7 @@ var SessionStoreInternal = {
          tabData.iconLoadingPrincipal
        );
      }
      TabStateCache.update(browser.permanentKey, {
      TabStateCache.update(browser, {
        image: null,
        iconLoadingPrincipal: null,
      });
@@ -4440,7 +4415,7 @@ var SessionStoreInternal = {
    }

    // Update the persistent tab state cache with |tabData| information.
    TabStateCache.update(browser.permanentKey, {
    TabStateCache.update(browser, {
      // NOTE: Copy the entries array shallowly, so as to not screw with the
      // original tabData's history when getting history updates.
      history: { entries: [...tabData.entries], index: tabData.index },
@@ -4469,7 +4444,7 @@ var SessionStoreInternal = {
      // Start a new epoch to discard all frame script messages relating to a
      // previous epoch. All async messages that are still on their way to chrome
      // will be ignored and don't override any tab data set when restoring.
      let epoch = this.startNextEpoch(browser.permanentKey);
      let epoch = this.startNextEpoch(browser);

      // Ensure that the tab will get properly restored in the event the tab
      // crashes while restoring.  But don't set this on lazy browsers as
@@ -4595,7 +4570,7 @@ var SessionStoreInternal = {
        // Start a new epoch to discard all frame script messages relating to a
        // previous epoch. All async messages that are still on their way to chrome
        // will be ignored and don't override any tab data set when restoring.
        let epoch = this.startNextEpoch(browser.permanentKey);
        let epoch = this.startNextEpoch(browser);

        this._sendRestoreHistory(browser, {
          tabData,
@@ -5612,18 +5587,26 @@ var SessionStoreInternal = {
   * to ignore stale messages sent from previous epochs. The function returns
   * the new epoch ID for the given |browser|.
   */
  startNextEpoch(permanentKey) {
    let next = this.getCurrentEpoch(permanentKey) + 1;
    this._browserEpochs.set(permanentKey, next);
  startNextEpoch(browser) {
    let next = this.getCurrentEpoch(browser) + 1;
    this._browserEpochs.set(browser.permanentKey, next);
    return next;
  },

  /**
   * Manually set the epoch to a given value.
   */
  setCurrentEpoch(aBrowser, aEpoch) {
    this._browserEpochs.set(aBrowser.permanentKey, aEpoch);
    return aEpoch;
  },

  /**
   * Returns the current epoch for the given <browser>. If we haven't assigned
   * a new epoch this will default to zero for new tabs.
   */
  getCurrentEpoch(permanentKey) {
    return this._browserEpochs.get(permanentKey) || 0;
  getCurrentEpoch(browser) {
    return this._browserEpochs.get(browser.permanentKey) || 0;
  },

  /**
@@ -5633,8 +5616,8 @@ var SessionStoreInternal = {
   * epoch. This function does that, and returns true if |epoch| is up-to-date
   * with respect to |browser|.
   */
  isCurrentEpoch(permanentKey, epoch) {
    return this.getCurrentEpoch(permanentKey) == epoch;
  isCurrentEpoch(browser, epoch) {
    return this.getCurrentEpoch(browser) == epoch;
  },

  /**
@@ -5642,10 +5625,10 @@ var SessionStoreInternal = {
   * receive a hint that a new docShell has been loaded into the browser as
   * the frame script starts out with epoch=0.
   */
  resetEpoch(permanentKey, frameLoader = null) {
    this._browserEpochs.delete(permanentKey);
    if (frameLoader) {
      frameLoader.requestEpochUpdate(0);
  resetEpoch(browser) {
    this._browserEpochs.delete(browser.permanentKey);
    if (browser && browser.frameLoader) {
      browser.frameLoader.requestEpochUpdate(0);
    }
  },

@@ -6069,10 +6052,10 @@ var SessionStoreInternal = {
    // all, and so we remove it from the tab state cache.  In particular, if
    // the restore is due to a remoteness change, then the user is loading a
    // new URL and the current search mode should not be carried over to it.
    let cacheState = TabStateCache.get(browser.permanentKey);
    let cacheState = TabStateCache.get(browser);
    if (cacheState.searchMode) {
      if (!initiatedBySessionStore || isNavigateAndRestore) {
        TabStateCache.update(browser.permanentKey, {
        TabStateCache.update(browser, {
          searchMode: null,
          userTypedValue: null,
        });
@@ -6106,7 +6089,7 @@ var SessionStoreInternal = {
      }

      // Remove state we don't need any longer.
      TabStateCache.update(browser.permanentKey, {
      TabStateCache.update(browser, {
        userTypedValue: null,
        userTypedClear: null,
      });
@@ -6121,14 +6104,14 @@ var SessionStoreInternal = {
    }
    // Restore search mode and its search string in userTypedValue, if
    // appropriate.
    let cacheState = TabStateCache.get(browser.permanentKey);
    let cacheState = TabStateCache.get(browser);
    if (cacheState.searchMode) {
      win.gURLBar.setSearchMode(cacheState.searchMode, browser);
      browser.userTypedValue = cacheState.userTypedValue;
      if (tab.selected) {
        win.gURLBar.setURI();
      }
      TabStateCache.update(browser.permanentKey, {
      TabStateCache.update(browser, {
        searchMode: null,
        userTypedValue: null,
      });
+10 −10
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@ ChromeUtils.defineModuleGetter(
 * Module that contains tab state collection methods.
 */
var TabState = Object.freeze({
  update(permanentKey, data) {
    TabStateInternal.update(permanentKey, data);
  update(browser, data) {
    TabStateInternal.update(browser, data);
  },

  collect(tab, extData) {
@@ -38,8 +38,8 @@ var TabState = Object.freeze({
    return TabStateInternal.clone(tab, extData);
  },

  copyFromCache(permanentKey, tabData, options) {
    TabStateInternal.copyFromCache(permanentKey, tabData, options);
  copyFromCache(browser, tabData, options) {
    TabStateInternal.copyFromCache(browser, tabData, options);
  },
});

@@ -47,8 +47,8 @@ var TabStateInternal = {
  /**
   * Processes a data update sent by the content script.
   */
  update(permanentKey, { data }) {
    TabStateCache.update(permanentKey, data);
  update(browser, { data }) {
    TabStateCache.update(browser, data);
  },

  /**
@@ -123,7 +123,7 @@ var TabStateInternal = {

    // Copy data from the tab state cache only if the tab has fully finished
    // restoring. We don't want to overwrite data contained in __SS_data.
    this.copyFromCache(browser.permanentKey, tabData, options);
    this.copyFromCache(browser, tabData, options);

    // After copyFromCache() was called we check for properties that are kept
    // in the cache only while the tab is pending or restoring. Once that
@@ -158,15 +158,15 @@ var TabStateInternal = {
  /**
   * Copy data for the given |browser| from the cache to |tabData|.
   *
   * @param permanentKey (object)
   * @param browser (xul:browser)
   *        The browser belonging to the given |tabData| object.
   * @param tabData (object)
   *        The tab data belonging to the given |tab|.
   * @param options (object)
   *        {includePrivateData: true} to always include private data
   */
  copyFromCache(permanentKey, tabData, options = {}) {
    let data = TabStateCache.get(permanentKey);
  copyFromCache(browser, tabData, options = {}) {
    let data = TabStateCache.get(browser);
    if (!data) {
      return;
    }
+13 −13
Original line number Diff line number Diff line
@@ -20,27 +20,27 @@ var TabStateCache = Object.freeze({
  /**
   * Retrieves cached data for a given |tab| or associated |browser|.
   *
   * @param permanentKey (object)
   * @param browserOrTab (xul:tab or xul:browser)
   *        The tab or browser to retrieve cached data for.
   * @return (object)
   *         The cached data stored for the given |tab|
   *         or associated |browser|.
   */
  get(permanentKey) {
    return TabStateCacheInternal.get(permanentKey);
  get(browserOrTab) {
    return TabStateCacheInternal.get(browserOrTab);
  },

  /**
   * Updates cached data for a given |tab| or associated |browser|.
   *
   * @param permanentKey (object)
   * @param browserOrTab (xul:tab or xul:browser)
   *        The tab or browser belonging to the given tab data.
   * @param newData (object)
   *        The new data to be stored for the given |tab|
   *        or associated |browser|.
   */
  update(permanentKey, newData) {
    TabStateCacheInternal.update(permanentKey, newData);
  update(browserOrTab, newData) {
    TabStateCacheInternal.update(browserOrTab, newData);
  },
});

@@ -50,14 +50,14 @@ var TabStateCacheInternal = {
  /**
   * Retrieves cached data for a given |tab| or associated |browser|.
   *
   * @param permanentKey (object)
   * @param browserOrTab (xul:tab or xul:browser)
   *        The tab or browser to retrieve cached data for.
   * @return (object)
   *         The cached data stored for the given |tab|
   *         or associated |browser|.
   */
  get(permanentKey) {
    return this._data.get(permanentKey);
  get(browserOrTab) {
    return this._data.get(browserOrTab.permanentKey);
  },

  /**
@@ -213,14 +213,14 @@ var TabStateCacheInternal = {
  /**
   * Updates cached data for a given |tab| or associated |browser|.
   *
   * @param permanentKey (object)
   * @param browserOrTab (xul:tab or xul:browser)
   *        The tab or browser belonging to the given tab data.
   * @param newData (object)
   *        The new data to be stored for the given |tab|
   *        or associated |browser|.
   */
  update(permanentKey, newData) {
    let data = this._data.get(permanentKey) || {};
  update(browserOrTab, newData) {
    let data = this._data.get(browserOrTab.permanentKey) || {};

    for (let key of Object.keys(newData)) {
      if (key == "storagechange") {
@@ -257,6 +257,6 @@ var TabStateCacheInternal = {
      }
    }

    this._data.set(permanentKey, data);
    this._data.set(browserOrTab.permanentKey, data);
  },
};
+2 −2
Original line number Diff line number Diff line
@@ -20,14 +20,14 @@ add_task(async function() {
  ) {
    let tab = gBrowser.getTabForBrowser(aBrowser);
    await TabStateFlusher.flush(aBrowser);
    let before = TabStateCache.get(aBrowser.permanentKey);
    let before = TabStateCache.get(aBrowser);

    let newTab = SessionStore.duplicateTab(window, tab);
    await Promise.all([
      BrowserTestUtils.browserLoaded(newTab.linkedBrowser),
      TestUtils.topicObserved("sessionstore-debug-tab-restored"),
    ]);
    let after = TabStateCache.get(newTab.linkedBrowser.permanentKey);
    let after = TabStateCache.get(newTab.linkedBrowser);

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

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

  mEmbedderElement = aEmbedder;

  if (mEmbedderElement) {
@@ -3266,17 +3262,6 @@ void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
      EventQueuePriority::Idle);
}

bool BrowsingContext::GetOffsetPath(nsTArray<uint32_t>& aPath) const {
  for (const BrowsingContext* current = this; current && current->GetParent();
       current = current->GetParent()) {
    if (current->CreatedDynamically()) {
      return false;
    }
    aPath.AppendElement(current->ChildOffset());
  }
  return true;
}

void BrowsingContext::GetHistoryID(JSContext* aCx,
                                   JS::MutableHandle<JS::Value> aVal,
                                   ErrorResult& aError) {
Loading