/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 nsIDOMWindow;
interface nsIDOMNode;
interface nsIDOMDocument;
interface nsIOfflineCacheUpdate;
interface nsIPrincipal;
interface nsIPrefBranch;
interface nsIApplicationCache;
interface nsIFile;
interface nsIObserver;

[scriptable, uuid(47360d57-8ef4-4a5d-8865-1a27a739ad1a)]
interface nsIOfflineCacheUpdateObserver : nsISupports {
  const unsigned long STATE_ERROR = 1;
  const unsigned long STATE_CHECKING = 2;
  const unsigned long STATE_NOUPDATE = 3;
  const unsigned long STATE_OBSOLETE = 4;
  const unsigned long STATE_DOWNLOADING = 5;
  const unsigned long STATE_ITEMSTARTED = 6;
  const unsigned long STATE_ITEMCOMPLETED = 7;
  const unsigned long STATE_ITEMPROGRESS = 8;
  const unsigned long STATE_FINISHED = 10;

  /**
   * aUpdate has changed its state.
   *
   * @param aUpdate
   *        The nsIOfflineCacheUpdate being processed.
   * @param event
   *        See enumeration above
   */
  void updateStateChanged(in nsIOfflineCacheUpdate aUpdate, in uint32_t state);

  /**
   * Informs the observer about an application being available to associate.
   *
   * @param applicationCache
   *        The application cache instance that has been created or found by the 
   *        update to associate with
   */
  void applicationCacheAvailable(in nsIApplicationCache applicationCache);
};

/**
 * An nsIOfflineCacheUpdate is used to update an application's offline
 * resources.
 *
 * It can be used to perform partial or complete updates.
 *
 * One update object will be updating at a time.  The active object will
 * load its items one by one, sending itemCompleted() to any registered
 * observers.
 */
[scriptable, uuid(a4503a53-6ab8-4b50-b01e-1c4f393fc980)]
interface nsIOfflineCacheUpdate : nsISupports {
  /**
   * Fetch the status of the running update.  This will return a value
   * defined in nsIDOMOfflineResourceList.
   */
  readonly attribute unsigned short status;

  /**
   * TRUE if the update is being used to add specific resources.
   * FALSE if the complete cache update process is happening.
   */
  readonly attribute boolean partial;

  /**
   * TRUE if this is an upgrade attempt, FALSE if it is a new cache
   * attempt.
   */
  readonly attribute boolean isUpgrade;

  /**
   * The domain being updated, and the domain that will own any URIs added
   * with this update.
   */
  readonly attribute ACString updateDomain;

  /**
   * The manifest for the offline application being updated.
   */
  readonly attribute nsIURI manifestURI;

  /**
   * TRUE if the cache update completed successfully.
   */
  readonly attribute boolean succeeded;

  /**
   * Initialize the update.
   *
   * @param aManifestURI
   *        The manifest URI to be checked.
   * @param aDocumentURI
   *        The page that is requesting the update.
   */
  void init(in nsIURI aManifestURI, in nsIURI aDocumentURI, in nsIDOMDocument aDocument,
            [optional] in nsIFile aCustomProfileDir,
            [optional] in unsigned long aAppId,
            [optional] in boolean aInBrowser);

  /**
   * Initialize the update for partial processing. 
   *
   * @param aManifestURI
   *        The manifest URI of the related cache.
   * @param aClientID
   *        Client  ID of the cache to store resource to. This ClientID
   *        must be ID of cache in the cache group identified by
   *        the manifest URI passed in the first parameter.
   * @param aDocumentURI
   *        The page that is requesting the update. May be null 
   *        when this information is unknown.
   */
  void initPartial(in nsIURI aManifestURI, in ACString aClientID, in nsIURI aDocumentURI);

  /**
   * Initialize the update to only check whether there is an update
   * to the manifest available (if it has actually changed on the server).
   *
   * @param aManifestURI
   *        The manifest URI of the related cache.
   * @param aAppID
   *        Local ID of an app (optional) to check the cache update for.
   * @param aInBrowser
   *        Whether to check for a cache populated from browser element.
   * @param aObserver
   *        nsIObserver implementation that receives the result.
   *        When aTopic == "offline-cache-update-available" there is an update to
   *        to download. Update of the app cache will lead to a new version
   *        download.
   *        When aTopic == "offline-cache-update-unavailable" then there is no
   *        update available (the manifest has not changed on the server).
   */
  void initForUpdateCheck(in nsIURI aManifestURI,
                          in unsigned long aAppID,
                          in boolean aInBrowser,
                          in nsIObserver aObserver);

  /**
   * Add a dynamic URI to the offline cache as part of the update.
   *
   * @param aURI
   *        The URI to add.
   */
  void addDynamicURI(in nsIURI aURI);

  /**
   * Add the update to the offline update queue.  An offline-cache-update-added
   * event will be sent to the observer service.
   */
  void schedule();

  /**
   * Observe loads that are added to the update.
   *
   * @param aObserver
   *        object that notifications will be sent to.
   * @param aHoldWeak
   *        TRUE if you want the update to hold a weak reference to the
   *        observer, FALSE for a strong reference.
   */
  void addObserver(in nsIOfflineCacheUpdateObserver aObserver,
                   in boolean aHoldWeak);

  /**
   * Remove an observer from the update.
   *
   * @param aObserver
   *        the observer to remove.
   */
  void removeObserver(in nsIOfflineCacheUpdateObserver aObserver);

  /**
   * Cancel the update when still in progress. This stops all running resource
   * downloads and discards the downloaded cache version. Throws when update
   * has already finished and made the new cache version active.
   */
  void cancel();

  /**
   * Return the number of bytes downloaded so far
   */
  readonly attribute uint64_t byteProgress;
};

[scriptable, uuid(6ee353ba-11ea-4008-a78a-55b343fb2a49)]
interface nsIOfflineCacheUpdateService : nsISupports {
    /**
     * Constants for the offline-app permission.
     *
     * XXX: This isn't a great place for this, but it's really the only
     * private offline-app-related interface
     */

    /**
     * Allow the domain to use offline APIs, and don't warn about excessive
     * usage.
     */
    const unsigned long ALLOW_NO_WARN = 3;

    /**
     * Access to the list of cache updates that have been scheduled.
     */
    readonly attribute unsigned long numUpdates;
    nsIOfflineCacheUpdate getUpdate(in unsigned long index);

    /**
     * Schedule a cache update for a given offline manifest.  If an
     * existing update is scheduled or running, that update will be returned.
     * Otherwise a new update will be scheduled.
     */
    nsIOfflineCacheUpdate scheduleUpdate(in nsIURI aManifestURI,
                                         in nsIURI aDocumentURI,
                                         in nsIDOMWindow aWindow);

    /**
     * Schedule a cache update for a given offline manifest and let the data
     * be stored to a custom profile directory.  There is no coalescing of
     * manifests by manifest URL.
     */
    nsIOfflineCacheUpdate scheduleCustomProfileUpdate(in nsIURI aManifestURI,
                                                      in nsIURI aDocumentURI,
                                                      in nsIFile aProfileDir);

    /**
     * Schedule a cache update for a given offline manifest using app cache
     * bound to the given appID+inBrowser flag.  If an existing update is
     * scheduled or running, that update will be returned. Otherwise a new
     * update will be scheduled.
     */
    nsIOfflineCacheUpdate scheduleAppUpdate(in nsIURI aManifestURI,
                                            in nsIURI aDocumentURI,
                                            in unsigned long aAppID,
                                            in boolean aInBrowser);

    /**
     * Schedule a cache update for a manifest when the document finishes
     * loading.
     */
    void scheduleOnDocumentStop(in nsIURI aManifestURI,
                                in nsIURI aDocumentURI,
                                in nsIDOMDocument aDocument);

    /**
     * Schedule a check to see if an update is available.
     *
     * This will not update or make any changes to the appcache.
     * It only notifies the observer to indicate whether the manifest has
     * changed on the server (or not): a changed manifest means that an
     * update is available.
     *
     * For arguments see nsIOfflineCacheUpdate.initForUpdateCheck() method
     * description.
     */
    void checkForUpdate(in nsIURI aManifestURI,
                        in unsigned long aAppID,
                        in boolean aInBrowser,
                        in nsIObserver aObserver);

    /**
     * Checks whether a principal should have access to the offline
     * cache.
     * @param aPrincipal
     *        The principal to check.
     * @param aPrefBranch
     *        The pref branch to use to check the
     *        offline-apps.allow_by_default pref.  If not specified,
     *        the pref service will be used.
     */
    boolean offlineAppAllowed(in nsIPrincipal aPrincipal,
                              in nsIPrefBranch aPrefBranch);

    /**
     * Checks whether a document at the given URI should have access
     * to the offline cache.
     * @param aURI
     *        The URI to check
     * @param aPrefBranch
     *        The pref branch to use to check the
     *        offline-apps.allow_by_default pref.  If not specified,
     *        the pref service will be used.
     */
    boolean offlineAppAllowedForURI(in nsIURI aURI,
                                    in nsIPrefBranch aPrefBranch);

    /**
     * Sets the "offline-app" permission for the principal.
     * In the single process model calls directly on permission manager.
     * In the multi process model dispatches to the parent process.
     */
    void allowOfflineApp(in nsIDOMWindow aWindow, in nsIPrincipal aPrincipal);
};
