/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */

module threads {

    interface [
        Conditional=WORKERS,
        CustomMarkFunction,
        DelegatingGetOwnPropertySlot,
        EventTarget,
        ExtendsDOMGlobalObject,
        IsWorkerContext,
        LegacyParent=JSWorkerContextBase,
        NoStaticTables,
        OmitConstructor
    ] WorkerContext {

        // WorkerGlobalScope
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
                 attribute [Replaceable] WorkerContext self;
#endif
                 attribute [Replaceable] WorkerLocation location;
        void close();
                 attribute EventListener onerror;

        // WorkerUtils
        [Custom] void importScripts(/*[Variadic] in DOMString urls */);
                 attribute [Replaceable] WorkerNavigator navigator;
#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
        [EnabledAtRuntime, RequiresAllArguments=Raise] Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in [Callback, Optional] DatabaseCallback creationCallback)
            raises(DOMException);
        [EnabledAtRuntime, RequiresAllArguments=Raise] DatabaseSync openDatabaseSync(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in [Callback, Optional] DatabaseCallback creationCallback)
            raises(DOMException);
#endif

        // Timers
        [Custom] long setTimeout(in TimeoutHandler handler, in long timeout);
        // [Custom] long setTimeout(in DOMString code, in long timeout);
        void clearTimeout(in long handle);
        [Custom] long setInterval(in TimeoutHandler handler, in long timeout);
        // [Custom] long setInterval(in DOMString code, in long timeout);
        void clearInterval(in long handle);


        // EventTarget interface
        void addEventListener(in DOMString type, 
                              in EventListener listener, 
                              in boolean useCapture);
        void removeEventListener(in DOMString type, 
                                 in EventListener listener, 
                                 in boolean useCapture);
        boolean dispatchEvent(in Event evt)
            raises(EventException);

#if defined(ENABLE_NOTIFICATIONS) && ENABLE_NOTIFICATIONS
        // Notification interface
        readonly attribute [EnabledAtRuntime] NotificationCenter webkitNotifications;
#endif

#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
        // Constructors
        attribute MessageEventConstructor MessageEvent;
        attribute WorkerLocationConstructor WorkerLocation;

#if ENABLE_CHANNEL_MESSAGING
        attribute [JSCCustomGetter] MessageChannelConstructor MessageChannel;
#endif
#if ENABLE_EVENTSOURCE
        attribute [JSCCustomGetter] EventSourceConstructor EventSource;
#endif
        attribute [JSCCustomGetter] XMLHttpRequestConstructor XMLHttpRequest;
#if defined(ENABLE_WEB_SOCKETS) && ENABLE_WEB_SOCKETS
        attribute [JSCCustomGetter,EnabledAtRuntime] WebSocketConstructor WebSocket; // Usable with the new operator
#endif
#endif

#if defined(ENABLE_BLOB) && ENABLE_BLOB
        attribute BlobBuilderConstructor BlobBuilder;
        attribute FileReaderConstructor FileReader;
        attribute FileReaderSyncConstructor FileReaderSync;
        DOMString createObjectURL(in Blob blob);
        void revokeObjectURL(in DOMString blobURL);
#endif

#if defined(ENABLE_FILE_SYSTEM) && ENABLE_FILE_SYSTEM
        const unsigned short TEMPORARY = 0;
        const unsigned short PERSISTENT = 1;
        [EnabledAtRuntime=FileSystem] void requestFileSystem(in unsigned short type, in long long size, in [Callback, Optional] FileSystemCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback);
        [EnabledAtRuntime=FileSystem] DOMFileSystemSync requestFileSystemSync(in unsigned short type, in long long size) raises (FileException);

                 attribute [EnabledAtRuntime=FileSystem] FlagsConstructor Flags;
#endif

        attribute [Conditional=BLOB,EnabledAtRuntime] ArrayBufferConstructor ArrayBuffer; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Int8ArrayConstructor Int8Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Uint8ArrayConstructor Uint8Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Int16ArrayConstructor Int16Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Uint16ArrayConstructor Uint16Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Int32ArrayConstructor Int32Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Uint32ArrayConstructor Uint32Array; // Usable with new operator
        attribute [Conditional=BLOB,EnabledAtRuntime] Float32ArrayConstructor Float32Array; // Usable with new operator
    };

}
