From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- .../components/satchel/FormHistoryParent.sys.mjs | 123 +++++++++++++++++++-- 1 file changed, 116 insertions(+), 7 deletions(-) (limited to 'toolkit/components/satchel/FormHistoryParent.sys.mjs') diff --git a/toolkit/components/satchel/FormHistoryParent.sys.mjs b/toolkit/components/satchel/FormHistoryParent.sys.mjs index 8fe943566e..4c8a3dc7a2 100644 --- a/toolkit/components/satchel/FormHistoryParent.sys.mjs +++ b/toolkit/components/satchel/FormHistoryParent.sys.mjs @@ -2,16 +2,29 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { FirefoxRelayTelemetry } from "resource://gre/modules/FirefoxRelayTelemetry.mjs"; +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { FirefoxRelay: "resource://gre/modules/FirefoxRelay.sys.mjs", + FirefoxRelayTelemetry: "resource://gre/modules/FirefoxRelayTelemetry.mjs", FormHistory: "resource://gre/modules/FormHistory.sys.mjs", LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs", }); +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "PREFERENCE_PREFIX_WEIGHT", + "browser.formfill.prefixWeight" +); + +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "PREFERENCE_BOUNDARY_WEIGHT", + "browser.formfill.boundaryWeight" +); + export class FormHistoryParent extends JSWindowActorParent { receiveMessage({ name, data }) { switch (name) { @@ -27,7 +40,7 @@ export class FormHistoryParent extends JSWindowActorParent { break; case "PasswordManager:offerRelayIntegration": { - FirefoxRelayTelemetry.recordRelayOfferedEvent( + lazy.FirefoxRelayTelemetry.recordRelayOfferedEvent( "clicked", data.telemetry.flowId, data.telemetry.scenarioName @@ -36,7 +49,7 @@ export class FormHistoryParent extends JSWindowActorParent { } case "PasswordManager:generateRelayUsername": { - FirefoxRelayTelemetry.recordRelayUsernameFilledEvent( + lazy.FirefoxRelayTelemetry.recordRelayUsernameFilledEvent( "clicked", data.telemetry.flowId ); @@ -64,10 +77,28 @@ export class FormHistoryParent extends JSWindowActorParent { } async #onAutoCompleteSearch({ searchString, params, scenarioName }) { - const formHistoryPromise = lazy.FormHistory.getAutoCompleteResults( - searchString, - params - ); + searchString = searchString.trim().toLowerCase(); + + let formHistoryPromise; + if ( + FormHistoryParent.canSearchIncrementally( + searchString, + this.previousSearchString + ) + ) { + formHistoryPromise = Promise.resolve( + FormHistoryParent.incrementalSearch( + searchString, + this.previousSearchString, + this.previousSearchResult + ) + ); + } else { + formHistoryPromise = lazy.FormHistory.getAutoCompleteResults( + searchString, + params + ); + } const relayPromise = lazy.FirefoxRelay.autocompleteItemsAsync({ formOrigin: this.formOrigin, @@ -79,6 +110,9 @@ export class FormHistoryParent extends JSWindowActorParent { relayPromise, ]); + this.previousSearchString = searchString; + this.previousSearchResult = formHistoryEntries; + return { formHistoryEntries, externalEntries }; } @@ -104,4 +138,79 @@ export class FormHistoryParent extends JSWindowActorParent { const browser = this.getRootBrowser(); return lazy.FirefoxRelay.generateUsername(browser, this.formOrigin); } + + async searchAutoCompleteEntries(searchString, data) { + const { inputName, scenarioName } = data; + const params = { + fieldname: inputName, + }; + return this.#onAutoCompleteSearch({ searchString, params, scenarioName }); + } + + static canSearchIncrementally(searchString, previousSearchString) { + previousSearchString ||= ""; + return ( + previousSearchString.length > 1 && + searchString.includes(previousSearchString) + ); + } + + static incrementalSearch( + searchString, + previousSearchString, + previousSearchResult + ) { + const searchTokens = searchString.split(/\s+/); + // We have a list of results for a shorter search string, so just + // filter them further based on the new search string and add to a new array. + let filteredEntries = []; + for (const entry of previousSearchResult) { + // Remove results that do not contain the token + // XXX bug 394604 -- .toLowerCase can be wrong for some intl chars + if (searchTokens.some(tok => !entry.textLowerCase.includes(tok))) { + continue; + } + FormHistoryParent.calculateScore(entry, searchString, searchTokens); + filteredEntries.push(entry); + } + filteredEntries.sort((a, b) => b.totalScore - a.totalScore); + return filteredEntries; + } + + /* + * calculateScore + * + * entry -- an nsIAutoCompleteResult entry + * searchString -- current value of the input (lowercase) + * searchTokens -- array of tokens of the search string + * + * Returns: an int + */ + static calculateScore(entry, searchString, searchTokens) { + let boundaryCalc = 0; + // for each word, calculate word boundary weights + for (const token of searchTokens) { + if (entry.textLowerCase.startsWith(token)) { + boundaryCalc++; + } + if (entry.textLowerCase.includes(" " + token)) { + boundaryCalc++; + } + } + boundaryCalc = boundaryCalc * lazy.PREFERENCE_BOUNDARY_WEIGHT; + // now add more weight if we have a traditional prefix match and + // multiply boundary bonuses by boundary weight + if (entry.textLowerCase.startsWith(searchString)) { + boundaryCalc += lazy.PREFERENCE_PREFIX_WEIGHT; + } + entry.totalScore = Math.round(entry.frecency * Math.max(1, boundaryCalc)); + } + + previewFields(_result) { + // Not implemented + } + + autofillFields(_result) { + // Not implemented + } } -- cgit v1.2.3