GeckoView 登录存储 API

Eugen Sawin <esawin@mozilla.com>

2019年12月20日

动机

当前的 GV 自动填充 API 提供了实现自动填充/登录应用程序支持的所有基本回调和元信息。它还管理回退到 Android AutofillManager,后者将请求委托给用户设置的系统范围的自动填充服务。

但是,当前的 GV 自动填充 API 没有利用处理许多自动填充/登录场景的 Gecko 启发式的完整范围。

GV 登录存储 API 旨在弥合这一差距,并为 Fenix 提供一个中间解决方案,以实现功能丰富的自动填充/登录支持,而无需复制 Gecko 机制。作为存储级 API,它还可以轻松集成到现有的 Firefox 同步 AC 中。

API 提案 A(已弃用)

统一登录存储 API:会话委托

class LoginStorage {
    class Login {
        String guid;
        // @Fenix: currently called `hostname` in AsyncLoginsStorage.
        String origin;
        // @Fenix: currently called `formSubmitURL` in AsyncLoginsStorage
        String formActionOrigin;
        String httpRealm;
        String username;
        String password;
    }

    class Hint {
        // @Fenix: Automatically save the login and indicate this to the
        // user.
        int GENERATED;
        // @Fenix: Don’t prompt to save but allow the user to open UI to
        // save if they really want.
        int PRIVATE_MODE;
        // The data looks like it may be some other data (e.g. CC) entered
        // in a password field.
        // @Fenix: Don’t prompt to save but allow the user to open UI to
        // save if they want (e.g. in case the CC number is actually the
        // username for a credit card account)
        int LOW_CONFIDENCE;
        // TBD
    }

    interface Delegate {
        // Notify that the given login has been used for login.
        // @Fenix: call AsyncLoginsStorage.touch(login.guid).
        void onLoginUsed(Login login);

        // Request logins for the given domain.
        // @Fenix: return AsyncLoginsStorage.getByHostname(domain).
        GeckoResult<Login[]> onLoginRequest(String domain);

        // Request to save or update the given login.
        // The hint should help determining the appropriate user prompting
        // behavior.
        // @Fenix: Use the API from application-services/issues/1983 to
        // determine whether to show a Save or Update button on the
        // doorhanger, taking into account un/pw edits in the doorhanger.
        // When the user confirms the save/update,
        void onLoginSave(Login login, int hint);

        // TBD (next API iteration): handle autocomplete selection.
        // GeckoResult<Login> onLoginSelect(Login[] logins);
    }
}

GeckoSession 的扩展

// Extending existing session class.
class GeckoSession {
    // Set the login storage delegate for this session.
    void setLoginStorageDelegate(LoginStorage.Delegate delegate);

    LoginStorage.Delegate getLoginStorageDelegate();
}

API 提案 B

拆分登录存储 API:运行时存储委托/会话提示

将存储和提示分开。登录的获取和保存由运行时委托处理,保存提示以及(将来)自动完成功能由提示委托处理。

class LoginStorage {
    class Login {
        String guid;
        // @Fenix: currently called `hostname` in AsyncLoginsStorage.
        String origin;
        // @Fenix: currently called `formSubmitURL` in AsyncLoginsStorage
        String formActionOrigin;
        String httpRealm;
        String username;
        String password;
    }

    interface Delegate {
        // v2
        // Notify that the given login has been used for login.
        // @Fenix: call AsyncLoginsStorage.touch(login.guid).
        void onLoginUsed(Login login);

        // Request logins for the given domain.
        // @Fenix: return AsyncLoginsStorage.getByHostname(domain).
        GeckoResult<Login[]> onLoginFetch(String domain);

        // Request to save or update the given login.
        void onLoginSave(Login login);
    }
}

GeckoRuntime 的扩展

// Extending existing runtime class.
class GeckoRuntime {
    // Set the login storage delegate for this runtime.
    void setLoginStorageDelegate(LoginStorage.Delegate delegate);
}

GeckoSession.PromptDelegate 的扩展

// Extending existing prompt delegate.
class GeckoSession {
    interface PromptDelegate {
        class LoginStoragePrompt extends BasePrompt {
            class Type {
                int SAVE;
                // TBD: autocomplete selection.
                // int SELECT;
            }

            class Hint {
                // v2
                // @Fenix: Automatically save the login and indicate this
                // to the user.
                int GENERATED;
                // @Fenix: Don’t prompt to save but allow the user to open
                // UI to save if they really want.
                int PRIVATE_MODE;
                // The data looks like it may be some other data (e.g. CC)
                // entered in a password field
                // @Fenix: Don’t prompt to save but allow the user to open
                // UI to save if they want (e.g. in case the CC number is
                // actually the username for a credit card account)
                int LOW_CONFIDENCE;
                // TBD
            }

            // Type
            int type;

            // Hint
            // The hint should help determining the appropriate user
            // prompting behavior.
            // @Fenix: Use the API from application-services/issues/1983 to
            // determine whether to show a Save or Update button on the
            // doorhanger, taking into account un/pw edits in the
            // doorhanger. When the user confirms the save/update.
            int hint;

            // For SAVE, it will hold the login to be stored or updated.
            // For SELECT, it will hold the logins for the autocomplete
            // selection.
            Login[] logins;

            // Confirm SAVE prompt: the login would include a user’s edits
            // to what will be saved.
            // v2
            // Confirm SELECT (autocomplete) prompt by providing the
            // selected login.
            PromptResponse confirm(Login login);

            // Dismiss request.
            PromptResponse dismiss();
        }

        GeckoResult<PromptResponse> onLoginStoragePrompt(
            GeckoSession session,
            LoginStoragePrompt prompt
        );
    }
}