DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (585fe4556335)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

#ifndef mozilla_dom_EventTarget_h_
#define mozilla_dom_EventTarget_h_

#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/DebuggerNotificationBinding.h"
#include "mozilla/dom/Nullable.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
#include "nsAtom.h"

class nsPIDOMWindowOuter;
class nsIGlobalObject;
class nsIDOMEventListener;

namespace mozilla {

class AsyncEventDispatcher;
class ErrorResult;
class EventChainPostVisitor;
class EventChainPreVisitor;
class EventChainVisitor;
class EventListenerManager;

namespace dom {

class AddEventListenerOptionsOrBoolean;
class Event;
class EventListener;
class EventListenerOptionsOrBoolean;
class EventHandlerNonNull;
class GlobalObject;
class WindowProxyHolder;

// IID for the dom::EventTarget interface
#define NS_EVENTTARGET_IID                           \
  {                                                  \
    0xde651c36, 0x0053, 0x4c67, {                    \
      0xb1, 0x3d, 0x67, 0xb9, 0x40, 0xfc, 0x82, 0xe4 \
    }                                                \
  }

class EventTarget : public nsISupports, public nsWrapperCache {
 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_EVENTTARGET_IID)

  // WebIDL API
  static already_AddRefed<EventTarget> Constructor(const GlobalObject& aGlobal,
                                                   ErrorResult& aRv);
  void AddEventListener(const nsAString& aType, EventListener* aCallback,
                        const AddEventListenerOptionsOrBoolean& aOptions,
                        const Nullable<bool>& aWantsUntrusted,
                        ErrorResult& aRv);
  void RemoveEventListener(const nsAString& aType, EventListener* aCallback,
                           const EventListenerOptionsOrBoolean& aOptions,
                           ErrorResult& aRv);

 protected:
  /**
   * This method allows addition of event listeners represented by
   * nsIDOMEventListener, with almost the same semantics as the
   * standard AddEventListener.  The one difference is that it just
   * has a "use capture" boolean, not an EventListenerOptions.
   */
  nsresult AddEventListener(const nsAString& aType,
                            nsIDOMEventListener* aListener, bool aUseCapture,
                            const Nullable<bool>& aWantsUntrusted);

 public:
  /**
   * Helper methods to make the nsIDOMEventListener version of
   * AddEventListener simpler to call for consumers.
   */
  nsresult AddEventListener(const nsAString& aType,
                            nsIDOMEventListener* aListener, bool aUseCapture) {
    return AddEventListener(aType, aListener, aUseCapture, Nullable<bool>());
  }
  nsresult AddEventListener(const nsAString& aType,
                            nsIDOMEventListener* aListener, bool aUseCapture,
                            bool aWantsUntrusted) {
    return AddEventListener(aType, aListener, aUseCapture,
                            Nullable<bool>(aWantsUntrusted));
  }

  /**
   * This method allows the removal of event listeners represented by
   * nsIDOMEventListener from the event target, with the same semantics as the
   * standard RemoveEventListener.
   */
  void RemoveEventListener(const nsAString& aType,
                           nsIDOMEventListener* aListener, bool aUseCapture);
  /**
   * RemoveSystemEventListener() should be used if you have used
   * AddSystemEventListener().
   */
  void RemoveSystemEventListener(const nsAString& aType,
                                 nsIDOMEventListener* aListener,
                                 bool aUseCapture);

  /**
   * Add a system event listener with the default wantsUntrusted value.
   */
  nsresult AddSystemEventListener(const nsAString& aType,
                                  nsIDOMEventListener* aListener,
                                  bool aUseCapture) {
    return AddSystemEventListener(aType, aListener, aUseCapture,
                                  Nullable<bool>());
  }

  /**
   * Add a system event listener with the given wantsUntrusted value.
   */
  nsresult AddSystemEventListener(const nsAString& aType,
                                  nsIDOMEventListener* aListener,
                                  bool aUseCapture, bool aWantsUntrusted) {
    return AddSystemEventListener(aType, aListener, aUseCapture,
                                  Nullable<bool>(aWantsUntrusted));
  }

  /**
   * Returns the EventTarget object which should be used as the target
   * of DOMEvents.
   * Usually |this| is returned, but for example Window (inner windw) returns
   * the WindowProxy (outer window).
   */
  virtual EventTarget* GetTargetForDOMEvent() { return this; };

  /**
   * Returns the EventTarget object which should be used as the target
   * of the event and when constructing event target chain.
   * Usually |this| is returned, but for example WindowProxy (outer window)
   * returns the Window (inner window).
   */
  virtual EventTarget* GetTargetForEventTargetChain() { return this; }

  /**
   * The most general DispatchEvent method.  This is the one the bindings call.
   */
  virtual bool DispatchEvent(Event& aEvent, CallerType aCallerType,
                             ErrorResult& aRv) = 0;

  /**
   * A version of DispatchEvent you can use if you really don't care whether it
   * succeeds or not and whether default is prevented or not.
   */
  void DispatchEvent(Event& aEvent);

  /**
   * A version of DispatchEvent you can use if you really don't care whether
   * default is prevented or not.
   */
  void DispatchEvent(Event& aEvent, ErrorResult& aRv);

  nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); }

  // Note, this takes the type in onfoo form!
  EventHandlerNonNull* GetEventHandler(const nsAString& aType) {
    RefPtr<nsAtom> type = NS_Atomize(aType);
    return GetEventHandler(type);
  }

  // Note, this takes the type in onfoo form!
  void SetEventHandler(const nsAString& aType, EventHandlerNonNull* aHandler,
                       ErrorResult& rv);

  // For an event 'foo' aType will be 'onfoo'.
  virtual void EventListenerAdded(nsAtom* aType) {}

  // For an event 'foo' aType will be 'onfoo'.
  virtual void EventListenerRemoved(nsAtom* aType) {}

  // Returns an outer window that corresponds to the inner window this event
  // target is associated with.  Will return null if the inner window is not the
  // current inner or if there is no window around at all.
  Nullable<WindowProxyHolder> GetOwnerGlobalForBindings();
  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() = 0;

  // The global object this event target is associated with, if any.
  // This may be an inner window or some other global object.  This
  // will never be an outer window.
  virtual nsIGlobalObject* GetOwnerGlobal() const = 0;

  /**
   * Get the event listener manager, creating it if it does not already exist.
   */
  virtual EventListenerManager* GetOrCreateListenerManager() = 0;

  /**
   * Get the event listener manager, returning null if it does not already
   * exist.
   */
  virtual EventListenerManager* GetExistingListenerManager() const = 0;

  virtual Maybe<EventCallbackDebuggerNotificationType>
  GetDebuggerNotificationType() const {
    return Nothing();
  }

  // Called from AsyncEventDispatcher to notify it is running.
  virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) {}

  // Used by APZ to determine whether this event target has non-chrome event
  // listeners for untrusted key events.
  bool HasNonSystemGroupListenersForUntrustedKeyEvents() const;

  // Used by APZ to determine whether this event target has non-chrome and
  // non-passive event listeners for untrusted key events.
  bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents() const;

  virtual bool IsApzAware() const;

  /**
   * Called before the capture phase of the event flow.
   * This is used to create the event target chain and implementations
   * should set the necessary members of EventChainPreVisitor.
   * At least aVisitor.mCanHandle must be set,
   * usually also aVisitor.mParentTarget if mCanHandle is true.
   * mCanHandle says that this object can handle the aVisitor.mEvent event and
   * the mParentTarget is the possible parent object for the event target chain.
   * @see EventDispatcher.h for more documentation about aVisitor.
   *
   * @param aVisitor the visitor object which is used to create the
   *                 event target chain for event dispatching.
   *
   * @note Only EventDispatcher should call this method.
   */
  virtual void GetEventTargetParent(EventChainPreVisitor& aVisitor) = 0;

  /**
   * Called before the capture phase of the event flow and after event target
   * chain creation. This is used to handle things that must be executed before
   * dispatching the event to DOM.
   */
  virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) { return NS_OK; }

  /**
   * If EventChainPreVisitor.mWantsWillHandleEvent is set true,
   * called just before possible event handlers on this object will be called.
   */
  virtual void WillHandleEvent(EventChainPostVisitor& aVisitor) {}

  /**
   * Called after the bubble phase of the system event group.
   * The default handling of the event should happen here.
   * @param aVisitor the visitor object which is used during post handling.
   *
   * @see EventDispatcher.h for documentation about aVisitor.
   * @note Only EventDispatcher should call this method.
   */
  MOZ_CAN_RUN_SCRIPT
  virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) = 0;

 protected:
  EventHandlerNonNull* GetEventHandler(nsAtom* aType);
  void SetEventHandler(nsAtom* aType, EventHandlerNonNull* aHandler);

  /**
   * Hook for AddEventListener that allows it to compute the right
   * wantsUntrusted boolean when one is not provided.  If this returns failure,
   * the listener will not be added.
   *
   * This hook will NOT be called unless aWantsUntrusted is null in
   * AddEventListener.  If you need to take action when event listeners are
   * added, use EventListenerAdded.  Especially because not all event listener
   * additions go through AddEventListener!
   */
  virtual bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) = 0;

  /**
   * A method to compute the right wantsUntrusted value for AddEventListener.
   * This will call the above hook as needed.
   *
   * If aOptions is non-null, and it contains a value for mWantUntrusted, that
   * value takes precedence over aWantsUntrusted.
   */
  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
                             const AddEventListenerOptionsOrBoolean* aOptions,
                             ErrorResult& aRv);

  /**
   * addSystemEventListener() adds an event listener of aType to the system
   * group.  Typically, core code should use the system group for listening to
   * content (i.e., non-chrome) element's events.  If core code uses
   * EventTarget::AddEventListener for a content node, it means
   * that the listener cannot listen to the event when web content calls
   * stopPropagation() of the event.
   *
   * @param aType            An event name you're going to handle.
   * @param aListener        An event listener.
   * @param aUseCapture      true if you want to listen the event in capturing
   *                         phase.  Otherwise, false.
   * @param aWantsUntrusted  true if you want to handle untrusted events.
   *                         false if not.
   *                         Null if you want the default behavior.
   */
  nsresult AddSystemEventListener(const nsAString& aType,
                                  nsIDOMEventListener* aListener,
                                  bool aUseCapture,
                                  const Nullable<bool>& aWantsUntrusted);
};

NS_DEFINE_STATIC_IID_ACCESSOR(EventTarget, NS_EVENTTARGET_IID)

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_EventTarget_h_