Bug 936026 - Autofill login forms after restoring documents from bfcache. r=jaws
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 20 Mar 2019 14:21:55 +0000
changeset 465224 4ce441f87fdf4abc6443ff83d610b2adff4d3885
parent 465223 2a807fde4c47339f48e548127d215880183fbcae
child 465225 48cd73fc089340f641dab57d6563e66b6738d731
push id112496
push usershindli@mozilla.com
push dateThu, 21 Mar 2019 04:37:39 +0000
treeherdermozilla-inbound@29476d3ca61d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs936026
milestone68.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 936026 - Autofill login forms after restoring documents from bfcache. r=jaws Differential Revision: https://phabricator.services.mozilla.com/D22212
toolkit/components/passwordmgr/LoginManagerContent.jsm
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -64,16 +64,24 @@ var observer = {
     }
 
     log("onLocationChange handled:", aLocation.displaySpec, aWebProgress.DOMWindow.document);
 
     LoginManagerContent._onNavigation(aWebProgress.DOMWindow.document);
   },
 
   onStateChange(aWebProgress, aRequest, aState, aStatus) {
+    if ((aState & Ci.nsIWebProgressListener.STATE_RESTORING) &&
+        (aState & Ci.nsIWebProgressListener.STATE_STOP)) {
+      // Re-fill a document restored from bfcache since password field values
+      // aren't persisted there.
+      LoginManagerContent._onDocumentRestored(aWebProgress.DOMWindow.document);
+      return;
+    }
+
     if (!(aState & Ci.nsIWebProgressListener.STATE_START)) {
       return;
     }
 
     // We only care about when a page triggered a load, not the user. For example:
     // clicking refresh/back/forward, typing a URL and hitting enter, and loading a bookmark aren't
     // likely to be when a user wants to save a login.
     let channel = aRequest.QueryInterface(Ci.nsIChannel);
@@ -976,17 +984,39 @@ var LoginManagerContent = {
    * @return true if the page requests autocomplete be disabled for the
    *              specified element.
    */
   _isAutocompleteDisabled(element) {
     return element && element.autocomplete == "off";
   },
 
   /**
-   * Trigger capture on any relevant LoginForms due to a navigation alone (not
+   * Fill a page that was restored from bfcache since we wouldn't receive
+   * DOMInputPasswordAdded or DOMFormHasPassword events for it.
+   * @param {Document} aDocument that was restored from bfcache.
+   */
+  _onDocumentRestored(aDocument) {
+    let rootElsWeakSet = LoginFormFactory.getRootElementsWeakSetForDocument(aDocument);
+    let weakLoginFormRootElements = ChromeUtils.nondeterministicGetWeakSetKeys(rootElsWeakSet);
+
+    log("_onDocumentRestored: loginFormRootElements approx size:", weakLoginFormRootElements.length,
+        "document:", aDocument);
+
+    for (let formRoot of weakLoginFormRootElements) {
+      if (!formRoot.isConnected) {
+        continue;
+      }
+
+      let formLike = LoginFormFactory.getForRootElement(formRoot);
+      this._fetchLoginsFromParentAndFillForm(formLike);
+    }
+  },
+
+  /**
+   * Trigger capture on any relevant FormLikes due to a navigation alone (not
    * necessarily due to an actual form submission). This method is used to
    * capture logins for cases where form submit events are not used.
    *
    * To avoid multiple notifications for the same LoginForm, this currently
    * avoids capturing when dealing with a real <form> which are ideally already
    * using a submit event.
    *
    * @param {Document} document being navigated