B2G/gecko/browser/components/sessionstore/src/SessionStore.jsm
/**
   * Collect data related to a single tab
   * @param aTab
   *        tabbrowser tab
   * @param aFullData
   *        always return privacy sensitive data (use with care)
   * @returns object
   */
Collect data related to a single tab
@param aTab
tabbrowser tab
@param aFullData
always return privacy sensitive data (use with care)
@returns object
Collect data related to a single tab @param aTab tabbrowser tab @param aFullData always return privacy sensitive data ( use with care ) @returns object
function ssi_collectTabData(aTab, aFullData) {
    var tabData = { entries: [] };
    var browser = aTab.linkedBrowser;
    if (!browser || !browser.currentURI)
      return tabData;
    else if (browser.__SS_data && browser.__SS_tabStillLoading) {
      tabData = browser.__SS_data;
      if (aTab.pinned)
        tabData.pinned = true;
      else
        delete tabData.pinned;
      tabData.hidden = aTab.hidden;
      if (aTab.__SS_extdata)
        tabData.extData = aTab.__SS_extdata;
      if (tabData.extData && !Object.keys(tabData.extData).length)
        delete tabData.extData;
      return tabData;
    }
    var history = null;
    try {
      history = browser.sessionHistory;
    }
    catch (ex) { } 
    if (history && browser.__SS_data &&
        browser.__SS_data.entries[history.index] &&
        browser.__SS_data.entries[history.index].url == browser.currentURI.spec &&
        history.index < this._sessionhistory_max_entries - 1 && !aFullData) {
      tabData = browser.__SS_data;
      tabData.index = history.index + 1;
    }
    else if (history && history.count > 0) {
      browser.__SS_hostSchemeData = [];
      try {
        for (var j = 0; j < history.count; j++) {
          let entry = this._serializeHistoryEntry(history.getEntryAtIndex(j, false),
                                                  aFullData, aTab.pinned, browser.__SS_hostSchemeData);
          tabData.entries.push(entry);
        }
        delete aTab.__SS_broken_history;
      }
      catch (ex) {
        if (!aTab.__SS_broken_history) {
          aTab.ownerDocument.defaultView.focus();
          aTab.ownerDocument.defaultView.gBrowser.selectedTab = aTab;
          NS_ASSERT(false, "SessionStore failed gathering complete history " +
                           "for the focused window/tab. See bug 669196.");
          aTab.__SS_broken_history = true;
        }
      }
      tabData.index = history.index + 1;
      if (!aFullData)
        browser.__SS_data = tabData;
    }
    else if (browser.currentURI.spec != "about:blank" ||
             browser.contentDocument.body.hasChildNodes()) {
      tabData.entries[0] = { url: browser.currentURI.spec };
      tabData.index = 1;
    }
    if (browser.userTypedValue) {
      tabData.userTypedValue = browser.userTypedValue;
      tabData.userTypedClear = browser.userTypedClear;
    } else {
      delete tabData.userTypedValue;
      delete tabData.userTypedClear;
    }
    if (aTab.pinned)
      tabData.pinned = true;
    else
      delete tabData.pinned;
    tabData.hidden = aTab.hidden;
    var disallow = [];
    for (var i = 0; i < CAPABILITIES.length; i++)
      if (!browser.docShell["allow" + CAPABILITIES[i]])
        disallow.push(CAPABILITIES[i]);
    if (disallow.length > 0)
      tabData.disallow = disallow.join(",");
    else if (tabData.disallow)
      delete tabData.disallow;
    tabData.attributes = {};
    for (let name in this.xulAttributes) {
      if (aTab.hasAttribute(name))
        tabData.attributes[name] = aTab.getAttribute(name);
    }
    if (aTab.__SS_extdata)
      tabData.extData = aTab.__SS_extdata;
    else if (tabData.extData)
      delete tabData.extData;
    if (history && browser.docShell instanceof Ci.nsIDocShell) {
      let storageData = SessionStorage.serialize(browser.docShell, aFullData)
      if (Object.keys(storageData).length)
        tabData.storage = storageData;
    }
    return tabData;
  }
function ssi_collectTabData ( aTab , aFullData ) { var tabData = { entries : [ ] } ; var browser = aTab . linkedBrowser ; if ( ! browser || ! browser . currentURI ) return tabData ; else if ( browser . __SS_data && browser . __SS_tabStillLoading ) { tabData = browser . __SS_data ; if ( aTab . pinned ) tabData . pinned = true ; else delete tabData . pinned ; tabData . hidden = aTab . hidden ; if ( aTab . __SS_extdata ) tabData . extData = aTab . __SS_extdata ; if ( tabData . extData && ! Object . keys ( tabData . extData ) . length ) delete tabData . extData ; return tabData ; } var history = null ; try { history = browser . sessionHistory ; } catch ( ex ) { } if ( history && browser . __SS_data && browser . __SS_data . entries [ history . index ] && browser . __SS_data . entries [ history . index ] . url == browser . currentURI . spec && history . index < this . _sessionhistory_max_entries - 1 && ! aFullData ) { tabData = browser . __SS_data ; tabData . index = history . index + 1 ; } else if ( history && history . count > 0 ) { browser . __SS_hostSchemeData = [ ] ; try { for ( var j = 0 ; j < history . count ; j ++ ) { let entry = this . _serializeHistoryEntry ( history . getEntryAtIndex ( j , false ) , aFullData , aTab . pinned , browser . __SS_hostSchemeData ) ; tabData . entries . push ( entry ) ; } delete aTab . __SS_broken_history ; } catch ( ex ) { if ( ! aTab . __SS_broken_history ) { aTab . ownerDocument . defaultView . focus ( ) ; aTab . ownerDocument . defaultView . gBrowser . selectedTab = aTab ; NS_ASSERT ( false , "SessionStore failed gathering complete history " + "for the focused window/tab. See bug 669196." ) ; aTab . __SS_broken_history = true ; } } tabData . index = history . index + 1 ; if ( ! aFullData ) browser . __SS_data = tabData ; } else if ( browser . currentURI . spec != "about:blank" || browser . contentDocument . body . hasChildNodes ( ) ) { tabData . entries [ 0 ] = { url : browser . currentURI . spec } ; tabData . index = 1 ; } if ( browser . userTypedValue ) { tabData . userTypedValue = browser . userTypedValue ; tabData . userTypedClear = browser . userTypedClear ; } else { delete tabData . userTypedValue ; delete tabData . userTypedClear ; } if ( aTab . pinned ) tabData . pinned = true ; else delete tabData . pinned ; tabData . hidden = aTab . hidden ; var disallow = [ ] ; for ( var i = 0 ; i < CAPABILITIES . length ; i ++ ) if ( ! browser . docShell [ "allow" + CAPABILITIES [ i ] ] ) disallow . push ( CAPABILITIES [ i ] ) ; if ( disallow . length > 0 ) tabData . disallow = disallow . join ( "," ) ; else if ( tabData . disallow ) delete tabData . disallow ; tabData . attributes = { } ; for ( let name in this . xulAttributes ) { if ( aTab . hasAttribute ( name ) ) tabData . attributes [ name ] = aTab . getAttribute ( name ) ; } if ( aTab . __SS_extdata ) tabData . extData = aTab . __SS_extdata ; else if ( tabData . extData ) delete tabData . extData ; if ( history && browser . docShell instanceof Ci . nsIDocShell ) { let storageData = SessionStorage . serialize ( browser . docShell , aFullData ) if ( Object . keys ( storageData ) . length ) tabData . storage = storageData ; } return tabData ; }
Collect data related to a single tab
 @param aTab
        tabbrowser tab
 @param aFullData
        always return privacy sensitive data (use with care)
 @returns object
Collect data related to a single tab @param aTab tabbrowser tab @param aFullData always return privacy sensitive data ( use with care ) @returns object
// can happen when calling this function right after .addTab() // use the data to be restored when the tab hasn't been completely loaded // If __SS_extdata is set then we'll use that since it might be newer. // If it exists but is empty then a key was likely deleted. In that case just // delete extData. // this could happen if we catch a tab during (de)initialization // XXXzeniko anchor navigation doesn't reset __SS_data, so we could reuse //           data even when we shouldn't (e.g. Back, different anchor) // If we make it through the for loop, then we're ok and we should clear // any indicator of brokenness. // In some cases, getEntryAtIndex will throw. This seems to be due to // history.count being higher than it should be. By doing this in a // try-catch, we'll update history to where it breaks, assert for // non-release builds, and still save sessionstore.js. We'll track if // we've shown the assert for this tab so we only show it once. // cf. bug 669196. // First Focus the window & tab we're having trouble with. // make sure not to cache privacy sensitive data which shouldn't get out // If there is a userTypedValue set, then either the user has typed something // in the URL bar, or a new tab was opened with a URI to load. userTypedClear // is used to indicate whether the tab was in some sort of loading state with // userTypedValue.