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 (777e60ca8853)

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
/* -*- 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/. */

#ifndef nsXBLPrototypeHandler_h__
#define nsXBLPrototypeHandler_h__

#include "nsIAtom.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIController.h"
#include "nsAutoPtr.h"
#include "nsXBLEventHandler.h"
#include "nsIWeakReference.h"
#include "nsIScriptGlobalObject.h"
#include "nsCycleCollectionParticipant.h"
#include "js/TypeDecls.h"

class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsXBLPrototypeBinding;

namespace mozilla {
namespace dom {
class EventTarget;
}
}

#define NS_HANDLER_TYPE_XBL_JS              (1 << 0)
#define NS_HANDLER_TYPE_XBL_COMMAND         (1 << 1)
#define NS_HANDLER_TYPE_XUL                 (1 << 2)
#define NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR (1 << 4)
#define NS_HANDLER_ALLOW_UNTRUSTED          (1 << 5)
#define NS_HANDLER_TYPE_SYSTEM              (1 << 6)
#define NS_HANDLER_TYPE_PREVENTDEFAULT      (1 << 7)

// XXX Use nsIDOMEvent:: codes?
#define NS_PHASE_CAPTURING          1
#define NS_PHASE_TARGET             2
#define NS_PHASE_BUBBLING           3

class nsXBLPrototypeHandler
{
public:
  // This constructor is used by XBL handlers (both the JS and command shorthand variety)
  nsXBLPrototypeHandler(const char16_t* aEvent, const char16_t* aPhase,
                        const char16_t* aAction, const char16_t* aCommand,
                        const char16_t* aKeyCode, const char16_t* aCharCode,
                        const char16_t* aModifiers, const char16_t* aButton,
                        const char16_t* aClickCount, const char16_t* aGroup,
                        const char16_t* aPreventDefault,
                        const char16_t* aAllowUntrusted,
                        nsXBLPrototypeBinding* aBinding,
                        uint32_t aLineNumber);

  // This constructor is used only by XUL key handlers (e.g., <key>)
  nsXBLPrototypeHandler(nsIContent* aKeyElement);

  // This constructor is used for handlers loaded from the cache
  nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);

  ~nsXBLPrototypeHandler();

  // if aCharCode is not zero, it is used instead of the charCode of aKeyEvent.
  bool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent,
                         uint32_t aCharCode = 0,
                         bool aIgnoreShiftKey = false);
  inline bool KeyEventMatched(nsIAtom* aEventType,
                                nsIDOMKeyEvent* aEvent,
                                uint32_t aCharCode = 0,
                                bool aIgnoreShiftKey = false)
  {
    if (aEventType != mEventName)
      return false;

    return KeyEventMatched(aEvent, aCharCode, aIgnoreShiftKey);
  }

  bool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
  inline bool MouseEventMatched(nsIAtom* aEventType,
                                  nsIDOMMouseEvent* aEvent)
  {
    if (aEventType != mEventName)
      return false;

    return MouseEventMatched(aEvent);
  }

  already_AddRefed<nsIContent> GetHandlerElement();

  void AppendHandlerText(const nsAString& aText);

  uint8_t GetPhase() { return mPhase; }
  uint8_t GetType() { return mType; }

  nsXBLPrototypeHandler* GetNextHandler() { return mNextHandler; }
  void SetNextHandler(nsXBLPrototypeHandler* aHandler) { mNextHandler = aHandler; }

  nsresult ExecuteHandler(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);

  already_AddRefed<nsIAtom> GetEventName();
  void SetEventName(nsIAtom* aName) { mEventName = aName; }

  nsXBLEventHandler* GetEventHandler()
  {
    if (!mHandler) {
      NS_NewXBLEventHandler(this, mEventName, getter_AddRefs(mHandler));
      // XXX Need to signal out of memory?
    }

    return mHandler;
  }

  nsXBLEventHandler* GetCachedEventHandler()
  {
    return mHandler;
  }

  bool HasAllowUntrustedAttr()
  {
    return (mType & NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR) != 0;
  }

  // This returns a valid value only if HasAllowUntrustedEventsAttr returns
  // true.
  bool AllowUntrustedEvents()
  {
    return (mType & NS_HANDLER_ALLOW_UNTRUSTED) != 0;
  }

  nsresult Read(nsIObjectInputStream* aStream);
  nsresult Write(nsIObjectOutputStream* aStream);

public:
  static uint32_t gRefCnt;

protected:
  void Init() {
    ++gRefCnt;
    if (gRefCnt == 1)
      // Get the primary accelerator key.
      InitAccessKeys();
  }

  already_AddRefed<nsIController> GetController(mozilla::dom::EventTarget* aTarget);

  inline int32_t GetMatchingKeyCode(const nsAString& aKeyName);
  void ConstructPrototype(nsIContent* aKeyElement,
                          const char16_t* aEvent=nullptr, const char16_t* aPhase=nullptr,
                          const char16_t* aAction=nullptr, const char16_t* aCommand=nullptr,
                          const char16_t* aKeyCode=nullptr, const char16_t* aCharCode=nullptr,
                          const char16_t* aModifiers=nullptr, const char16_t* aButton=nullptr,
                          const char16_t* aClickCount=nullptr, const char16_t* aGroup=nullptr,
                          const char16_t* aPreventDefault=nullptr,
                          const char16_t* aAllowUntrusted=nullptr);

  void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aElement, const char *aMessageName);
  void GetEventType(nsAString& type);
  bool ModifiersMatchMask(nsIDOMUIEvent* aEvent,
                            bool aIgnoreShiftKey = false);
  nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
  nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
  nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
                              nsIScriptContext *aBoundContext, nsIAtom *aName,
                              JS::MutableHandle<JSObject*> aHandler);
  static int32_t KeyToMask(int32_t key);
  
  static int32_t kAccelKey;
  static int32_t kMenuAccessKey;
  static void InitAccessKeys();

  static const int32_t cShift;
  static const int32_t cAlt;
  static const int32_t cControl;
  static const int32_t cMeta;
  static const int32_t cOS;

  static const int32_t cShiftMask;
  static const int32_t cAltMask;
  static const int32_t cControlMask;
  static const int32_t cMetaMask;
  static const int32_t cOSMask;

  static const int32_t cAllModifiers;

protected:
  union {
    nsIWeakReference* mHandlerElement;  // For XUL <key> element handlers. [STRONG]
    char16_t*        mHandlerText;     // For XBL handlers (we don't build an
                                        // element for the <handler>, and instead
                                        // we cache the JS text or command name
                                        // that we should use.
  };

  uint32_t mLineNumber;  // The line number we started at in the XBL file
  
  // The following four values make up 32 bits.
  uint8_t mPhase;            // The phase (capturing, bubbling)
  uint8_t mType;             // The type of the handler.  The handler is either a XUL key
                             // handler, an XBL "command" event, or a normal XBL event with
                             // accompanying JavaScript.  The high bit is used to indicate
                             // whether this handler should prevent the default action.
  uint8_t mMisc;             // Miscellaneous extra information.  For key events,
                             // stores whether or not we're a key code or char code.
                             // For mouse events, stores the clickCount.

  int32_t mKeyMask;          // Which modifier keys this event handler expects to have down
                             // in order to be matched.
 
  // The primary filter information for mouse/key events.
  int32_t mDetail;           // For key events, contains a charcode or keycode. For
                             // mouse events, stores the button info.

  // Prototype handlers are chained. We own the next handler in the chain.
  nsXBLPrototypeHandler* mNextHandler;
  nsCOMPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
  nsRefPtr<nsXBLEventHandler> mHandler;
  nsXBLPrototypeBinding* mPrototypeBinding; // the binding owns us
};

#endif