/* 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 nsIURI;
interface nsIInputStream;

[scriptable, uuid(5799251f-5b55-4df7-a9e7-0c27812c469a)]
interface nsISearchSubmission : nsISupports
{
  /**
   * The POST data associated with a search submission, wrapped in a MIME
   * input stream. May be null.
   */
  readonly attribute nsIInputStream postData;

  /**
   * The URI to submit a search to.
   */
  readonly attribute nsIURI uri;
};

[scriptable, uuid(65fd517b-6bda-4bac-bbe1-42de1b3a7df6)]
interface nsISearchEngine : nsISupports
{
  /**
   * Gets a nsISearchSubmission object that contains information about what to
   * send to the search engine, including the URI and postData, if applicable.
   *
   * @param  data
   *         Data to add to the submission object.
   *         i.e. the search terms.
   *
   * @param  responseType [optional]
   *         The MIME type that we'd like to receive in response
   *         to this submission.  If null, will default to "text/html".
   *
   * @param purpose [optional]
   *        A string meant to indicate the context of the search request. This
   *        allows the search service to provide a different nsISearchSubmission
   *        depending on e.g. where the search is triggered in the UI.
   *
   * @returns A nsISearchSubmission object that contains information about what
   *          to send to the search engine.  If no submission can be
   *          obtained for the given responseType, returns null.
   */
  nsISearchSubmission getSubmission(in AString data,
                                    [optional] in AString responseType,
                                    [optional] in AString purpose);

  /**
   * Adds a parameter to the search engine's submission data. This should only
   * be called on engines created via addEngineWithDetails.
   *
   * @param name
   *        The parameter's name. Must not be null.
   *
   * @param value
   *        The value to pass. If value is "{searchTerms}", it will be
   *        substituted with the user-entered data when retrieving the
   *        submission. Must not be null.
   *
   * @param responseType
   *        Since an engine can have several different request URLs,
   *        differentiated by response types, this parameter selects
   *        a request to add parameters to.  If null, will default
   *        to "text/html"
   *
   * @throws NS_ERROR_FAILURE if the search engine is read-only.
   * @throws NS_ERROR_INVALID_ARG if name or value are null.
   */
  void addParam(in AString name, in AString value, in AString responseType);

  /**
   * Determines whether the engine can return responses in the given
   * MIME type.  Returns true if the engine spec has a URL with the
   * given responseType, false otherwise.
   *
   * @param responseType
   *        The MIME type to check for
   */
  boolean supportsResponseType(in AString responseType);

  /**
   * Returns a string with the URL to an engine's icon matching both width and
   * height. Returns null if icon with specified dimensions is not found.
   *
   * @param width
   *        Width of the requested icon.
   * @param height
   *        Height of the requested icon.
   */
  AString getIconURLBySize(in long width, in long height);

  /**
   * Gets an array of all available icons. Each entry is an object with
   * width, height and url properties. width and height are numeric and
   * represent the icon's dimensions. url is a string with the URL for
   * the icon.
   */
  jsval getIcons();

  /**
   * Opens a speculative connection to the engine's search URI
   * (and suggest URI, if different) to reduce request latency
   *
   * @param  options
   *         An object that must contain the following fields:
   *         {window} the content window for the window performing the search
   *
   * @throws NS_ERROR_INVALID_ARG if options is omitted or lacks required
   *         elemeents
   */
  void speculativeConnect(in jsval options);

  /**
   * Supported search engine types.
   */
  const unsigned long TYPE_MOZSEARCH     = 1;
  const unsigned long TYPE_SHERLOCK      = 2;
  const unsigned long TYPE_OPENSEARCH    = 3;

  /**
   * Supported search engine data types.
   */
  const unsigned long DATA_XML     = 1;
  const unsigned long DATA_TEXT    = 2;

  /**
   * An optional shortcut alias for the engine.
   * When non-null, this is a unique identifier.
   */
  attribute AString alias;

  /**
   * A text description describing the engine.
   */
  readonly attribute AString description;

  /**
   * Whether the engine should be hidden from the user.
   */
  attribute boolean hidden;

  /**
   * A nsIURI corresponding to the engine's icon, stored locally. May be null.
   */
  readonly attribute nsIURI iconURI;

  /**
   * The display name of the search engine. This is a unique identifier.
   */
  readonly attribute AString name;

  /**
   * A URL string pointing to the engine's search form.
   */
  readonly attribute AString searchForm;

  /**
   * The search engine type.
   */
  readonly attribute long type;

  /**
   * An optional unique identifier for this search engine within the context of
   * the distribution, as provided by the distributing entity.
   */
  readonly attribute AString identifier;

  /**
   * Gets a string representing the hostname from which search results for a
   * given responseType are returned, minus the leading "www." (if present).
   * This can be specified as an url attribute in the engine description file,
   * but will default to host from the <Url>'s template otherwise.
   *
   * @param  responseType [optional]
   *         The MIME type to get resultDomain for.  Defaults to "text/html".
   *
   * @return the resultDomain for the given responseType.
   */
  AString getResultDomain([optional] in AString responseType);
};

[scriptable, uuid(0dc93e51-a7bf-4a16-862d-4b3469ff6206)]
interface nsISearchParseSubmissionResult : nsISupports
{
  /**
   * The search engine associated with the URL passed in to
   * nsISearchEngine::parseSubmissionURL, or null if the URL does not represent
   * a search submission.
   */
  readonly attribute nsISearchEngine engine;

  /**
   * String containing the sought terms.  This can be an empty string in case no
   * terms were specified or the URL does not represent a search submission.
   */
  readonly attribute AString terms;

  /**
   * The offset of the string |terms| in the URL passed in to
   * nsISearchEngine::parseSubmissionURL, or -1 if the URL does not represent
   * a search submission.
   */
  readonly attribute long termsOffset;

  /**
   * The length of the |terms| in the original encoding of the URL passed in to
   * nsISearchEngine::parseSubmissionURL. If the search term in the original
   * URL is encoded then this will be bigger than |terms.length|.
   */
  readonly attribute long termsLength;
};

[scriptable, uuid(9fc39136-f08b-46d3-b232-96f4b7b0e235)]
interface nsISearchInstallCallback : nsISupports
{
  const unsigned long ERROR_UNKNOWN_FAILURE = 0x1;
  const unsigned long ERROR_DUPLICATE_ENGINE = 0x2;

  /**
   * Called to indicate that the engine addition process succeeded.
   *
   * @param engine
   *        The nsISearchEngine object that was added (will not be null).
   */
  void onSuccess(in nsISearchEngine engine);

  /**
   * Called to indicate that the engine addition process failed.
   *
   * @param errorCode
   *        One of the ERROR_* values described above indicating the cause of
   *        the failure.
   */
  void onError(in unsigned long errorCode);
};

/**
 * Callback for asynchronous initialization of nsIBrowserSearchService
 */
[scriptable, function, uuid(02256156-16e4-47f1-9979-76ff98ceb590)]
interface nsIBrowserSearchInitObserver : nsISupports
{
  /**
   * Called once initialization of the browser search service is complete.
   *
   * @param aStatus The status of that service.
   */
  void onInitComplete(in nsresult aStatus);
};

[scriptable, uuid(150ef720-bbe2-4169-b9f3-ef7ec0654ced)]
interface nsIBrowserSearchService : nsISupports
{
  /**
   * Start asynchronous initialization.
   *
   * The callback is triggered once initialization is complete, which may be
   * immediately, if initialization has already been completed by some previous
   * call to this method. The callback is always invoked asynchronously.
   *
   * @param aObserver An optional object observing the end of initialization.
   */
  void init([optional] in nsIBrowserSearchInitObserver aObserver);

  /**
   * Determine whether initialization has been completed.
   *
   * Clients of the service can use this attribute to quickly determine whether
   * initialization is complete, and decide to trigger some immediate treatment,
   * to launch asynchronous initialization or to bailout.
   *
   * Note that this attribute does not indicate that initialization has succeeded.
   *
   * @return |true| if the search service is now initialized, |false| if
   * initialization has not been triggered yet.
   */
  readonly attribute bool isInitialized;

  /**
   * Resets the default engine to its original value.
   */
  void resetToOriginalDefaultEngine();

  /**
   * Adds a new search engine from the file at the supplied URI, optionally
   * asking the user for confirmation first.  If a confirmation dialog is
   * shown, it will offer the option to begin using the newly added engine
   * right away.
   *
   * @param engineURL
   *        The URL to the search engine's description file.
   *
   * @param dataType
   *        An integer representing the plugin file format. Must be one
   *        of the supported search engine data types defined above.
   *
   * @param iconURL
   *        A URL string to an icon file to be used as the search engine's
   *        icon. This value may be overridden by an icon specified in the
   *        engine description file.
   *
   * @param confirm
   *        A boolean value indicating whether the user should be asked for
   *        confirmation before this engine is added to the list.  If this
   *        value is false, the engine will be added to the list upon successful
   *        load, but it will not be selected as the current engine.
   *
   * @param callback
   *        A nsISearchInstallCallback that will be notified when the
   *        addition is complete, or if the addition fails. It will not be
   *        called if addEngine throws an exception.
   *
   * @throws NS_ERROR_FAILURE if the type is invalid, or if the description
   *         file cannot be successfully loaded.
   */
  void addEngine(in AString engineURL, in long dataType, in AString iconURL,
                 in boolean confirm, [optional] in nsISearchInstallCallback callback);

  /**
   * Adds a new search engine, without asking the user for confirmation and
   * without starting to use it right away.
   *
   * @param name
   *        The search engine's name. Must be unique. Must not be null.
   *
   * @param iconURL
   *        Optional: A URL string pointing to the icon to be used to represent
   *        the engine.
   *
   * @param alias
   *        Optional: A unique shortcut that can be used to retrieve the
   *        search engine.
   *
   * @param description
   *        Optional: a description of the search engine.
   *
   * @param method
   *        The HTTP request method used when submitting a search query.
   *        Must be a case insensitive value of either "get" or "post".
   *
   * @param url
   *        The URL to which search queries should be sent.
   *        Must not be null.
   *
   * @param extensionID [optional]
   *        Optional: The correct extensionID if called by an add-on.
   */
  void addEngineWithDetails(in AString name,
                            in AString iconURL,
                            in AString alias,
                            in AString description,
                            in AString method,
                            in AString url,
                            [optional] in AString extensionID);

  /**
   * Un-hides all engines installed in the directory corresponding to
   * the directory service's NS_APP_SEARCH_DIR key. (i.e. the set of
   * engines returned by getDefaultEngines)
   */
  void restoreDefaultEngines();

  /**
   * Returns an engine with the specified alias.
   *
   * @param   alias
   *          The search engine's alias.
   * @returns The corresponding nsISearchEngine object, or null if it doesn't
   *          exist.
   */
  nsISearchEngine getEngineByAlias(in AString alias);

  /**
   * Returns an engine with the specified name.
   *
   * @param   aEngineName
   *          The name of the engine.
   * @returns The corresponding nsISearchEngine object, or null if it doesn't
   *          exist.
   */
  nsISearchEngine getEngineByName(in AString aEngineName);

  /**
   * Returns an array of all installed search engines.
   *
   * @returns an array of nsISearchEngine objects.
   */
  void getEngines(
            [optional] out unsigned long engineCount,
            [retval, array, size_is(engineCount)] out nsISearchEngine engines);

  /**
   * Returns an array of all installed search engines whose hidden attribute is
   * false.
   *
   * @returns an array of nsISearchEngine objects.
   */
  void getVisibleEngines(
            [optional] out unsigned long engineCount,
            [retval, array, size_is(engineCount)] out nsISearchEngine engines);

  /**
   * Returns an array of all default search engines. This includes all loaded
   * engines that aren't in the user's profile directory
   * (NS_APP_USER_SEARCH_DIR).
   *
   * @returns an array of nsISearchEngine objects.
   */
  void getDefaultEngines(
            [optional] out unsigned long engineCount,
            [retval, array, size_is(engineCount)] out nsISearchEngine engines);

  /**
   * Moves a visible search engine.
   *
   * @param  engine
   *         The engine to move.
   * @param  newIndex
   *         The engine's new index in the set of visible engines.
   *
   * @throws NS_ERROR_FAILURE if newIndex is out of bounds, or if engine is
   *         hidden.
   */
  void moveEngine(in nsISearchEngine engine, in long newIndex);

  /**
   * Removes the search engine. If the search engine is installed in a global
   * location, this will just hide the engine. If the engine is in the user's
   * profile directory, it will be removed from disk.
   *
   * @param  engine
   *         The engine to remove.
   */
  void removeEngine(in nsISearchEngine engine);

  /**
   * The default search engine. Returns the first visible engine if the default
   * engine is hidden. May be null if there are no visible search engines.
   */
  attribute nsISearchEngine defaultEngine;

  /**
   * The currently active search engine. May be null if there are no visible
   * search engines.
   */
  attribute nsISearchEngine currentEngine;

  /**
   * Gets a representation of the default engine in an anonymized JSON
   * string suitable for recording in the Telemetry environment.
   *
   * @return an object containing anonymized info about the default engine:
   *         name, loadPath, submissionURL (for default engines).
   */
  jsval getDefaultEngineInfo();

  /**
   * Determines if the provided URL represents results from a search engine, and
   * provides details about the match.
   *
   * The lookup mechanism checks whether the domain name and path of the
   * provided HTTP or HTTPS URL matches one of the known values for the visible
   * search engines.  The match does not depend on which of the schemes is used.
   * The expected URI parameter for the search terms must exist in the query
   * string, but other parameters are ignored.
   *
   * @param url
   *        String containing the URL to parse, for example
   *        "https://www.google.com/search?q=terms".
   */
  nsISearchParseSubmissionResult parseSubmissionURL(in AString url);
};

%{ C++
/**
 * The observer topic to listen to for actions performed on installed
 * search engines.
 */
#define SEARCH_ENGINE_TOPIC "browser-search-engine-modified"

/**
 * Sent when an engine is removed from the data store.
 */
#define SEARCH_ENGINE_REMOVED      "engine-removed"

/**
 * Sent when an engine is changed. This includes when the engine's "hidden"
 * property is changed.
 */
#define SEARCH_ENGINE_CHANGED      "engine-changed"

/**
 * Sent when an engine is added to the list of available engines.
 */
#define SEARCH_ENGINE_ADDED        "engine-added"

/**
 * Sent when a search engine being installed from a remote plugin description
 * file is completely loaded. This is used internally by the search service as
 * an indication of when the engine can be added to the internal store, and
 * therefore should not be used to detect engine availability. It is always
 * followed by an "added" notification.
 */
#define SEARCH_ENGINE_LOADED       "engine-loaded"

/**
 * Sent when the "current" engine is changed.
 */
#define SEARCH_ENGINE_CURRENT      "engine-current";

/**
 * Sent when the "default" engine is changed.
 */
#define SEARCH_ENGINE_DEFAULT      "engine-default";



%}
