summaryrefslogtreecommitdiffstats
path: root/dom/xbl/nsXBLPrototypeHandler.h
blob: 6898b73edebc1a02aeb81dd076b44b54cd5bd350 (plain)
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
/* -*- 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 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 "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 AutoJSAPI;
class EventTarget;
} // namespace dom
} // namespace mozilla

#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

namespace mozilla {
namespace dom {

struct IgnoreModifierState
{
  // When mShift is true, Shift key state will be ignored.
  bool mShift;
  // When mOS is true, OS key state will be ignored.
  bool mOS;

  IgnoreModifierState()
    : mShift(false)
    , mOS(false)
  {
  }
};

} // namespace dom
} // namespace mozilla

class nsXBLPrototypeHandler
{
  typedef mozilla::dom::IgnoreModifierState IgnoreModifierState;

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>)
  explicit nsXBLPrototypeHandler(nsIContent* aKeyElement);

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

  ~nsXBLPrototypeHandler();

  bool EventTypeEquals(nsIAtom* aEventType) const
  {
    return mEventName == aEventType;
  }

  // if aCharCode is not zero, it is used instead of the charCode of aKeyEvent.
  bool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent,
                       uint32_t aCharCode,
                       const IgnoreModifierState& aIgnoreModifierState);

  bool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
  inline bool MouseEventMatched(nsIAtom* aEventType,
                                  nsIDOMMouseEvent* aEvent)
  {
    if (!EventTypeEquals(aEventType)) {
      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) {
      mHandler = NS_NewXBLEventHandler(this, mEventName);
    }

    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,
                          const IgnoreModifierState& aIgnoreModifierState);
  nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
  nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
  nsresult EnsureEventHandler(mozilla::dom::AutoJSAPI& jsapi, nsIAtom* aName,
                              JS::MutableHandle<JSObject*> aHandler);
  static int32_t KeyToMask(int32_t key);
  static int32_t AccelKeyMask();

  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"
  RefPtr<nsXBLEventHandler> mHandler;
  nsXBLPrototypeBinding* mPrototypeBinding; // the binding owns us
};

#endif