<!DOCTYPE html>
<html>
<head>
  <title>Test all synthetic events</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">

/**
 * kEventConstructors is a helper and database of all events.
 * The sort order of the definition is by A to Z (ignore the Event postfix).
 *
 * XXX: should we move this into EventUtils.js?
 *
 * create: function or null.  If this is null, it's impossible to create untrusted event for it.
 *         Otherwise, create(aName, aProps) returns an instance of the event initialized with aProps.
 *         aName specifies the event's type name.  See each create() code for the detail of aProps.
 */
const kEventConstructors = {
  Event:                                     { create: function (aName, aProps) {
                                                         return new Event(aName, aProps);
                                                       },
                                             },
  AnimationEvent:                            { create: function (aName, aProps) {
                                                         return new AnimationEvent(aName, aProps);
                                                       },
                                             },
  AnimationPlaybackEvent:                    { create: function (aName, aProps) {
                                                         return new AnimationPlaybackEvent(aName, aProps);
                                                       },
                                             },
  AudioProcessingEvent:                      { create: null, // Cannot create untrusted event from JS.
                                             },
  BeforeAfterKeyboardEvent:                  { create: function (aName, aProps) {
                                                         return new BeforeAfterKeyboardEvent(aName, aProps);
                                                       },
                                             },
  BeforeUnloadEvent:                         { create: function (aName, aProps) {
                                                         var e = document.createEvent("beforeunloadevent");
                                                         e.initEvent(aName, aProps.bubbles, aProps.cancelable);
                                                         return e;
                                                       },
                                             },
  BlobEvent:                                 { create: function (aName, aProps) {
                                                         return new BlobEvent(aName, aProps);
                                                       },
                                             },
  CallEvent:                                 { create: function (aName, aProps) {
                                                          return new CallEvent(aName, aProps);
                                                       },
                                             },
  CallGroupErrorEvent:                       { create: function (aName, aProps) {
                                                          return new CallGroupErrorEvent(aName, aProps);
                                                       },
                                             },
  CFStateChangeEvent:                        { create: function (aName, aProps) {
                                                          return new CFStateChangeEvent(aName, aProps);
                                                       },
                                             },
  CloseEvent:                                { create: function (aName, aProps) {
                                                         return new CloseEvent(aName, aProps);
                                                       },
                                             },
  ClipboardEvent:                            { create: function (aName, aProps) {
                                                         return new ClipboardEvent(aName, aProps);
                                                       },
                                             },
  CommandEvent:                              { create: function (aName, aProps) {
                                                         var e = document.createEvent("commandevent");
                                                         e.initCommandEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                            aProps.command);
                                                         return e;
                                                       },
                                             },
  CompositionEvent:                          { create: function (aName, aProps) {
                                                         var e = document.createEvent("compositionevent");
                                                         e.initCompositionEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                                aProps.view, aProps.data, aProps.locale);
                                                         return e;
                                                       },
                                             },
  CustomEvent:                               { create: function (aName, aProps) {
                                                         return new CustomEvent(aName, aProps);
                                                       },
                                             },
  DataErrorEvent:                            { create: function (aName, aProps) {
                                                          return new DataErrorEvent(aName, aProps);
                                                       },
                                             },
  DataContainerEvent:                        { create: function (aName, aProps) {
                                                         var e = document.createEvent("datacontainerevent");
                                                         e.initEvent(aName, aProps.bubbles, aProps.cancelable);
                                                         return e;
                                                       },
                                             },
  DeviceLightEvent:                          { create: function (aName, aProps) {
                                                         return new DeviceLightEvent(aName, aProps);
                                                       },
                                             },
  DeviceMotionEvent:                         { create: function (aName, aProps) {
                                                         var e = document.createEvent("devicemotionevent");
                                                         e.initDeviceMotionEvent(aName, aProps.bubbles, aProps.cancelable, aProps.acceleration,
                                                                                 aProps.accelerationIncludingGravity, aProps.rotationRate,
                                                                                 aProps.interval || 0.0);
                                                         return e;
                                                       },
                                             },
  DeviceOrientationEvent:                    { create: function (aName, aProps) {
                                                         return new DeviceOrientationEvent(aName, aProps);
                                                       },
                                             },
  DeviceProximityEvent:                      { create: function (aName, aProps) {
                                                         return new DeviceProximityEvent(aName, aProps);
                                                       },
                                             },
  DownloadEvent:                             { create: function (aName, aProps) {
                                                         return new DownloadEvent(aName, aProps);
                                                       },
                                             },
  DragEvent:                                 { create: function (aName, aProps) {
                                                         var e = document.createEvent("dragevent");
                                                         e.initDragEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                         aProps.view, aProps.detail,
                                                                         aProps.screenX, aProps.screenY,
                                                                         aProps.clientX, aProps.clientY,
                                                                         aProps.ctrlKey, aProps.altKey, aProps.shiftKey, aProps.metaKey,
                                                                         aProps.button, aProps.relatedTarget, aProps.dataTransfer);
                                                         return e;
                                                       },
                                             },
  ErrorEvent:                                { create: function (aName, aProps) {
                                                         return new ErrorEvent(aName, aProps);
                                                       },
  },
  FlyWebFetchEvent:                          { create: null, // Cannot create untrusted event from JS.
                                             },
  FlyWebWebSocketEvent:                      { create: null, // Cannot create untrusted event from JS.
                                             },
  FocusEvent:                                { create: function (aName, aProps) {
                                                         return new FocusEvent(aName, aProps);
                                                       },
                                             },
  FontFaceSetLoadEvent:                      { create: function (aName, aProps) {
                                                         return new FontFaceSetLoadEvent(aName, aProps);
                                                       },
                                             },
  GamepadEvent:                              { create: function (aName, aProps) {
                                                         return new GamepadEvent(aName, aProps);
                                                       },
                                             },
  GamepadAxisMoveEvent:                      { create: function (aName, aProps) {
                                                         return new GamepadAxisMoveEvent(aName, aProps);
                                                       },
                                             },
  GamepadButtonEvent:                        { create: function (aName, aProps) {
                                                         return new GamepadButtonEvent(aName, aProps);
                                                       },
                                             },
  HashChangeEvent:                           { create: function (aName, aProps) {
                                                         return new HashChangeEvent(aName, aProps);
                                                       },
                                             },
  IDBVersionChangeEvent:                     { create: function (aName, aProps) {
                                                         return new IDBVersionChangeEvent(aName, aProps);
                                                       },
                                             },
  ImageCaptureErrorEvent:                                { create: function (aName, aProps) {
                                                         return new ImageCaptureErrorEvent(aName, aProps);
                                                       },
                                             },
  InputEvent:                                { create: function (aName, aProps) {
                                                         return new InputEvent(aName, aProps);
                                                       },
                                             },
  KeyEvent:                                  { create: function (aName, aProps) {
                                                         return new KeyboardEvent(aName, aProps);
                                                       },
                                             },
  KeyboardEvent:                             { create: function (aName, aProps) {
                                                         return new KeyboardEvent(aName, aProps);
                                                       },
                                             },
  MediaEncryptedEvent:                       { create: function (aName, aProps) {
                                                         return new MediaEncryptedEvent(aName, aProps);
                                                       },
                                             },
  MediaKeyMessageEvent:                      { create: function (aName, aProps) {
                                                         return new MediaKeyMessageEvent(aName, {
                                                           messageType: "license-request",
                                                           message: new ArrayBuffer(0)
                                                         });
                                                       },
                                             },
  MediaStreamEvent:                          { create: function (aName, aProps) {
                                                         return new MediaStreamEvent(aName, aProps);
                                                       },
                                             },
  MediaStreamTrackEvent:                     {
                                               // Difficult to test required arguments.
                                             },
  MessageEvent:                              { create: function (aName, aProps) {
                                                         var e = new MessageEvent("messageevent", { bubbles: aProps.bubbles,
                                                             cancelable: aProps.cancelable, data: aProps.data, origin: aProps.origin,
                                                             lastEventId: aProps.lastEventId, source: aProps.source });
                                                         return e;
                                                       },
                                             },
  MouseEvent:                                { create: function (aName, aProps) {
                                                         return new MouseEvent(aName, aProps);
                                                       },
                                             },
  MouseScrollEvent:                          { create: function (aName, aProps) {
                                                         var e = document.createEvent("mousescrollevents");
                                                         e.initMouseScrollEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                                aProps.view, aProps.detail,
                                                                                aProps.screenX, aProps.screenY,
                                                                                aProps.clientX, aProps.clientY,
                                                                                aProps.ctrlKey, aProps.altKey, aProps.shiftKey, aProps.metaKey,
                                                                                aProps.button, aProps.relatedTarget, aProps.axis);
                                                         return e;
                                                       },
                                             },
  MozApplicationEvent:                       { create: function (aName, aProps) {
                                                         return new MozApplicationEvent(aName, aProps);
                                                       },
                                             },
  MozClirModeEvent:                          { create: function (aName, aProps) {
                                                         return new MozClirModeEvent(aName, aProps);
                                                       },
                                             },
  MozContactChangeEvent:                     { create: function (aName, aProps) {
                                                         return new MozContactChangeEvent(aName, aProps);
                                                       },
                                             },
  MozEmergencyCbModeEvent:                   { create: function (aName, aProps) {
                                                          return new MozEmergencyCbModeEvent(aName, aProps);
                                                       },
                                             },
  MozMessageDeletedEvent:                    { create: function (aName, aProps) {
                                                         return new MozMessageDeletedEvent(aName, aProps);
                                                       },
                                             },
  MozMmsEvent:                               { create: function (aName, aProps) {
                                                         return new MozMmsEvent(aName, aProps);
                                                       },
                                             },
  MozOtaStatusEvent:                         { create: function (aName, aProps) {
                                                          return new MozOtaStatusEvent(aName, aProps);
                                                       },
                                             },
  MozSettingsEvent:                          { create: function (aName, aProps) {
                                                         return new MozSettingsEvent(aName, aProps);
                                                       },
                                             },
  MozSettingsTransactionEvent:               { create: function (aName, aProps) {
                                                         return new MozSettingsTransactionEvent(aName, aProps);
                                                       },
                                             },
  MozSmsEvent:                               { create: function (aName, aProps) {
                                                         return new MozSmsEvent(aName, aProps);
                                                       },
                                             },
  MozStkCommandEvent:                        { create: function (aName, aProps) {
                                                          return new MozStkCommandEvent(aName, aProps);
                                                       },
                                             },
  MozWifiConnectionInfoEvent:                { create: function (aName, aProps) {
                                                         return new MozWifiConnectionInfoEvent(aName, aProps);
                                                       },
                                             },
  MozWifiStatusChangeEvent:                  { create: function (aName, aProps) {
                                                          return new MozWifiStatusChangeEvent(aName, aProps);
                                                       },
                                             },
  MozWifiStationInfoEvent:                   { create: function (aName, aProps) {
                                                          return new MozWifiStationInfoEvent(aName, aProps);
                                                       },
                                             },
  MutationEvent:                             { create: function (aName, aProps) {
                                                         var e = document.createEvent("mutationevent");
                                                         e.initMutationEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                             aProps.relatedNode, aProps.prevValue, aProps.newValue,
                                                                             aProps.attrName, aProps.attrChange);
                                                         return e;
                                                       },
                                             },
  NotifyPaintEvent:                          { create: function (aName, aProps) {
                                                         var e = document.createEvent("notifypaintevent");
                                                         e.initEvent(aName, aProps.bubbles, aProps.cancelable);
                                                         return e;
                                                       },
                                             },
  OfflineAudioCompletionEvent:               { create: null, // Cannot create untrusted event from JS.
                                             },
  PageTransitionEvent:                       { create: function (aName, aProps) {
                                                         return new PageTransitionEvent(aName, aProps);
                                                       },
                                             },
  PointerEvent:                              { create: function (aName, aProps) {
                                                         return new PointerEvent(aName, aProps);
                                                       },
                                             },
  PopStateEvent:                             { create: function (aName, aProps) {
                                                         return new PopStateEvent(aName, aProps);
                                                       },
                                             },
  PopupBlockedEvent:                         { create: function (aName, aProps) {
                                                         return new PopupBlockedEvent(aName, aProps);
                                                       },
                                             },
  ProgressEvent:                             { create: function (aName, aProps) {
                                                         return new ProgressEvent(aName, aProps);
                                                       },
                                             },
  RecordErrorEvent:                          { create: function (aName, aProps) {
                                                         return new RecordErrorEvent(aName, aProps);
                                                       },
                                             },
  RTCDataChannelEvent:                       { create: function (aName, aProps) {
                                                         return new RTCDataChannelEvent(aName, aProps);
                                                       },
                                             },
  RTCDTMFToneChangeEvent:                       { create: function (aName, aProps) {
                                                         return new RTCDTMFToneChangeEvent(aName, aProps);
                                                       },
                                             },
  RTCPeerConnectionIceEvent:                 { create: function (aName, aProps) {
                                                         return new RTCPeerConnectionIceEvent(aName, aProps);
                                                       },
                                             },
  RTCTrackEvent:                             {
                                               // Difficult to test required arguments.
                                             },
  ScrollAreaEvent:                           { create: function (aName, aProps) {
                                                         var e = document.createEvent("scrollareaevent");
                                                         e.initScrollAreaEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                               aProps.view, aProps.details,
                                                                               aProps.x || 0.0, aProps.y || 0.0,
                                                                               aProps.width || 0.0, aProps.height || 0.0);
                                                         return e;
                                                       },
                                             },
  ServiceWorkerMessageEvent:                 { create: function (aName, aProps) {
                                                         var e = new ServiceWorkerMessageEvent("serviceworkermessageevent", { bubbles: aProps.bubbles,
                                                             cancelable: aProps.cancelable, data: aProps.data, origin: aProps.origin,
                                                             lastEventId: aProps.lastEventId, source: aProps.source });
                                                         return e;
                                                       },
                                             },
  SimpleGestureEvent:                        { create: function (aName, aProps) {
                                                         var e = document.createEvent("simplegestureevent");
                                                         e.initSimpleGestureEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                                  aProps.view, aProps.detail,
                                                                                  aProps.screenX, aProps.screenY,
                                                                                  aProps.clientX, aProps.clientY,
                                                                                  aProps.ctrlKey, aProps.altKey, aProps.shiftKey, aProps.metaKey,
                                                                                  aProps.button, aProps.relatedTarget,
                                                                                  aProps.allowedDirections, aProps.direction, aProps.delta || 0.0,
                                                                                  aProps.clickCount);
                                                         return e;
                                                       },
                                             },
  SpeechRecognitionError:                    { create: function (aName, aProps) {
                                                         return new SpeechRecognitionError(aName, aProps);
                                                       },
                                             },
  SpeechRecognitionEvent:                    { create: function (aName, aProps) {
                                                         return new SpeechRecognitionEvent(aName, aProps);
                                                       },
                                             },
  SpeechSynthesisErrorEvent:                 { create: function (aName, aProps) {
                                                         aProps.error = "synthesis-unavailable";
                                                         aProps.utterance = new SpeechSynthesisUtterance("Hello World");
                                                         return new SpeechSynthesisErrorEvent(aName, aProps);
                                                       },
                                             },
  SpeechSynthesisEvent:                      { create: function (aName, aProps) {
                                                         aProps.utterance = new SpeechSynthesisUtterance("Hello World");
                                                         return new SpeechSynthesisEvent(aName, aProps);
                                                       },
                                             },
  StorageEvent:                              { create: function (aName, aProps) {
                                                         return new StorageEvent(aName, aProps);
                                                       },
                                             },
  StyleRuleChangeEvent:                      { create: function (aName, aProps) {
                                                         return new StyleRuleChangeEvent(aName, aProps);
                                                       },
                                               chromeOnly: true,
                                             },
  StyleSheetApplicableStateChangeEvent:      { create: function (aName, aProps) {
                                                         return new StyleSheetApplicableStateChangeEvent(aName, aProps);
                                                       },
                                               chromeOnly: true,
                                             },
  StyleSheetChangeEvent:                     { create: function (aName, aProps) {
                                                         return new StyleSheetChangeEvent(aName, aProps);
                                                       },
                                               chromeOnly: true,
                                             },
  SVGZoomEvent:                              { create: function (aName, aProps) {
                                                         var e = document.createEvent("svgzoomevent");
                                                         e.initUIEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                       aProps.view, aProps.detail);
                                                         return e;
                                                       },
                                             },
  TCPSocketErrorEvent:                       { create: function(aName, aProps) {
                                                         return new TCPSocketErrorEvent(aName, aProps);
                                                       },
                                             },
  TCPSocketEvent:                            { create: function(aName, aProps) {
                                                         return new TCPSocketEvent(aName, aProps);
                                                       },
                                             },
  TCPServerSocketEvent:                      { create: function(aName, aProps) {
                                                         return new TCPServerSocketEvent(aName, aProps);
                                                       },
                                             },
  TimeEvent:                                 { create: function (aName, aProps) {
                                                         var e = document.createEvent("timeevent");
                                                         e.initTimeEvent(aName, aProps.view, aProps.detail);
                                                         return e;
                                                       },
                                             },
  TouchEvent:                                { create: function (aName, aProps) {
                                                         var e = document.createEvent("touchevent");
                                                         e.initTouchEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                          aProps.view, aProps.detail,
                                                                          aProps.ctrlKey, aProps.altKey, aProps.shiftKey, aProps.metaKey,
                                                                          aProps.touches, aProps.targetTouches, aProps.changedTouches);
                                                         return e;
                                                       },
                                             },
  TrackEvent:                                { create: function (aName, aProps) {
                                                         return new TrackEvent(aName, aProps);
                                                       },
                                             },
  TransitionEvent:                           { create: function (aName, aProps) {
                                                         return new TransitionEvent(aName, aProps);
                                                       },
                                             },
  UIEvent:                                   { create: function (aName, aProps) {
                                                         return new UIEvent(aName, aProps);
                                                       },
                                             },
  UserProximityEvent:                        { create: function (aName, aProps) {
                                                         return new UserProximityEvent(aName, aProps);
                                                       },
                                             },
  USSDReceivedEvent:                         { create: function (aName, aProps) {
                                                          return new USSDReceivedEvent(aName, aProps);
                                                       },
                                             },
  WheelEvent:                                { create: function (aName, aProps) {
                                                         return new WheelEvent(aName, aProps);
                                                       },
                                             },
  WebGLContextEvent:                         { create: function (aName, aProps) {
                                                         return new WebGLContextEvent(aName, aProps);
                                                       },
                                             },
};

for (var name of Object.keys(kEventConstructors)) {
  if (!kEventConstructors[name].chromeOnly) {
    continue;
  }
  if (window[name]) {
    ok(false, name + " should be chrome only.");
  }
  window[name] = SpecialPowers.unwrap(SpecialPowers.wrap(window)[name]);
}

var props = Object.getOwnPropertyNames(window);
for (var i = 0; i < props.length; i++) {
  // Assume that event object must be named as "FooBarEvent".
  if (!props[i].match(/^([A-Z][a-zA-Z]+)?Event$/)) {
    continue;
  }
  if (!kEventConstructors[props[i]]) {
    ok(false, "Unknown event found: " + props[i]);
    continue;
  }
  if (!kEventConstructors[props[i]].create) {
    todo(false, "Cannot create untrusted event of " + props[i]);
    continue;
  }
  ok(true, "Creating " + props[i] + "...");
  var event = kEventConstructors[props[i]].create("foo", {});
  if (!event) {
    ok(false, "Failed to create untrusted event: " + props[i]);
    continue;
  }
  if (typeof(event.getModifierState) == "function") {
    const kModifiers = [ "Shift", "Control", "Alt", "AltGr", "Meta", "CapsLock", "ScrollLock", "NumLock", "OS", "Fn", "FnLock", "Symbol", "SymbolLock" ];
    for (var j = 0; j < kModifiers.length; j++) {
      ok(true, "Calling " + props[i] + ".getModifierState(" + kModifiers[j] + ")...");
      var modifierState = event.getModifierState(kModifiers[j]);
      ok(true, props[i] + ".getModifierState(" + kModifiers[j] + ") = " + modifierState);
    }
  }
}

</script>
</pre>
</body>
</html>