/* 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/. */

#include "nsISupports.idl"

interface nsILoginInfo;
interface nsIPropertyBag;

[scriptable, uuid(43429075-ede6-41eb-ac69-a8cd4376b041)]
interface nsILoginSearchCallback : nsISupports
{
  /**
   * Called when a search is complete and the results are ready.
   *
   * @param aLogins
   *        Logins found in the search.
   */
  void onSearchComplete(in Array<nsILoginInfo> aLogins);
};

[scriptable, uuid(406c5518-b20d-411c-bf01-1b1b545dab64)]
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.
   */
  readonly attribute Promise initializationPromise;

  /**
   * Like addLogin, but asynchronous.
   *
   * @param aLogin
   *        The login to be added.
   * @return A promise which resolves with a cloned login with the guid set.
   *
   * Default values for each login's nsILoginMetaInfo properties will be
   * created. However, if the caller specifies non-default values, they will
   * be used instead.
   */
  Promise addLoginAsync(in nsILoginInfo aLogin);

  /**
   * Like addLogin, but asynchronous and for many logins.
   *
   * @param aLogins
   *        A JS Array of nsILoginInfos to add.
   * @return A promise which resolves with a JS Array of cloned logins with
   *         the guids set.
   *
   * Default values for each login's nsILoginMetaInfo properties will be
   * created. However, if the caller specifies non-default values, they will
   * be used instead.
   */
  Promise addLogins(in jsval aLogins);

  /**
   * Remove a login from the login manager.
   *
   * @param aLogin
   *        The login to be removed.
   *
   * The specified login must exactly match a stored login. However, the
   * values of any nsILoginMetaInfo properties are ignored.
   */
  Promise removeLoginAsync(in nsILoginInfo aLogin);

  /**
   *Like modifyLogin, but asynchronous.
   *
   * Modify an existing login in the login manager.
   *
   * @param oldLogin
   *        The login to be modified.
   * @param newLoginData
   *        The new login values (either a nsILoginInfo or nsIProperyBag)
   *
   * If newLoginData is a nsILoginInfo, all of the old login's nsILoginInfo
   * properties are changed to the values from newLoginData (but the old
   * login's nsILoginMetaInfo properties are unmodified).
   *
   * If newLoginData is a nsIPropertyBag, only the specified properties
   * will be changed. The nsILoginMetaInfo properties of oldLogin can be
   * changed in this manner.
   *
   * If the propertybag contains an item named "timesUsedIncrement", the
   * login's timesUsed property will be incremented by the item's value.
   */
  Promise modifyLoginAsync(in nsILoginInfo oldLogin, in nsISupports newLoginData);

    /**
   * Record that the password of a saved login was used (e.g. submitted or copied).
   *
   * @param {nsILoginInfo} aLogin
   *        The login record of the password that was used.
   * @param {boolean} aPrivateContextWithoutExplicitConsent
   *        If the use was in private browsing AND without the user explicitly choosing to save/update.
   *        Login use metadata will not be updated in this case but it will stil be counted for telemetry.
   * @param {AString} aLoginType
   *        One of "form_login", "form_password", "auth_login", or "prompt_login".
   *        See saved_login_used in Events.yaml.
   *        Don't assume that an auth. login is never used in a form and vice-versa. This argument
   *        indicates the context of how it was used.
   * @param {boolean} aFilled
   *        Whether the login was filled, rather than being typed manually.
   *
   * If only the username was used, this method shouldn't be called as we don't
   * want to double-count the use if both the username and password are copied.
   * Copying of the username normally precedes the copying of the password anyways.
   */
  Promise recordPasswordUseAsync(in nsILoginInfo aLogin, in boolean aPrivateContextWithoutExplicitConsent, in AString aLoginType, in boolean aFilled);


  /**
   * Remove all stored user facing logins.
   *
   * This will remove all the logins that a user can access through about:logins.
   * This will not remove the FxA Sync key which is stored with the rest of a user's logins
   * but is not accessible through about:logins
   *
   * The browser sanitization feature allows the user to clear any stored
   * passwords. This interface allows that to be done without getting each
   * login first.
   *
   */
  Promise removeAllUserFacingLoginsAsync();

  /**
   * Completely remove all logins, including the user's FxA Sync key.
   *
   */
  Promise removeAllLoginsAsync();

  /**
   * Fetch all logins in the login manager. An array is always returned;
   * if there are no logins the array is empty. Decryption is handled in
   * one batch.
   *
   * @return A promise which resolves with a JS Array of nsILoginInfo objects.
   */
  Promise getAllLogins();

  /**
   * Like getAllLogins, but with a callback returning the search results.
   *
   * @param {nsILoginSearchCallback} aCallback
   *        The interface to notify when the search is complete.
   *
   */
  void getAllLoginsWithCallback(in nsILoginSearchCallback aCallback);

  /**
   * For migration purposes, asynchronously reencrypt all logins in the
   * background. If a login is updated externally during that reencryption, that
   * update will take priority and will not be overwritten.
   */
  Promise reencryptAllLogins();

  /**
   * Debug helper to identify logins with invalid origin/formActionOrigin URLs.
   * Used to diagnose login storage incompatibilities with the Application Services
   * Rust component, which has stricter URL validation requirements.
   *
   * @return A promise which resolves with a JS Array of objects containing
   *         origin, timeCreated, and timeLastUsed for logins that failed
   *         URL validation.
   */
  Promise listInvalidOrigins();

  /**
   * Obtain a list of all origins for which password saving is disabled.
   *
   * @return An array of origin strings. For example: ["https://www.site.com"].
   */
  Array<AString> getAllDisabledHosts();

  /**
   * Check to see if saving logins has been disabled for an origin.
   *
   * @param aHost
   *        The origin to check. For example: "http://foo.com".
   */
  boolean getLoginSavingEnabled(in AString aHost);

  /**
   * Disable (or enable) storing logins for the specified origin. When
   * disabled, the login manager will not prompt to store logins for
   * that origin. Existing logins are not affected.
   *
   * @param aHost
   *        The origin to set. For example: "http://foo.com".
   * @param isEnabled
   *        Specify if saving logins should be enabled (true) or
   *        disabled (false)
   */
  void setLoginSavingEnabled(in AString aHost, in boolean isEnabled);

  /**
   * Search for logins matching the specified criteria. Called when looking
   * for logins that might be applicable to a form or authentication request.
   *
   * @deprecated Removed: now throws NS_ERROR_NOT_IMPLEMENTED. Use
   * `searchLoginsAsync` instead. The throwing stub is retained so that
   * Thunderbird gets a clear error pointing to the replacement.
   *
   * @param aOrigin
   *        The origin to restrict searches to. For example: "http://www.site.com".
   *        To find logins for a given nsIURI, you would typically pass in
   *        its prePath (excluding userPass).
   * @param aActionOrigin
   *        For form logins, this argument should be the origin to which the
   *        form will be submitted, not the whole URL.
   *        For HTTP auth. logins, specify null.
   *        An empty string ("") will match any value (except null).
   * @param aHttpRealm
   *        For HTTP auth. logins, this argument should be the HTTP Realm
   *        for which the login applies. This is obtained from the
   *        WWW-Authenticate header. See RFC2617. For form logins,
   *        specify null.
   *        An empty string ("") will match any value (except null).
   * @return An array of nsILoginInfo objects.
   */
  Array<nsILoginInfo> findLogins(in AString aOrigin, in AString aActionOrigin,
                                 in AString aHttpRealm);

  /**
   * Search for logins matching the specified criteria, as with
   * findLogins(). This interface only returns the number of matching
   * logins (and not the logins themselves), which allows a caller to
   * check for logins without causing the user to be prompted for a primary
   * password to decrypt the logins.
   *
   * @param aOrigin
   *        The origin to restrict searches to. Specify an empty string
   *        to match all origins. A null value will not match any logins, and
   *        will thus always return a count of 0.
   * @param aActionOrigin
   *        The origin to which a form login will be submitted. To match any
   *        form login, specify an empty string. To not match any form
   *        login, specify null.
   * @param aHttpRealm
   *        The HTTP Realm for which the login applies. To match logins for
   *        any realm, specify an empty string. To not match logins for any
   *        realm, specify null.
   */
  Promise countLoginsAsync(in AString aOrigin, in AString aActionOrigin,
                            in AString aHttpRealm);

  /**
   * Asynchonously search for logins in the login manager. The Promise always
   * resolves to an array; if there are no logins the array is empty.
   *
   * @param {object} matchData
   *        The data used to search as a JS object. This does not follow the same
   *        requirements as findLogins for those fields. Wildcard matches are
   *        simply not specified. If a `guid` is specified then no other properties
   *        are used (outside of GeckoView).
   * @return A promise resolving to an array of nsILoginInfo objects.
   */
  Promise searchLoginsAsync(in jsval matchData);

  /**
   * Returns the "sync id" used by Sync to know whether the store is current with
   * respect to the sync servers.
   *
   * Returns null if the data doesn't exist or if the data can't be
   * decrypted (including if the primary-password prompt is cancelled). This is
   * OK for Sync as it can't even begin syncing if the primary-password is
   * locked as the sync encrytion keys are stored in this login manager.
   */
  Promise getSyncID();

  /**
   * Sets the "sync id" used by Sync to know whether the store is current with
   * respect to the sync servers. May be set to null.
   *
   * Throws if the data can't be encrypted (including if the primary-password
   * prompt is cancelled)
   */
  Promise setSyncID(in AString syncID);

  /**
   * Returns the timestamp of the last sync as a double (in seconds since Epoch
   * rounded to two decimal places), or 0.0 if the data doesn't exist.
   */
  Promise getLastSync();

  /**
   * Sets the timestamp of the last sync.
   */
  Promise setLastSync(in double timestamp);

  /**
   * Ensures that the local sync ID for the engine matches the sync ID for
   * the collection on the server. If they don't match, then we set
    * the local sync ID to newSyncID and reset the last sync timestamp.
   */
  Promise ensureCurrentSyncID(in AString newSyncID);

  /**
   * Mark a login's password as potentially vulnerable (breached).
   */
  Promise addPotentiallyVulnerablePassword(in nsILoginInfo aLogin);

  /**
   * Check if a login's password is potentially vulnerable.
   */
  Promise isPotentiallyVulnerablePassword(in nsILoginInfo aLogin);

  /**
   * Record that a breach alert for a login was dismissed by the user.
   */
  Promise recordBreachAlertDismissal(in AString aLoginGUID);

  /**
   * Get all breach alert dismissals keyed by login GUID.
   */
  Promise getBreachAlertDismissalsByLoginGUID();

  /**
   * Check which of the given logins have potentially vulnerable passwords.
   * Returns a promise resolving to an array of GUIDs of vulnerable logins.
   */
  Promise arePotentiallyVulnerablePasswords(in jsval aLogins);

  /**
   * Clear all potentially vulnerable password records.
   */
  Promise clearAllPotentiallyVulnerablePasswords();

 /**
  * True when a primary password prompt is being displayed.
  */
  readonly attribute boolean uiBusy;

 /**
  * True when the primary password has already been entered, and so a caller
  * can ask for decrypted logins without triggering a prompt.
  */
  readonly attribute boolean isLoggedIn;
};

%{C++

#define NS_LOGINMANAGER_CONTRACTID "@mozilla.org/login-manager;1"

%}
