Session store debugging draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Mon, 25 Apr 2016 19:44:15 -0500
changeset 375854 e83de1952158493db7e7bd7fd6e3704c0e81edd4
parent 375853 6ed1b85f50d482b443fffe0b3a2ac2ca608e8722
child 375855 580e16cf701869f16e6ab5b0f735ace37160fdcc
push id20402
push userbmo:jryans@gmail.com
push dateMon, 06 Jun 2016 20:31:20 +0000
milestone49.0a1
Session store debugging MozReview-Commit-ID: 2K7CbItPJE7
browser/components/sessionstore/SessionHistory.jsm
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/content/content-sessionStore.js
--- a/browser/components/sessionstore/SessionHistory.jsm
+++ b/browser/components/sessionstore/SessionHistory.jsm
@@ -95,16 +95,19 @@ var SessionHistoryInternal = {
       // record it. For about:blank we explicitly want an empty array without
       // an 'index' property to denote that there are no history entries.
       if (uri != "about:blank" || (body && body.hasChildNodes())) {
         data.entries.push({ url: uri });
         data.index = 1;
       }
     }
 
+    dump(`SH COLLECT:\n`);
+    dump(`${JSON.stringify(data, null, 2)}\n`);
+
     return data;
   },
 
   /**
    * Get an object that is a serialized representation of a History entry.
    *
    * @param shEntry
    *        nsISHEntry instance
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -674,16 +674,19 @@ var SessionStoreInternal = {
    * and thus enables communication with OOP tabs.
    */
   receiveMessage(aMessage) {
     // If we got here, that means we're dealing with a frame message
     // manager message, so the target will be a <xul:browser>.
     var browser = aMessage.target;
     let win = browser.ownerDocument.defaultView;
     let tab = win ? win.gBrowser.getTabForBrowser(browser) : null;
+    let key = browser.permanentKey ? browser.permanentKey.id : "<unk>";
+    dump(`SessionStore got message for browser ${key}: ` +
+         `${JSON.stringify(aMessage.data, null, 2)}\n`);
 
     // Ensure we receive only specific messages from <xul:browser>s that
     // have no tab or window assigned, e.g. the ones that preload
     // about:newtab pages, or windows that have closed.
     if (!tab && !NOTAB_MESSAGES.has(aMessage.name)) {
       throw new Error(`received unexpected message '${aMessage.name}' ` +
                       `from a browser that has no tab or window`);
     }
@@ -691,31 +694,37 @@ var SessionStoreInternal = {
     let data = aMessage.data || {};
     let hasEpoch = data.hasOwnProperty("epoch");
 
     // Most messages sent by frame scripts require to pass an epoch.
     if (!hasEpoch && !NOEPOCH_MESSAGES.has(aMessage.name)) {
       throw new Error(`received message '${aMessage.name}' without an epoch`);
     }
 
+    if (hasEpoch) {
+      dump(`Epoch expected: ${this.getCurrentEpoch(browser)}, sent: ${data.epoch}\n`)
+    }
+
     // Ignore messages from previous epochs.
     if (hasEpoch && !this.isCurrentEpoch(browser, data.epoch)) {
+      dump("Message ignored, invalid epoch\n");
       return;
     }
 
     switch (aMessage.name) {
       case "SessionStore:update":
         // |browser.frameLoader| might be empty if the browser was already
         // destroyed and its tab removed. In that case we still have the last
         // frameLoader we know about to compare.
         let frameLoader = browser.frameLoader ||
                           this._lastKnownFrameLoader.get(browser.permanentKey);
 
         // If the message isn't targeting the latest frameLoader discard it.
         if (frameLoader != aMessage.targetFrameLoader) {
+          dump("Message ignored, incorrect frameLoader\n");
           return;
         }
 
         if (aMessage.data.isFinal) {
           // If this the final message we need to resolve all pending flush
           // requests for the given browser as they might have been sent too
           // late and will never respond. If they have been sent shortly after
           // switching a browser's remoteness there isn't too much data to skip.
@@ -731,16 +740,17 @@ var SessionStoreInternal = {
         // and not yet been revived.
         if (this._crashedBrowsers.has(browser.permanentKey)) {
           return;
         }
 
         // Record telemetry measurements done in the child and update the tab's
         // cached state. Mark the window as dirty and trigger a delayed write.
         this.recordTelemetry(aMessage.data.telemetry);
+        dump(`Record data in TabState from browser ${key}\n`);
         TabState.update(browser, aMessage.data);
         this.saveStateDelayed(win);
 
         // 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.
         if (this._closedTabs.has(browser.permanentKey)) {
           let {closedTabs, tabData} = this._closedTabs.get(browser.permanentKey);
@@ -920,16 +930,17 @@ var SessionStoreInternal = {
       case "oop-browser-crashed":
         this.onBrowserCrashed(win, target);
         break;
       case "XULFrameLoaderCreated":
         if (target.namespaceURI == NS_XUL &&
             target.localName == "browser" &&
             target.frameLoader &&
             target.permanentKey) {
+          dump(`XULFrameLoaderCreated for key ${target.permanentKey.id}\n`)
           this._lastKnownFrameLoader.set(target.permanentKey, target.frameLoader);
           this.resetEpoch(target);
         }
         break;
       default:
         throw new Error(`unhandled event ${aEvent.type}?`);
     }
     this._clearRestoringWindows();
@@ -4158,16 +4169,17 @@ var SessionStoreInternal = {
 
   /**
    * Each fresh tab starts out with epoch=0. This function can be used to
    * start a next epoch by incrementing the current value. It will enables us
    * to ignore stale messages sent from previous epochs. The function returns
    * the new epoch ID for the given |browser|.
    */
   startNextEpoch(browser) {
+    dump(`startNextEpoch for ${browser.permanentKey.id}\n`)
     let next = this.getCurrentEpoch(browser) + 1;
     this._browserEpochs.set(browser.permanentKey, next);
     return next;
   },
 
   /**
    * Returns the current epoch for the given <browser>. If we haven't assigned
    * a new epoch this will default to zero for new tabs.
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -815,16 +815,17 @@ var MessageQueue = {
     }
 
     this._data.clear();
 
     durationMs = Date.now() - durationMs;
     telemetry.FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_LONGEST_OP_MS = durationMs;
 
     try {
+      dump(`Sending with epoch ${gCurrentEpoch}\n`)
       // Send all data to the parent process.
       sendAsyncMessage("SessionStore:update", {
         data, telemetry, flushID,
         isFinal: options.isFinal || false,
         epoch: gCurrentEpoch
       });
     } catch (ex if ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
       let telemetry = {