summaryrefslogtreecommitdiffstats
path: root/dom/events/KeyboardEvent.h
blob: a43c6caaefe3670dd3d0169e09822367509850d7 (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
/* -*- 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_KeyboardEvent_h_
#define mozilla_dom_KeyboardEvent_h_

#include "mozilla/dom/UIEvent.h"
#include "mozilla/dom/KeyboardEventBinding.h"
#include "mozilla/EventForwards.h"

namespace mozilla::dom {

class KeyboardEvent : public UIEvent {
 public:
  KeyboardEvent(EventTarget* aOwner, nsPresContext* aPresContext,
                WidgetKeyboardEvent* aEvent);

  NS_INLINE_DECL_REFCOUNTING_INHERITED(KeyboardEvent, UIEvent)

  virtual KeyboardEvent* AsKeyboardEvent() override { return this; }

  static already_AddRefed<KeyboardEvent> ConstructorJS(
      const GlobalObject& aGlobal, const nsAString& aType,
      const KeyboardEventInit& aParam);

  virtual JSObject* WrapObjectInternal(
      JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override {
    return KeyboardEvent_Binding::Wrap(aCx, this, aGivenProto);
  }

  bool AltKey(CallerType aCallerType = CallerType::System);
  bool CtrlKey(CallerType aCallerType = CallerType::System);
  bool ShiftKey(CallerType aCallerType = CallerType::System);
  bool MetaKey();

  // Returns true if the modifier state of the event matches the modifier state
  // of access key.
  bool IsMenuAccessKeyPressed() const;
  Modifiers GetModifiersForMenuAccessKey() const;

  bool GetModifierState(const nsAString& aKey,
                        CallerType aCallerType = CallerType::System) {
    bool modifierState = GetModifierStateInternal(aKey);

    if (!ShouldResistFingerprinting(aCallerType)) {
      return modifierState;
    }

    Modifiers modifier = WidgetInputEvent::GetModifier(aKey);
    return GetSpoofedModifierStates(modifier, modifierState);
  }

  bool Repeat();
  bool IsComposing();
  void GetKey(nsAString& aKey) const;
  uint32_t CharCode(CallerType aCallerType = CallerType::System);
  uint32_t KeyCode(CallerType aCallerType = CallerType::System);
  virtual uint32_t Which(CallerType aCallerType = CallerType::System) override;
  uint32_t Location();

  void GetCode(nsAString& aCode, CallerType aCallerType = CallerType::System);
  void GetInitDict(KeyboardEventInit& aParam);

  void InitKeyEventJS(const nsAString& aType, bool aCanBubble, bool aCancelable,
                      nsGlobalWindowInner* aView, bool aCtrlKey, bool aAltKey,
                      bool aShiftKey, bool aMetaKey, uint32_t aKeyCode,
                      uint32_t aCharCode);
  static bool IsInitKeyEventAvailable(JSContext*, JSObject*);

  void InitKeyboardEventJS(const nsAString& aType, bool aCanBubble,
                           bool aCancelable, nsGlobalWindowInner* aView,
                           const nsAString& aKey, uint32_t aLocation,
                           bool aCtrlKey, bool aAltKey, bool aShiftKey,
                           bool aMetaKey);

 protected:
  ~KeyboardEvent() = default;

  void InitWithKeyboardEventInit(EventTarget* aOwner, const nsAString& aType,
                                 const KeyboardEventInit& aParam);

 private:
  // True, if the instance is initialized by JS.
  bool mInitializedByJS;
  // True, if the instance is initialized by Ctor.
  bool mInitializedByCtor;

  // If the instance is created with Constructor(), which may have independent
  // value.  mInitializedWhichValue stores it.  I.e., this is invalid when
  // mInitializedByCtor is false.
  uint32_t mInitializedWhichValue;

  // This method returns the boolean to indicate whether spoofing keyboard
  // event for fingerprinting resistance. It will return true when pref
  // 'privacy.resistFingerprinting' is true and the event target is content.
  // Otherwise, it will return false.
  bool ShouldResistFingerprinting(CallerType aCallerType);

  // This method returns the spoofed modifier state of the given modifier key
  // for fingerprinting resistance.
  bool GetSpoofedModifierStates(const Modifiers aModifierKey,
                                const bool aRawModifierState);

  /**
   * ComputeTraditionalKeyCode() computes traditional keyCode value.  I.e.,
   * returns 0 if this event should return non-zero from CharCode().
   * In spite of the name containing "traditional", this computes spoof
   * keyCode value if user wants it.
   *
   * @param aKeyboardEvent  Should be |*mEvent->AsKeyboardEvent()|.
   * @param aCallerType     Set caller type of KeyCode() or CharCode().
   * @return                If traditional charCode value is 0, returns
   *                        the raw keyCode value or spoof keyCode value.
   *                        Otherwise, 0.
   */
  uint32_t ComputeTraditionalKeyCode(WidgetKeyboardEvent& aKeyboardEvent,
                                     CallerType aCallerType);
  /**
   * ShouldUseSameValueForCharCodeAndKeyCode() returns true if KeyCode() and
   * CharCode() should return same value.
   */
  bool ShouldUseSameValueForCharCodeAndKeyCode(
      const WidgetKeyboardEvent& aKeyboardEvent, CallerType aCallerType) const;
};

}  // namespace mozilla::dom

already_AddRefed<mozilla::dom::KeyboardEvent> NS_NewDOMKeyboardEvent(
    mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext,
    mozilla::WidgetKeyboardEvent* aEvent);

#endif  // mozilla_dom_KeyboardEvent_h_