/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsIDOMEventTarget.idl"

interface nsIChannel;
interface nsIDOMDocument;
interface nsIDOMEventListener;
interface nsILoadGroup;
interface nsIPrincipal;
interface nsIScriptContext;
interface nsIURI;
interface nsIVariant;
interface nsIGlobalObject;
interface nsIInputStream;
interface nsIDOMBlob;

[builtinclass, uuid(88e7d2a0-2e5b-4f65-9624-a61e607a9948)]
interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
  // event handler attributes
};

[builtinclass, uuid(d74c4dc4-bc8c-4f5d-b7f1-121a48750abe)]
interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
  // for future use
};

/**
 * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest
 * object. The goal has been to make Mozilla's version match Microsoft's
 * version as closely as possible, but there are bound to be some differences.
 *
 * In general, Microsoft's documentation for IXMLHttpRequest can be used.
 * Mozilla's interface definitions provide some additional documentation. The
 * web page to look at is http://www.mozilla.org/xmlextras/
 *
 * Mozilla's XMLHttpRequest object can be created in JavaScript like this:
 *   new XMLHttpRequest()
 * compare to Internet Explorer:
 *   new ActiveXObject("Msxml2.XMLHTTP")
 *
 * From JavaScript, the methods and properties visible in the XMLHttpRequest
 * object are a combination of nsIXMLHttpRequest and nsIJSXMLHttpRequest;
 * there is no need to differentiate between those interfaces.
 *
 * From native code, the way to set up onload and onerror handlers is a bit
 * different. Here is a comment from Johnny Stenback <jst@netscape.com>:
 *
 *   The mozilla implementation of nsIXMLHttpRequest implements the interface
 *   nsIDOMEventTarget and that's how you're supported to add event listeners.
 *   Try something like this:
 *
 *   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(myxmlhttpreq));
 *
 *   target->AddEventListener(NS_LITERAL_STRING("load"), mylistener,
 *                            PR_FALSE)
 *
 *   where mylistener is your event listener object that implements the
 *   interface nsIDOMEventListener.
 *
 *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
 *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
 *   those.
 *
 * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
 * you're aware of all the security implications.  And then think twice about
 * it.
 */
[scriptable, uuid(6f54214c-7175-498d-9d2d-0429e38c2869)]
interface nsIXMLHttpRequest : nsISupports
{
  /**
   * The request uses a channel in order to perform the
   * request.  This attribute represents the channel used
   * for the request.  NULL if the channel has not yet been
   * created.
   *
   * Mozilla only. Requires elevated privileges to access.
   */
  readonly attribute nsIChannel channel;

  /**
   * The response to the request is parsed as if it were a
   * text/xml stream. This attributes represents the response as
   * a DOM Document object. NULL if the request is unsuccessful or
   * has not yet been sent.
   */
  readonly attribute nsIDOMDocument responseXML;

  /**
   * The response to the request as text.
   * NULL if the request is unsuccessful or
   * has not yet been sent.
   */
  readonly attribute AString responseText;

  /**
   * Determine a response format which response attribute returns.
   * empty string (initial value) or "text": as text.
   * "arraybuffer": as a typed array ArrayBuffer.
   * "blob": as a File API Blob.
   * "document": as a DOM Document object.
   */
  attribute AString responseType;

  /**
   * The response to the request as a specified format by responseType.
   * NULL if the request is unsuccessful or
   * has not yet been sent.
   */
  [implicit_jscontext] readonly attribute jsval /* any */ response;

  /**
   * The status of the response to the request for HTTP requests.
   */
  // XXX spec says unsigned short
  readonly attribute unsigned long status;

  /**
   * The string representing the status of the response for
   * HTTP requests.
   */
  readonly attribute ACString statusText;

  /**
   * If the request has been sent already, this method will
   * abort the request.
   */
  [binaryname(SlowAbort)] void abort();

  /**
   * Returns all of the response headers as a string for HTTP
   * requests.
   *
   * @returns A string containing all of the response headers.
   *          The empty string if the response has not yet been received.
   */
  ACString getAllResponseHeaders();

  /**
   * Returns the text of the header with the specified name for
   * HTTP requests.
   *
   * @param header The name of the header to retrieve
   * @returns A string containing the text of the header specified.
   *          NULL if the response has not yet been received or the
   *          header does not exist in the response.
   */
  ACString getResponseHeader(in ACString header);

%{C++
  // note this is NOT virtual so this won't muck with the vtable!
  inline nsresult Open(const nsACString& method, const nsACString& url,
                       bool async, const nsAString& user,
                       const nsAString& password) {
    return Open(method, url, async, user, password, 3);
  }
%}
  /**
   * Meant to be a script-only method for initializing a request.
   *
   * If there is an "active" request (that is, if open() has been called
   * already), this is equivalent to calling abort() and then open().
   *
   * @param method The HTTP method - either "POST" or "GET". Ignored
   *               if the URL is not a HTTP URL.
   * @param url The URL to which to send the request.
   * @param async (optional) Whether the request is synchronous or
   *              asynchronous i.e. whether send returns only after
   *              the response is received or if it returns immediately after
   *              sending the request. In the latter case, notification
   *              of completion is sent through the event listeners.
   *              The default value is true.
   * @param user (optional) A username for authentication if necessary.
   *             The default value is the empty string
   * @param password (optional) A password for authentication if necessary.
   *                 The default value is the empty string
   */
  [optional_argc] void open(in ACString method, in AUTF8String url,
                            [optional] in boolean async,
                            [optional,Undefined(Empty)] in DOMString user,
                            [optional,Undefined(Empty)] in DOMString password);

  /**
   * Sends the request. If the request is asynchronous, returns
   * immediately after sending the request. If it is synchronous
   * returns only after the response has been received.
   *
   * All event listeners must be set before calling send().
   *
   * After the initial response, all event listeners will be cleared.
   * // XXXbz what does that mean, exactly?   
   *
   * @param body Either an instance of nsIDOMDocument, nsIInputStream
   *             or a string (nsISupportsString in the native calling
   *             case). This is used to populate the body of the
   *             HTTP request if the HTTP request method is "POST".
   *             If the parameter is a nsIDOMDocument, it is serialized.
   *             If the parameter is a nsIInputStream, then it must be
   *             compatible with nsIUploadChannel.setUploadStream, and a
   *             Content-Length header will be added to the HTTP request
   *             with a value given by nsIInputStream.available.  Any
   *             headers included at the top of the stream will be
   *             treated as part of the message body.  The MIME type of
   *             the stream should be specified by setting the Content-
   *             Type header via the setRequestHeader method before
   *             calling send.
   */
  void   send([optional] in nsIVariant body);

  /**
   * Sets a HTTP request header for HTTP requests. You must call open
   * before setting the request headers.
   *
   * @param header The name of the header to set in the request.
   * @param value The body of the header.
   */
  void   setRequestHeader(in ACString header, in ACString value);

  /**
   * The amount of milliseconds a request can take before being terminated.
   * Initially zero. Zero means there is no timeout.
   */
  attribute unsigned long timeout;

  /**
   * The state of the request.
   *
   * Possible values:
   *   0 UNSENT   open() has not been called yet.
   *   1 OPENED   send() has not been called yet.
   *   2 HEADERS_RECEIVED
   *              send() has been called, headers and status are available.
   *   3 LOADING  Downloading, responseText holds the partial data.
   *   4 DONE     Finished with all operations.
   */
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  /**
   * Override the mime type returned by the server (if any). This may
   * be used, for example, to force a stream to be treated and parsed
   * as text/xml, even if the server does not report it as such. This
   * must be done before the <code>send</code> method is invoked.
   *
   * @param mimetype The type used to override that returned by the server
   *                 (if any).
   */
  [binaryname(SlowOverrideMimeType)] void overrideMimeType(in DOMString mimetype);

  /**
   * Set to true if this is a background service request. This will
   * prevent a load group being associated with the request, and
   * suppress any security dialogs from being shown * to the user.
   * In the cases where one of those dialogs would be shown, the request
   * will simply fail instead.
   */
  attribute boolean mozBackgroundRequest;

  /**
   * When set to true attempts to make cross-site Access-Control requests
   * with credentials such as cookies and authorization headers.
   *
   * Never affects same-site requests.
   *
   * Defaults to false.
   */
  attribute boolean withCredentials;

  /**
   * Initialize the object for use from C++ code with the principal, script
   * context, and owner window that should be used.
   *
   * @param principal The principal to use for the request. This must not be
   *                  null.
   * @param scriptContext The script context to use for the request. May be
   *                      null.
   * @param globalObject The associated global for the request. Can be the
   *                     outer window, a sandbox, or a backstage pass.
   *                     May be null, but then the request cannot create a
   *                     document.
   * @param baseURI The base URI to use when resolving relative URIs. May be
   *                null.
   * @param loadGroup An optional load group to use when performing the request.
   *                  This will be used even if the global has a window with a
   *                  load group.
   */
  [noscript] void init(in nsIPrincipal principal,
                       in nsIScriptContext scriptContext,
                       in nsIGlobalObject globalObject,
                       in nsIURI baseURI,
                       [optional] in nsILoadGroup loadGroup);

  /**
   * Upload process can be tracked by adding event listener to |upload|.
   */
  readonly attribute nsIXMLHttpRequestUpload upload;

  /**
   * Meant to be a script-only mechanism for setting a callback function.
   * The attribute is expected to be JavaScript function object. When the
   * readyState changes, the callback function will be called.
   * This attribute should not be used from native code!!
   *
   * After the initial response, all event listeners will be cleared.
   * // XXXbz what does that mean, exactly?   
   *
   * Call open() before setting an onreadystatechange listener.
   */
  [implicit_jscontext] attribute jsval onreadystatechange;

  /**
   * If true, the request will be sent without cookie and authentication
   * headers.
   */
  readonly attribute boolean mozAnon;

  /**
   * If true, the same origin policy will not be enforced on the request.
   */
  readonly attribute boolean mozSystem;
};

[uuid(840d0d00-e83e-4a29-b3c7-67e96e90a499)]
interface nsIXHRSendable : nsISupports {
  void getSendInfo(out nsIInputStream body,
                   out uint64_t contentLength,
                   out ACString contentType,
                   out ACString charset);
};

/**
 * @deprecated
 */
[scriptable, uuid(8ae70a39-edf1-40b4-a992-472d23421c25)]
interface nsIJSXMLHttpRequest : nsISupports {
};

%{ C++
#define NS_XMLHTTPREQUEST_CID                       \
 { /* d164e770-4157-11d4-9a42-000064657374 */       \
  0xd164e770, 0x4157, 0x11d4,                       \
 {0x9a, 0x42, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
#define NS_XMLHTTPREQUEST_CONTRACTID \
"@mozilla.org/xmlextras/xmlhttprequest;1"
%}
