mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 993197 - Asynchronize nsILoginManager::autoCompleteSearch. r=dolske
This commit is contained in:
parent
16016e0fde
commit
564639d6e1
@ -8,12 +8,12 @@
|
||||
interface nsIURI;
|
||||
interface nsILoginInfo;
|
||||
interface nsIAutoCompleteResult;
|
||||
interface nsIFormAutoCompleteObserver;
|
||||
interface nsIDOMHTMLInputElement;
|
||||
interface nsIDOMHTMLFormElement;
|
||||
interface nsIPropertyBag;
|
||||
|
||||
[scriptable, uuid(f5f2a39a-dffe-4eb9-ad28-340afd53b1a3)]
|
||||
|
||||
[scriptable, uuid(f441b0a3-6588-455e-baa8-2e2dbba84655)]
|
||||
interface nsILoginManager : nsISupports {
|
||||
/**
|
||||
* This promise is resolved when initialization is complete, and is rejected
|
||||
@ -210,9 +210,10 @@ interface nsILoginManager : nsISupports {
|
||||
* which calls it directly. This isn't really ideal, it should
|
||||
* probably be callback registered through the FFC.
|
||||
*/
|
||||
nsIAutoCompleteResult autoCompleteSearch(in AString aSearchString,
|
||||
in nsIAutoCompleteResult aPreviousResult,
|
||||
in nsIDOMHTMLInputElement aElement);
|
||||
void autoCompleteSearchAsync(in AString aSearchString,
|
||||
in nsIAutoCompleteResult aPreviousResult,
|
||||
in nsIDOMHTMLInputElement aElement,
|
||||
in nsIFormAutoCompleteObserver aListener);
|
||||
|
||||
/**
|
||||
* Fill a form with login information if we have it. This method will fill
|
||||
|
@ -8,6 +8,7 @@ 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",
|
||||
@ -408,32 +409,34 @@ LoginManager.prototype = {
|
||||
return this._storage.setLoginSavingEnabled(hostname, enabled);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* autoCompleteSearch
|
||||
* autoCompleteSearchAsync
|
||||
*
|
||||
* Yuck. This is called directly by satchel:
|
||||
* nsFormFillController::StartSearch()
|
||||
* [toolkit/components/satchel/src/nsFormFillController.cpp]
|
||||
* [toolkit/components/satchel/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.
|
||||
*/
|
||||
autoCompleteSearch : function (aSearchString, aPreviousResult, aElement) {
|
||||
autoCompleteSearchAsync : function (aSearchString, aPreviousResult,
|
||||
aElement, aCallback) {
|
||||
// aPreviousResult & aResult are nsIAutoCompleteResult,
|
||||
// aElement is nsIDOMHTMLInputElement
|
||||
|
||||
if (!this._remember)
|
||||
return null;
|
||||
if (!this._remember) {
|
||||
setTimeout(function() {
|
||||
aCallback.onSearchCompletion(new UserAutoCompleteResult(aSearchString, []));
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
log("AutoCompleteSearch invoked. Search is:", aSearchString);
|
||||
|
||||
var result = null;
|
||||
|
||||
if (aPreviousResult &&
|
||||
aSearchString.substr(0, aPreviousResult.searchString.length) == aPreviousResult.searchString) {
|
||||
log("Using previous autocomplete result");
|
||||
result = aPreviousResult;
|
||||
let result = aPreviousResult;
|
||||
result.wrappedJSObject.searchString = aSearchString;
|
||||
|
||||
// We have a list of results for a shorter search string, so just
|
||||
@ -452,47 +455,47 @@ LoginManager.prototype = {
|
||||
result.removeValueAt(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function() { aCallback.onSearchCompletion(result); }, 0);
|
||||
} else {
|
||||
log("Creating new autocomplete search result.");
|
||||
|
||||
var doc = aElement.ownerDocument;
|
||||
var origin = this._getPasswordOrigin(doc.documentURI);
|
||||
var actionOrigin = this._getActionOrigin(aElement.form);
|
||||
setTimeout(function() {
|
||||
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 (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]);
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
log(matchingLogins.length, "autocomplete logins avail.");
|
||||
result = new UserAutoCompleteResult(aSearchString, matchingLogins);
|
||||
log(matchingLogins.length, "autocomplete logins avail.");
|
||||
aCallback.onSearchCompletion(new UserAutoCompleteResult(aSearchString,
|
||||
matchingLogins));
|
||||
}.bind(this), 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------- Internal methods / callbacks for document integration ------- */
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* _getPasswordOrigin
|
||||
*
|
||||
|
@ -599,7 +599,6 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
|
||||
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.
|
||||
@ -607,14 +606,12 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
|
||||
if (mPwmgrInputs.Get(mFocusedInputNode, &dummy)) {
|
||||
// XXX aPreviousResult shouldn't ever be a historyResult type, since we're not letting
|
||||
// satchel manage the field?
|
||||
rv = mLoginManager->AutoCompleteSearch(aSearchString,
|
||||
aPreviousResult,
|
||||
mFocusedInput,
|
||||
getter_AddRefs(result));
|
||||
mLastListener = aListener;
|
||||
rv = mLoginManager->AutoCompleteSearchAsync(aSearchString,
|
||||
aPreviousResult,
|
||||
mFocusedInput,
|
||||
this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aListener) {
|
||||
aListener->OnSearchResult(this, result);
|
||||
}
|
||||
} else {
|
||||
mLastListener = aListener;
|
||||
|
||||
@ -653,32 +650,42 @@ nsFormFillController::PerformInputListAutoComplete(nsIAutoCompleteResult* aPrevi
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAutoCompleteResult> result;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user