Backed out changeset f556e62f5ee8 (bug 993197) for causing bug 1030663 a=orange
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 27 Jun 2014 15:18:16 +0200
changeset 204894 83f9b25520bfa86866822d7be16e3c0c61686df0
parent 204893 115171f8216d3b15f142e53e11a495b6c79d3c8b
child 204943 cc7244eea5d5a28583571a078002e3cfb9aaf077
push idunknown
push userunknown
push dateunknown
reviewersorange
bugs993197, 1030663
milestone33.0a1
backs outf556e62f5ee81d28e29b7d46e69fa028e48add5d
Backed out changeset f556e62f5ee8 (bug 993197) for causing bug 1030663 a=orange
toolkit/components/passwordmgr/nsILoginManager.idl
toolkit/components/passwordmgr/nsLoginManager.js
toolkit/components/satchel/nsFormFillController.cpp
--- a/toolkit/components/passwordmgr/nsILoginManager.idl
+++ b/toolkit/components/passwordmgr/nsILoginManager.idl
@@ -3,22 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "nsISupports.idl"
 
 interface nsIURI;
 interface nsILoginInfo;
 interface nsIAutoCompleteResult;
-interface nsIFormAutoCompleteObserver;
 interface nsIDOMHTMLInputElement;
 interface nsIDOMHTMLFormElement;
 interface nsIPropertyBag;
 
-[scriptable, uuid(f441b0a3-6588-455e-baa8-2e2dbba84655)]
+[scriptable, uuid(f5f2a39a-dffe-4eb9-ad28-340afd53b1a3)]
+
 interface nsILoginManager : nsISupports {
     /**
      * This promise is resolved when initialization is complete, and is rejected
      * in case initialization failed.  This includes the initial loading of the
      * login data as well as any migration from previous versions.
      *
      * Calling any method of nsILoginManager before this promise is resolved
      * might trigger the synchronous initialization fallback.
@@ -205,20 +205,19 @@ interface nsILoginManager : nsISupports 
 
     /**
      * Generate results for a userfield autocomplete menu.
      *
      * NOTE: This interface is provided for use only by the FormFillController,
      *       which calls it directly. This isn't really ideal, it should
      *       probably be callback registered through the FFC.
      */
-    void autoCompleteSearchAsync(in AString aSearchString,
-                                 in nsIAutoCompleteResult aPreviousResult,
-                                 in nsIDOMHTMLInputElement aElement,
-                                 in nsIFormAutoCompleteObserver aListener);
+    nsIAutoCompleteResult autoCompleteSearch(in AString aSearchString,
+                                    in nsIAutoCompleteResult aPreviousResult,
+                                    in nsIDOMHTMLInputElement aElement);
 
     /**
      * Fill a form with login information if we have it. This method will fill
      * aForm regardless of the signon.autofillForms preference.
      *
      * @param aForm
      *        The form to fill
      * @return Success of attempt fill form
--- a/toolkit/components/passwordmgr/nsLoginManager.js
+++ b/toolkit/components/passwordmgr/nsLoginManager.js
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/Timer.jsm");
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
                                   "resource://gre/modules/LoginManagerContent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
                                   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
@@ -404,44 +403,42 @@ LoginManager.prototype = {
         // Nulls won't round-trip with getAllDisabledHosts().
         if (hostname.indexOf("\0") != -1)
             throw "Invalid hostname";
 
         log("Login saving for", hostname, "now enabled?", enabled);
         return this._storage.setLoginSavingEnabled(hostname, enabled);
     },
 
+
     /*
-     * autoCompleteSearchAsync
+     * autoCompleteSearch
      *
      * Yuck. This is called directly by satchel:
      * nsFormFillController::StartSearch()
-     * [toolkit/components/satchel/nsFormFillController.cpp]
+     * [toolkit/components/satchel/src/nsFormFillController.cpp]
      *
      * We really ought to have a simple way for code to register an
      * auto-complete provider, and not have satchel calling pwmgr directly.
      */
-    autoCompleteSearchAsync : function (aSearchString, aPreviousResult,
-                                        aElement, aCallback) {
+    autoCompleteSearch : function (aSearchString, aPreviousResult, aElement) {
         // aPreviousResult & aResult are nsIAutoCompleteResult,
         // aElement is nsIDOMHTMLInputElement
 
-        if (!this._remember) {
-            setTimeout(function() {
-                aCallback.onSearchCompletion(new UserAutoCompleteResult(aSearchString, []));
-            }, 0);
-            return;
-        }
+        if (!this._remember)
+            return null;
 
         log("AutoCompleteSearch invoked. Search is:", aSearchString);
 
+        var result = null;
+
         if (aPreviousResult &&
                 aSearchString.substr(0, aPreviousResult.searchString.length) == aPreviousResult.searchString) {
             log("Using previous autocomplete result");
-            let result = aPreviousResult;
+            result = aPreviousResult;
             result.wrappedJSObject.searchString = aSearchString;
 
             // We have a list of results for a shorter search string, so just
             // filter them further based on the new search string.
             // Count backwards, because result.matchCount is decremented
             // when we remove an entry.
             for (var i = result.matchCount - 1; i >= 0; i--) {
                 var match = result.getValueAt(i);
@@ -450,57 +447,57 @@ LoginManager.prototype = {
                 if (aSearchString.length > match.length ||
                     aSearchString.toLowerCase() !=
                         match.substr(0, aSearchString.length).toLowerCase())
                 {
                     log("Removing autocomplete entry:", match);
                     result.removeValueAt(i, false);
                 }
             }
-
-            setTimeout(function() { aCallback.onSearchCompletion(result); }, 0);
         } else {
             log("Creating new autocomplete search result.");
 
-            setTimeout(function() {
-                var doc = aElement.ownerDocument;
-                var origin = this._getPasswordOrigin(doc.documentURI);
-                var actionOrigin = this._getActionOrigin(aElement.form);
+            var doc = aElement.ownerDocument;
+            var origin = this._getPasswordOrigin(doc.documentURI);
+            var actionOrigin = this._getActionOrigin(aElement.form);
 
-                // This shouldn't trigger a master password prompt, because we
-                // don't attach to the input until after we successfully obtain
-                // logins for the form.
-                var logins = this.findLogins({}, origin, actionOrigin, null);
-                var matchingLogins = [];
+            // This shouldn't trigger a master password prompt, because we
+            // don't attach to the input until after we successfully obtain
+            // logins for the form.
+            var logins = this.findLogins({}, origin, actionOrigin, null);
+            var matchingLogins = [];
 
-                // Filter out logins that don't match the search prefix. Also
-                // filter logins without a username, since that's confusing to see
-                // in the dropdown and we can't autocomplete them anyway.
-                for (let i = 0; i < logins.length; i++) {
-                    var username = logins[i].username.toLowerCase();
-                    log(username);
-                    if (username &&
-                        aSearchString.length <= username.length &&
-                        aSearchString.toLowerCase() ==
-                            username.substr(0, aSearchString.length))
-                    {
-                        matchingLogins.push(logins[i]);
-                    }
+            // Filter out logins that don't match the search prefix. Also
+            // filter logins without a username, since that's confusing to see
+            // in the dropdown and we can't autocomplete them anyway.
+            for (i = 0; i < logins.length; i++) {
+                var username = logins[i].username.toLowerCase();
+                if (username &&
+                    aSearchString.length <= username.length &&
+                    aSearchString.toLowerCase() ==
+                        username.substr(0, aSearchString.length))
+                {
+                    matchingLogins.push(logins[i]);
                 }
-                log(matchingLogins.length, "autocomplete logins avail.");
-                aCallback.onSearchCompletion(new UserAutoCompleteResult(aSearchString,
-                                                                        matchingLogins));
-            }.bind(this), 0);
+            }
+            log(matchingLogins.length, "autocomplete logins avail.");
+            result = new UserAutoCompleteResult(aSearchString, matchingLogins);
         }
+
+        return result;
     },
 
 
+
+
     /* ------- Internal methods / callbacks for document integration ------- */
 
 
+
+
     /*
      * _getPasswordOrigin
      *
      * Get the parts of the URL we want for identification.
      */
     _getPasswordOrigin : function (uriString, allowJS) {
         var realm = "";
         try {
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -594,29 +594,32 @@ nsFormFillController::GetInPrivateContex
 ////////////////////////////////////////////////////////////////////////
 //// nsIAutoCompleteSearch
 
 NS_IMETHODIMP
 nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAString &aSearchParam,
                                   nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener)
 {
   nsresult rv;
+  nsCOMPtr<nsIAutoCompleteResult> result;
 
   // If the login manager has indicated it's responsible for this field, let it
   // handle the autocomplete. Otherwise, handle with form history.
   bool dummy;
   if (mPwmgrInputs.Get(mFocusedInputNode, &dummy)) {
     // XXX aPreviousResult shouldn't ever be a historyResult type, since we're not letting
     // satchel manage the field?
-    mLastListener = aListener;
-    rv = mLoginManager->AutoCompleteSearchAsync(aSearchString,
-                                                aPreviousResult,
-                                                mFocusedInput,
-                                                this);
+    rv = mLoginManager->AutoCompleteSearch(aSearchString,
+                                           aPreviousResult,
+                                           mFocusedInput,
+                                           getter_AddRefs(result));
     NS_ENSURE_SUCCESS(rv, rv);
+    if (aListener) {
+      aListener->OnSearchResult(this, result);
+    }
   } else {
     mLastListener = aListener;
 
     // It appears that mFocusedInput is always null when we are focusing a XUL
     // element. Scary :)
     if (!mFocusedInput || nsContentUtils::IsAutocompleteEnabled(mFocusedInput)) {
       nsCOMPtr <nsIFormAutoComplete> formAutoComplete =
         do_GetService("@mozilla.org/satchel/form-autocomplete;1", &rv);
@@ -645,52 +648,42 @@ nsresult
 nsFormFillController::PerformInputListAutoComplete(nsIAutoCompleteResult* aPreviousResult)
 {
   // If an <input> is focused, check if it has a list="<datalist>" which can
   // provide the list of suggestions.
 
   nsresult rv;
   nsCOMPtr<nsIAutoCompleteResult> result;
 
-  bool dummy;
-  if (!mPwmgrInputs.Get(mFocusedInputNode, &dummy)) {
-    nsCOMPtr <nsIInputListAutoComplete> inputListAutoComplete =
-      do_GetService("@mozilla.org/satchel/inputlist-autocomplete;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = inputListAutoComplete->AutoCompleteSearch(aPreviousResult,
-                                                   mLastSearchString,
-                                                   mFocusedInput,
-                                                   getter_AddRefs(result));
-    NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr <nsIInputListAutoComplete> inputListAutoComplete =
+    do_GetService("@mozilla.org/satchel/inputlist-autocomplete;1", &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = inputListAutoComplete->AutoCompleteSearch(aPreviousResult,
+                                                 mLastSearchString,
+                                                 mFocusedInput,
+                                                 getter_AddRefs(result));
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    if (mFocusedInput) {
-      nsCOMPtr<nsIDOMHTMLElement> list;
-      mFocusedInput->GetList(getter_AddRefs(list));
+  if (mFocusedInput) {
+    nsCOMPtr<nsIDOMHTMLElement> list;
+    mFocusedInput->GetList(getter_AddRefs(list));
 
-      // Add a mutation observer to check for changes to the items in the <datalist>
-      // and update the suggestions accordingly.
-      nsCOMPtr<nsINode> node = do_QueryInterface(list);
-      if (mListNode != node) {
-        if (mListNode) {
-          mListNode->RemoveMutationObserver(this);
-          mListNode = nullptr;
-        }
-        if (node) {
-          node->AddMutationObserverUnlessExists(this);
-          mListNode = node;
-        }
+    // Add a mutation observer to check for changes to the items in the <datalist>
+    // and update the suggestions accordingly.
+    nsCOMPtr<nsINode> node = do_QueryInterface(list);
+    if (mListNode != node) {
+      if (mListNode) {
+        mListNode->RemoveMutationObserver(this);
+        mListNode = nullptr;
+      }
+      if (node) {
+        node->AddMutationObserverUnlessExists(this);
+        mListNode = node;
       }
     }
-  } else {
-    result = aPreviousResult;
-
-    // If this is a password manager input mLastSearchResult will be a JS
-    // object (wrapped in an XPConnect reflector), so we need to take care not
-    // to hold onto it for too long.
-    mLastSearchResult = nullptr;
   }
 
   if (mLastListener) {
     mLastListener->OnSearchResult(this, result);
   }
 
   return NS_OK;
 }