/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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"
#include "nsIRunnable.idl"
%{C++
#include "nsCOMPtr.h"
#include "mozilla/AlreadyAddRefed.h"
%}

native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>&&);

[scriptable, uuid(f9d60700-e6dc-4a72-9537-689058655472)]
interface nsIEventTarget : nsISupports
{
  /* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
  /**
   * This must be non-virtual due to issues with MSVC 2013's ordering of
   * vtbls for overloads.  With other platforms we can leave this virtual
   * and avoid adding lots of Dispatch() methods to classes inheriting this.
   */
%{C++
    nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
      return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
    }
%}

  /**
   * This flag specifies the default mode of event dispatch, whereby the event
   * is simply queued for later processing.  When this flag is specified,
   * dispatch returns immediately after the event is queued.
   */
  const unsigned long DISPATCH_NORMAL = 0;

  /**
   * This flag specifies the synchronous mode of event dispatch, in which the
   * dispatch method does not return until the event has been processed.
   *
   * NOTE: passing this flag to dispatch may have the side-effect of causing
   * other events on the current thread to be processed while waiting for the
   * given event to be processed.
   */
  const unsigned long DISPATCH_SYNC = 1;

  /**
   * Check to see if this event target is associated with the current thread.
   *
   * @returns
   *   A boolean value that if "true" indicates that events dispatched to this
   *   event target will run on the current thread (i.e., the thread calling
   *   this method).
   */
  boolean isOnCurrentThread();

  /**
   * Dispatch an event to this event target.  This function may be called from
   * any thread, and it may be called re-entrantly.
   *
   * @param event
   *   The alreadyAddRefed<> event to dispatch.
   *   NOTE that the event will be leaked if it fails to dispatch. Also note
   *   that if "flags" includes DISPATCH_SYNC, it may return error from Run()
   *   after a successful dispatch. In that case, the event is not leaked.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [noscript, binaryname(Dispatch)] void dispatchFromC(in alreadyAddRefed_nsIRunnable event, in unsigned long flags);
  /**
   * Version of Dispatch to expose to JS, which doesn't require an alreadyAddRefed<>
   * (it will be converted to that internally)
   *
   * @param event
   *   The (raw) event to dispatch.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [binaryname(DispatchFromScript)] void dispatch(in nsIRunnable event, in unsigned long flags);
};

%{C++
// convenient aliases:
#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
#define NS_DISPATCH_SYNC   nsIEventTarget::DISPATCH_SYNC
%}
