/* -*- Mode: IDL; tab-width: 8; 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"

%{C++
#include "jspubtd.h"
%}

interface xpcIJSWeakReference;
interface nsIClassInfo;
interface nsIComponentManager;
interface nsIJSCID;
interface nsIJSIID;
interface nsIStackFrame;

/**
* interface of Components.interfacesByID
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(c99cffac-5aed-4267-ad2f-f4a4c9d4a081)]
interface nsIXPCComponents_InterfacesByID : nsISupports
{
};

/**
* interface of Components.interfaces
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(b8c31bba-79db-4a1d-930d-4cdd68713f9e)]
interface nsIXPCComponents_Interfaces : nsISupports
{
};

/**
* interface of Components.classes
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(978ff520-d26c-11d2-9842-006008962422)]
interface nsIXPCComponents_Classes : nsISupports
{
};

/**
* interface of Components.classesByID
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(336a9590-4d19-11d3-9893-006008962422)]
interface nsIXPCComponents_ClassesByID : nsISupports
{
};

/**
* interface of Components.results
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(2fc229a0-5860-11d3-9899-006008962422)]
interface nsIXPCComponents_Results : nsISupports
{
};

/**
* interface of Components.ID
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(7994a6e0-e028-11d3-8f5d-0010a4e73d9a)]
interface nsIXPCComponents_ID : nsISupports
{
};

/**
* interface of Components.Exception
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(5bf039c0-e028-11d3-8f5d-0010a4e73d9a)]
interface nsIXPCComponents_Exception : nsISupports
{
};

/**
* interface of Components.Constructor
* (interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(88655640-e028-11d3-8f5d-0010a4e73d9a)]
interface nsIXPCComponents_Constructor : nsISupports
{
};

/**
* interface of object returned by Components.Constructor
* (additional interesting stuff only reflected into JavaScript)
*/
[scriptable, uuid(c814ca20-e0dc-11d3-8f5f-0010a4e73d9a)]
interface nsIXPCConstructor : nsISupports
{
    readonly attribute nsIJSCID classID;
    readonly attribute nsIJSIID interfaceID;
    readonly attribute string   initializer;
};

/**
* interface of object returned by Components.utils.Sandbox.
*/
[scriptable, uuid(4f8ae0dc-d266-4a32-875b-6a9de71a8ce9)]
interface nsIXPCComponents_utils_Sandbox : nsISupports
{
};

/**
 * interface for callback to be passed to Cu.schedulePreciseGC
 */
[scriptable, function, uuid(71000535-b0fd-44d1-8ce0-909760e3953c)]
interface ScheduledGCCallback : nsISupports
{
    void callback();
};

/**
* interface of Components.utils
*/
[scriptable, uuid(ae292d08-cfb0-4862-a2b6-4779e5ef7e72)]
interface nsIXPCComponents_Utils : nsISupports
{

    /* reportError is designed to be called from JavaScript only.
     *
     * It will report a JS Error object to the JS console, and return. It
     * is meant for use in exception handler blocks which want to "eat"
     * an exception, but still want to report it to the console.
     *
     * It must be called with one param, usually an object which was caught by
     * an exception handler.  If it is not a JS error object, the parameter
     * is converted to a string and reported as a new error.
     */
    [implicit_jscontext] void reportError(in jsval error);

    readonly attribute nsIXPCComponents_utils_Sandbox Sandbox;

    /*
     * evalInSandbox is designed to be called from JavaScript only.
     *
     * evalInSandbox evaluates the provided source string in the given sandbox.
     * It returns the result of the evaluation to the caller.
     *
     * var s = new C.u.Sandbox("http://www.mozilla.org");
     * var res = C.u.evalInSandbox("var five = 5; 2 + five", s);
     * var outerFive = s.five;
     * s.seven = res;
     * var thirtyFive = C.u.evalInSandbox("five * seven", s);
     */
    [implicit_jscontext,optional_argc]
    jsval evalInSandbox(in AString source, in jsval sandbox,
                        [optional] in jsval version,
                        [optional] in jsval filename,
                        [optional] in long lineNo);

    /*
     * getSandboxMetadata is designed to be called from JavaScript only.
     *
     * getSandboxMetadata retrieves the metadata associated with
     * a sandbox object. It will return undefined if there
     * is no metadata attached to the sandbox.
     *
     * var s = C.u.Sandbox(..., { metadata: "metadata" });
     * var metadata = C.u.getSandboxMetadata(s);
     */
    [implicit_jscontext]
    jsval getSandboxMetadata(in jsval sandbox);

    /*
     * setSandboxMetadata is designed to be called from JavaScript only.
     *
     * setSandboxMetadata sets the metadata associated with
     * a sandbox object.
     *
     * Note that the metadata object will be copied before being used.
     * The copy will be performed using the structured clone algorithm.
     * Note that this algorithm does not support reflectors and
     * it will throw if it encounters them.
     */
    [implicit_jscontext]
    void setSandboxMetadata(in jsval sandbox, in jsval metadata);

    /*
     * import is designed to be called from JavaScript only.
     *
     * Synchronously loads and evaluates the js file located at
     * 'registryLocation' with a new, fully privileged global object.
     *
     * If 'targetObj' is specified and equal to null, returns the
     * module's global object. Otherwise (if 'targetObj' is not
     * specified, or 'targetObj' is != null) looks for a property
     * 'EXPORTED_SYMBOLS' on the new global object. 'EXPORTED_SYMBOLS'
     * is expected to be an array of strings identifying properties on
     * the global object.  These properties will be installed as
     * properties on 'targetObj', or, if 'targetObj' is not specified,
     * on the caller's global object. If 'EXPORTED_SYMBOLS' is not
     * found, an error is thrown.
     *
     * @param resourceURI A resource:// URI string to load the module from.
     * @param targetObj  the object to install the exported properties on.
     *        If this parameter is a primitive value, this method throws
     *        an exception.
     * @returns the module code's global object.
     *
     * The implementation maintains a hash of registryLocation->global obj.
     * Subsequent invocations of importModule with 'registryLocation'
     * pointing to the same file will not cause the module to be re-evaluated,
     * but the symbols in EXPORTED_SYMBOLS will be exported into the
     * specified target object and the global object returned as above.
     *
     * (This comment is duplicated from xpcIJSModuleLoader.)
     */
    [implicit_jscontext,optional_argc]
    jsval import(in AUTF8String aResourceURI, [optional] in jsval targetObj);

    /*
     * Unloads the JS module at 'registryLocation'. Existing references to the
     * module will continue to work but any subsequent import of the module will
     * reload it and give new reference. If the JS module hasn't yet been
     * imported then this method will do nothing.
     *
     * @param resourceURI A resource:// URI string to unload the module from.
     */
    void unload(in AUTF8String registryLocation);

    /*
     * Imports global properties (like DOM constructors) into the scope, defining
     * them on the caller's global. aPropertyList should be an array of property
     * names.
     *
     * See xpc::GlobalProperties::Parse for the current list of supported
     * properties.
     */
    [implicit_jscontext]
    void importGlobalProperties(in jsval aPropertyList);

    /*
     * To be called from JS only.
     *
     * Return a weak reference for the given JS object.
     */
    [implicit_jscontext]
    xpcIJSWeakReference getWeakReference(in jsval obj);

    /*
     * To be called from JS only.
     *
     * Force an immediate garbage collection cycle.
     */
    void forceGC();

    /*
     * To be called from JS only.
     *
     * Force an immediate cycle collection cycle.
     */
    void forceCC();
    
    /*
     * To be called from JS only.
     *
     * Force an immediate shrinking garbage collection cycle.
     */
    void forceShrinkingGC();

    /*
     * Schedule a garbage collection cycle for a point in the future when no JS
     * is running. Call the provided function once this has occurred.
     */
    void schedulePreciseGC(in ScheduledGCCallback callback);
    
    /*
     * Schedule a shrinking garbage collection cycle for a point in the future
     * when no JS is running. Call the provided function once this has occured.
     */
    void schedulePreciseShrinkingGC(in ScheduledGCCallback callback);

    /**
     * Return the keys in a weak map.  This operation is
     * non-deterministic because it is affected by the scheduling of the
     * garbage collector and the cycle collector.
     *
     * This should only be used to write tests of the interaction of
     * the GC and CC with weak maps.
     *
     * @param aMap weak map or other JavaScript value
     * @returns If aMap is a weak map object, return the keys of the weak
                map as an array.  Otherwise, return undefined.
     */
    [implicit_jscontext]
    jsval nondeterministicGetWeakMapKeys(in jsval aMap);

    [implicit_jscontext]
    jsval getJSTestingFunctions();

    /*
     * To be called from JS only.
     *
     * Returns the global object with which the given object is associated.
     *
     * @param obj The JavaScript object whose global is to be gotten.
     * @return the corresponding global.
     */
    [implicit_jscontext]
    jsval getGlobalForObject(in jsval obj);

    /*
     * To be called from JS only.
     *
     * Returns the true if the object is a (scripted) proxy.
     * NOTE: Security wrappers are unwrapped first before the check.
     */
    [implicit_jscontext]
    boolean isProxy(in jsval vobject);

    /*
     * Similar to evalInSandbox except this one is used to eval a script in the
     * scope of a window. Also note, that the return value and the possible exceptions
     * in the script are structured cloned, unless they are natives (then they are just
     * wrapped).
     * Principal of the caller must subsume the target's.
     */
    [implicit_jscontext]
    jsval evalInWindow(in AString source, in jsval window);

    /*
     * To be called from JS only.
     *
     * Instead of simply wrapping a function into another compartment,
     * this helper function creates a native function in the target
     * compartment and forwards the call to the original function.
     * That call will be different than a regular JS function call in
     * that, the |this| is left unbound, and all the non-native JS
     * object arguments will be cloned using the structured clone
     * algorithm.
     * The return value is the new forwarder function, wrapped into
     * the caller's compartment.
     * The 3rd argument is an optional options object:
     * - defineAs: the name of the property that will
     *             be set on the target scope, with
     *             the forwarder function as the value.
     */
    [implicit_jscontext]
    jsval exportFunction(in jsval vfunction, in jsval vscope, [optional] in jsval voptions);

    /*
     * To be called from JS only.
     *
     * Returns an object created in |vobj|'s compartment.
     * If defineAs property on the options object is a non-null ID,
     * the new object will be added to vobj as a property. Also, the
     * returned new object is always automatically waived (see waiveXrays).
     */
    [implicit_jscontext]
    jsval createObjectIn(in jsval vobj, [optional] in jsval voptions);

    /*
     * To be called from JS only.
     *
     * Returns an array created in |vobj|'s compartment.
     */
    [implicit_jscontext]
    jsval createArrayIn(in jsval vobj);

    /*
     * To be called from JS only.
     *
     * Returns a date given timestamp |msec| created in |vobj|'s compartment.
     */
    [implicit_jscontext]
    jsval createDateIn(in jsval vobj, in long long msec);

    /*
     * To be called from JS only.
     *
     * Ensures that all functions come from vobj's scope (and aren't cross
     * compartment wrappers).
     */
    [implicit_jscontext]
    void makeObjectPropsNormal(in jsval vobj);

    /**
     * Determines whether this object is backed by a DeadObjectProxy.
     *
     * Dead-wrapper objects hold no other objects alive (they have no outgoing
     * reference edges) and will throw if you touch them (e.g. by
     * reading/writing a property).
     */
    bool isDeadWrapper(in jsval obj);

    /*
     * To be called from JS only. This is for Gecko internal use only, and may
     * disappear at any moment.
     *
     * Forces a recomputation of all wrappers in and out of the compartment
     * containing |vobj|. If |vobj| is not an object, all wrappers system-wide
     * are recomputed.
     */
    [implicit_jscontext]
    void recomputeWrappers([optional] in jsval vobj);

    /*
     * To be called from JS only. This is for Gecko internal use only, and may
     * disappear at any moment.
     *
     * Enables Xray vision for same-compartment access for the compartment
     * indicated by |vscope|. All outgoing wrappers are recomputed.
     */
    [implicit_jscontext]
    void setWantXrays(in jsval vscope);

    /*
     * This seemingly-paradoxical API allows privileged code to explicitly give
     * unprivileged code a reference to its own Components object (whereas it's
     * normally hidden away on a scope chain visible only to XBL methods). See
     * also SpecialPowers.getComponents.
     */
    [implicit_jscontext]
    jsval getComponentsForScope(in jsval vscope);

    /*
     * Dispatches a runnable to the current/main thread. If |scope| is passed,
     * the runnable will be dispatch in the compartment of |scope|, which
     * affects which error reporter gets called.
     */
    [implicit_jscontext]
    void dispatch(in jsval runnable, [optional] in jsval scope);

    /*
     * To be called from JS only.
     *
     * These are the set of JSContext options that privileged script
     * is allowed to control for the purposes of testing.  These
     * options should be kept in sync with what's controllable in the
     * jsshell and by setting prefs in nsJSEnvironment.
     *
     * NB: Assume that getting any of these attributes is relatively
     * cheap, but setting any of them is relatively expensive.
     */
    [implicit_jscontext]
    attribute boolean strict;

    [implicit_jscontext]
    attribute boolean werror;

    [implicit_jscontext]
    attribute boolean strict_mode;

    [implicit_jscontext]
    attribute boolean ion;

    [implicit_jscontext]
    void setGCZeal(in long zeal);

    [implicit_jscontext]
    void nukeSandbox(in jsval obj);

    /*
     * API to dynamically block script for a given global. This takes effect
     * immediately, unlike other APIs that only affect newly-created globals.
     *
     * The machinery here maintains a counter, and allows script only if each
     * call to blockScriptForGlobal() has been matched with a call to
     * unblockScriptForGlobal(). The caller _must_ make sure never to call
     * unblock() more times than it calls block(), since that could potentially
     * interfere with another consumer's script blocking.
     */

    [implicit_jscontext]
    void blockScriptForGlobal(in jsval global);

    [implicit_jscontext]
    void unblockScriptForGlobal(in jsval global);

    /**
     * Check whether the given object is an XrayWrapper.
     */
    bool isXrayWrapper(in jsval obj);

    /**
     * Waive Xray on a given value. Identity op for primitives.
     */
    [implicit_jscontext]
    jsval waiveXrays(in jsval aVal);

    /**
     * Strip off Xray waivers on a given value. Identity op for primitives.
     */
    [implicit_jscontext]
    jsval unwaiveXrays(in jsval aVal);

    /**
     * Gets the name of the JSClass of the object.
     *
     * if |aUnwrap| is true, all wrappers are unwrapped first. Unless you're
     * specifically trying to detect whether the object is a proxy, this is
     * probably what you want.
     */
    [implicit_jscontext]
    string getClassName(in jsval aObj, in bool aUnwrap);

    /**
     * Get a DOM classinfo for the given classname.  Only some class
     * names are supported.
     */
    nsIClassInfo getDOMClassInfo(in AString aClassName);

    /**
     * Gets the incument global for the execution of this function. For internal
     * and testing use only.
     *
     * If |callback| is passed, it is invoked with the incumbent global as its
     * sole argument. This allows the incumbent global to be measured in callback
     * environments with no scripted frames on the stack.
     */
    [implicit_jscontext]
    jsval getIncumbentGlobal([optional] in jsval callback);

    /**
     * Forces the generation of an XPCWrappedJS for a given object. For internal
     * and testing use only. This is only useful to set up wrapper map conditions
     * for a testcase. The return value is not an XPCWrappedJS itself, but an
     * opaque nsISupports holder that keeps the underlying XPCWrappedJS alive.
     *
     * if |scope| is passed, the XPCWrappedJS is generated in the scope of that object.
     */
    [implicit_jscontext]
    nsISupports generateXPCWrappedJS(in jsval obj, [optional] in jsval scope);

    /**
      * Retrieve the last time, in microseconds since epoch, that a given
      * watchdog-related event occured.
      *
      * Valid categories:
      *   "RuntimeStateChange"      - Runtime switching between active and inactive states
      *   "WatchdogWakeup"          - Watchdog waking up from sleeping
      *   "WatchdogHibernateStart"  - Watchdog begins hibernating
      *   "WatchdogHibernateStop"   - Watchdog stops hibernating
      */
    PRTime getWatchdogTimestamp(in AString aCategory);
};

/**
* interface of JavaScript's 'Components' object
*/
[scriptable, uuid(4229848f-f49e-40e5-90cc-66968aaf4e1b)]
interface nsIXPCComponents : nsISupports
{
    readonly attribute nsIXPCComponents_Interfaces      interfaces;
    readonly attribute nsIXPCComponents_InterfacesByID  interfacesByID;
    readonly attribute nsIXPCComponents_Classes         classes;
    readonly attribute nsIXPCComponents_ClassesByID     classesByID;
    readonly attribute nsIStackFrame                    stack;
    readonly attribute nsIXPCComponents_Results         results;
    readonly attribute nsIComponentManager              manager;
    readonly attribute nsIXPCComponents_Utils           utils;

    readonly attribute nsIXPCComponents_ID              ID;
    readonly attribute nsIXPCComponents_Exception       Exception;
    readonly attribute nsIXPCComponents_Constructor     Constructor;

    boolean isSuccessCode(in nsresult result);

    /* @deprecated Use Components.utils.reportError instead. */
    [deprecated, implicit_jscontext] void reportError(in jsval error);

    /* 'lastResult' is accessible via JavaScript only */
    /* 'returnCode' is accessible via JavaScript only */
};
