Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
namespace logins {
/// We expose the crypto primitives on the namespace
/// Create a new, random, encryption key.
[Throws=LoginsApiError]
string create_key();
/// Create a "canary" string, which can be used to test if the encryption
//key is still valid for the logins data
[Throws=LoginsApiError]
string create_canary([ByRef]string text, [ByRef]string encryption_key);
/// Check that key is still valid using the output of `create_canary`.
//`text` much match the text you initially passed to `create_canary()`
[Throws=LoginsApiError]
boolean check_canary([ByRef]string canary, [ByRef]string text, [ByRef]string encryption_key);
/// Utility function to create a StaticKeyManager to be used for the time
/// being until support lands for [trait implementation of an UniFFI
/// in UniFFI.
KeyManager create_static_key_manager(string key);
/// Similar to create_static_key_manager above, create a
/// ManagedEncryptorDecryptor by passing in a KeyManager
EncryptorDecryptor create_managed_encdec(KeyManager key_manager);
/// Create a LoginStore with StaticKeyManager by passing in a db path and a
/// static key
LoginStore create_login_store_with_static_key_manager(string path, string key);
};
/// A login entry from the user, not linked to any database record.
/// The add/update APIs input these.
dictionary LoginEntry {
// login fields
string origin;
string? http_realm;
string? form_action_origin;
string username_field;
string password_field;
// secure login fields
string password;
string username;
};
/// Login data specific to database records.
/// The add_with_record API inputs this.
dictionary LoginMeta {
string id;
i64 times_used;
i64 time_created;
i64 time_last_used;
i64 time_password_changed;
};
/// A login together with record fields, handed over to the store API; ie a login persisted
/// elsewhere, useful for migrations
dictionary LoginEntryWithMeta {
LoginEntry entry;
LoginMeta meta;
};
/// A bulk insert result entry, returned by `add_many` and `add_many_with_meta`
[Enum]
interface BulkResultEntry {
Success(Login login);
Error(string message);
};
/// A login stored in the database
dictionary Login {
// meta fields
string id;
i64 times_used;
i64 time_created;
i64 time_last_used;
i64 time_password_changed;
// login fields
string origin;
string? http_realm;
string? form_action_origin;
string username_field;
string password_field;
// secure login fields
string password;
string username;
};
/// Metrics tracking deletion of logins that cannot be decrypted, see `delete_undecryptable_records_for_remote_replacement`
/// for more details
dictionary LoginsDeletionMetrics {
u64 local_deleted;
u64 mirror_deleted;
};
/// These are the errors returned by our public API.
[Error]
interface LoginsApiError {
/// NSS not initialized.
NSSUninitialized();
/// NSS error during authentication
NSSAuthenticationError(string reason);
/// error during authentication (in PrimaryPasswordAuthenticator)
AuthenticationError(string reason);
/// authentication has been cancelled.
AuthenticationCanceled();
/// The login data supplied is invalid. The reason will indicate what's wrong with it.
InvalidRecord(string reason);
/// Asking to do something with a guid which doesn't exist.
NoSuchRecord(string reason);
/// Encryption key is missing.
MissingKey();
/// Encryption key is not valid.
InvalidKey();
/// encryption failed
EncryptionFailed(string reason);
/// decryption failed
DecryptionFailed(string reason);
/// An operation was interrupted at the request of the consuming app.
Interrupted(string reason);
/// Sync reported that authentication failed and the user should re-enter their FxA password.
// TODO: remove this at the same time as remove the sync() method in favour of the SyncManager.
SyncAuthInvalid(string reason);
/// something internal went wrong which doesn't have a public error value
/// because the consuming app can not reasonably take any action to resolve it.
/// The underlying error will have been logged and reported.
/// (ideally would just be `Unexpected`, but that would be a breaking change)
UnexpectedLoginsApiError(string reason);
};
[Trait, WithForeign]
interface EncryptorDecryptor {
[Throws=LoginsApiError]
bytes encrypt(bytes cleartext);
[Throws=LoginsApiError]
bytes decrypt(bytes ciphertext);
};
[Trait, WithForeign]
interface KeyManager {
[Throws=LoginsApiError]
bytes get_key();
};
interface StaticKeyManager {
constructor(string key);
};
interface ManagedEncryptorDecryptor {
constructor(KeyManager key_manager);
};
interface LoginStore {
[Throws=LoginsApiError]
constructor(string path, EncryptorDecryptor encdec);
[Throws=LoginsApiError]
Login add(LoginEntry login);
[Throws=LoginsApiError]
sequence<BulkResultEntry> add_many(sequence<LoginEntry> logins);
[Throws=LoginsApiError]
Login add_with_meta(LoginEntryWithMeta entry_with_meta);
[Throws=LoginsApiError]
sequence<BulkResultEntry> add_many_with_meta(sequence<LoginEntryWithMeta> entries_with_meta);
[Throws=LoginsApiError]
Login update([ByRef] string id, LoginEntry login);
[Throws=LoginsApiError]
Login add_or_update(LoginEntry login);
[Throws=LoginsApiError]
boolean delete([ByRef] string id);
[Throws=LoginsApiError, Self=ByArc]
sequence<boolean> delete_many(sequence<string> ids);
/// Clear out locally stored logins data
///
/// If sync is enabled, then we will try to recover the data on the next sync.
///
/// The main reason to call this is when regenerating a new encryption key.
/// In that case, there's no reason to keep around the local data since it can't be decrypted.
/// Calling `wipe_local` is better than keeping around these un-decryptable logins, since we
/// might be able to recover the data via sync.
///
/// This is a no-op for freshly created databases, so it's safe to call this whenever a key is
/// generated.
[Throws=LoginsApiError]
void wipe_local();
[Throws=LoginsApiError, Self=ByArc]
void reset();
/// The `delete_undecryptable_records_for_remote_replacement` function locally deletes stored logins
/// that cannot be decrypted and sets the last sync time to 0 so any existing server records can be downloaded
/// and overwrite the locally deleted records.
///
/// NB: This function was created to unblock iOS logins users who are unable to sync logins and should not be used
/// outside of this use case.
[Throws=LoginsApiError, Self=ByArc]
LoginsDeletionMetrics delete_undecryptable_records_for_remote_replacement();
[Throws=LoginsApiError]
void touch([ByRef] string id);
[Throws=LoginsApiError]
boolean is_empty();
[Throws=LoginsApiError]
i64 count();
[Throws=LoginsApiError]
i64 count_by_origin([ByRef] string origin);
[Throws=LoginsApiError]
i64 count_by_form_action_origin([ByRef] string form_action_origin);
[Throws=LoginsApiError]
sequence<Login> list();
[Throws=LoginsApiError]
sequence<Login> get_by_base_domain([ByRef] string base_domain);
[Throws=LoginsApiError]
boolean has_logins_by_base_domain([ByRef] string base_domain);
[Throws=LoginsApiError]
Login? find_login_to_update(LoginEntry look);
[Throws=LoginsApiError]
Login? get([ByRef] string id);
[Throws=LoginsApiError]
void set_checkpoint([ByRef] string checkpoint);
[Throws=LoginsApiError]
string? get_checkpoint();
/// Run maintenance on the DB
///
/// This is intended to be run during idle time and will take steps / to clean up / shrink the
/// database.
[Throws=LoginsApiError]
void run_maintenance();
[Self=ByArc]
void register_with_sync_manager();
[Self=ByArc]
void shutdown();
};