Bug 1443765: Update android formdata sessionstore test for delayed save r=snorp
authorRandell Jesup <rjesup@jesup.org>
Thu, 08 Mar 2018 17:12:57 -0500
changeset 407218 c1152eaf2036a18226b7e04f8359eff9aeb83cd8
parent 407217 f34ad0155500e32c013d15b706986bc4726fd41c
child 407219 d4b3440ba8c95ec6352814a5a710758c93366f3c
push id100610
push userrjesup@wgate.com
push dateThu, 08 Mar 2018 22:43:28 +0000
treeherdermozilla-inbound@c1152eaf2036 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1443765
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1443765: Update android formdata sessionstore test for delayed save r=snorp
mobile/android/components/SessionStore.js
mobile/android/tests/browser/chrome/test_session_form_data.html
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -48,16 +48,22 @@ const PREFS_RESTORE_FROM_CRASH = "browse
 const PREFS_MAX_CRASH_RESUMES = "browser.sessionstore.max_resumed_crashes";
 const PREFS_MAX_TABS_UNDO = "browser.sessionstore.max_tabs_undo";
 
 const MINIMUM_SAVE_DELAY = 2000;
 const SAVE_INTERVAL_PRIVATE_TABS = 500;
 
 function SessionStore() { }
 
+function sendEvent(browser, event) {
+  let evt = new Event(event, {"bubbles": true, "cancelable": false});
+  browser.dispatchEvent(evt);
+}
+
+
 SessionStore.prototype = {
   classID: Components.ID("{8c1f07d6-cba3-4226-a315-8bd43d67d032}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISessionStore,
                                          Ci.nsIDOMEventListener,
                                          Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
@@ -681,16 +687,23 @@ SessionStore.prototype = {
         ", aNoNotification = " + aNoNotification);
     if (!aNoNotification) {
       let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(aBrowser);
       this.saveStateDelayed(isPrivate);
     }
   },
 
   onTabClose: function ss_onTabClose(aWindow, aBrowser, aTabIndex) {
+    // collect any pending data before saving
+    if (this._formdataSavePending) {
+      this.onTabInput(aWindow, aBrowser);
+    }
+    if (this._scrollSavePending) {
+      this.onTabScroll(aWindow, aBrowser);
+    }
     let data = aBrowser.__SS_data;
     let tab = aWindow.BrowserApp.getTabForId(data.tabId);
 
     if (this._maxTabsUndo == 0 || this._sessionDataIsEmpty(data)) {
       this._lastClosedTabIndex = INVALID_TAB_INDEX;
       return;
     }
 
@@ -707,18 +720,17 @@ SessionStore.prototype = {
 
       this._lastClosedTabIndex = aTabIndex;
 
       if (this._notifyClosedTabs) {
         this._sendClosedTabsToJava(aWindow);
       }
 
       log("onTabClose() ran for tab " + tab.id);
-      let evt = new Event("SSTabCloseProcessed", {"bubbles": true, "cancelable": false});
-      aBrowser.dispatchEvent(evt);
+      sendEvent(aBrowser, "SSTabCloseProcessed");
     }
   },
 
   _sessionDataIsEmpty: function ss_sessionDataIsEmpty(aData) {
     if (!aData || !aData.entries || aData.entries.length == 0) {
       return true;
     }
 
@@ -787,18 +799,17 @@ SessionStore.prototype = {
       this.onTabInput(aWindow, aBrowser);
       // A similar thing applies for the scroll position, otherwise a stray
       // DOMTitleChanged event can clobber the scroll position if the user
       // doesn't scroll again afterwards.
       this.onTabScroll(aWindow, aBrowser);
     }
 
     log("onTabLoad() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id);
-    let evt = new Event("SSTabDataUpdated", {"bubbles": true, "cancelable": false});
-    aBrowser.dispatchEvent(evt);
+    sendEvent(aBrowser, "SSTabDataUpdated");
     this.saveStateDelayed();
 
     this._updateCrashReportURL(aWindow);
   },
 
   onTabSelect: function ss_onTabSelect(aWindow, aBrowser) {
     if (this._loadState != STATE_RUNNING) {
       return;
@@ -861,32 +872,35 @@ SessionStore.prototype = {
       aWindow.clearTimeout(this._formdataSavePending);
       this._formdataSavePending = null;
       log("onTabInput() clearing pending timeout");
     }
 
     // If this browser belongs to a zombie tab or the initial restore hasn't yet finished,
     // skip any session save activity.
     if (aBrowser.__SS_restore || !this._startupRestoreFinished || aBrowser.__SS_restoreReloadPending) {
+      sendEvent(aBrowser, "SSTabInputCaptured");
       return;
     }
 
     // Don't bother trying to save text data if we don't have history yet
     let data = aBrowser.__SS_data;
     if (!data || data.entries.length == 0) {
+      sendEvent(aBrowser, "SSTabInputCaptured");
       return;
     }
 
     // Start with storing the main content
     let content = aBrowser.contentWindow;
 
     // If the main content document has an associated URL that we are not
     // allowed to store data for, bail out. We explicitly discard data for any
     // children as well even if storing data for those frames would be allowed.
     if (!PrivacyLevel.check(content.document.documentURI)) {
+      sendEvent(aBrowser, "SSTabInputCaptured");
       return;
     }
 
     // Store the main content
     let formdata = FormData.collect(content) || {};
 
     // Loop over direct child frames, and store the text data
     let children = [];
@@ -908,16 +922,17 @@ SessionStore.prototype = {
     }
 
     // If we found any form data, main content or frames, let's save it
     if (Object.keys(formdata).length) {
       data.formdata = formdata;
       log("onTabInput() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id);
       this.saveStateDelayed();
     }
+    sendEvent(aBrowser, "SSTabInputCaptured");
   },
 
   onTabScroll: function ss_onTabScroll(aWindow, aBrowser) {
     // If we've been called directly, cancel any pending timeouts.
     if (this._scrollSavePending) {
       aWindow.clearTimeout(this._scrollSavePending);
       this._scrollSavePending = null;
       log("onTabScroll() clearing pending timeout");
@@ -973,18 +988,17 @@ SessionStore.prototype = {
     // Save some data that'll help in adjusting the zoom level
     // when restoring in a different screen orientation.
     scrolldata.zoom.displaySize = this._getContentViewerSize(content);
     log("onTabScroll() displayWidth: " + scrolldata.zoom.displaySize.width);
 
     // Save zoom and scroll data.
     data.scrolldata = scrolldata;
     log("onTabScroll() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id);
-    let evt = new Event("SSTabScrollCaptured", {"bubbles": true, "cancelable": false});
-    aBrowser.dispatchEvent(evt);
+    sendEvent(aBrowser, "SSTabScrollCaptured");
     this.saveStateDelayed();
   },
 
   _getContentViewerSize: function ss_getContentViewerSize(aWindow) {
     let displaySize = {};
     let width = {}, height = {};
     aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
       Ci.nsIDOMWindowUtils).getContentViewerSize(width, height);
--- a/mobile/android/tests/browser/chrome/test_session_form_data.html
+++ b/mobile/android/tests/browser/chrome/test_session_form_data.html
@@ -94,16 +94,18 @@ add_task(function* test_formdata() {
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
       yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
+      // Note: event must occur even if no info is captured due to privacy
+      yield promiseTabEvent(browser, "SSTabInputCaptured");
 
       // Remove the tab.
       gBrowserApp.closeTab(tab);
       yield promiseTabEvent(browser, "SSTabCloseProcessed");
     });
   }
 
   yield createAndRemoveTab();
@@ -149,16 +151,17 @@ add_task(function* test_formdata2() {
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
       yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
+      yield promiseTabEvent(browser, "SSTabInputCaptured");
 
       // Remove the tab.
       gBrowserApp.closeTab(tab);
       yield promiseTabEvent(browser, "SSTabCloseProcessed");
     });
   }
 
   yield createAndRemoveTab();
@@ -209,16 +212,17 @@ add_task(function* test_formdata_navigat
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
       yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
+      yield promiseTabEvent(browser, "SSTabInputCaptured");
 
       // Visit a different page.
       gBrowserApp.loadURI(otherURL, browser);
       yield promiseBrowserEvent(browser, "DOMContentLoaded");
       is(browser.currentURI.spec, otherURL, "navigated to a different page");
 
       // Go back.
       is(browser.canGoBack, true, "can go back");