Backed out 4 changesets (bug 1137557) for causing intermittent Gij switching_test.js failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 24 Aug 2015 13:27:01 -0400
changeset 259068 aa51330c9e0982791b7995c303339ee386ea4172
parent 259067 6244c61498596b222755098e6f3210049747e76d
child 259069 44ffa68bc9d7009fbdb733cc117c6a58edcf817a
push id29268
push userryanvm@gmail.com
push dateTue, 25 Aug 2015 00:37:23 +0000
treeherdermozilla-central@08015770c9d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1137557
milestone43.0a1
backs outce86cf91f423417b4b6ca5842bca793817b3284a
83af10efcd3ced1f1ffaa202aeea7de03cf096f9
e48ed45d1c801dc8d41b6f731b532c29794223d2
81e93b60a622527acc1582ee5ee1e6899ec331ef
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1137557) for causing intermittent Gij switching_test.js failures. Backed out changeset ce86cf91f423 (bug 1137557) Backed out changeset 83af10efcd3c (bug 1137557) Backed out changeset e48ed45d1c80 (bug 1137557) Backed out changeset 81e93b60a622 (bug 1137557) CLOSED TREE
dom/base/TextInputProcessor.cpp
dom/base/TextInputProcessor.h
dom/base/test/chrome/window_nsITextInputProcessor.xul
dom/inputmethod/MozKeyboard.js
dom/inputmethod/forms.js
dom/inputmethod/mochitest/mochitest.ini
dom/inputmethod/mochitest/test_bug1137557.html
dom/interfaces/base/nsITextInputProcessor.idl
dom/webidl/InputMethod.webidl
widget/TextEventDispatcher.cpp
widget/TextEventDispatcher.h
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -1,15 +1,14 @@
 /* -*- 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/. */
 
-#include "gfxPrefs.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/TextEventDispatcher.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TextInputProcessor.h"
 #include "nsIDocShell.h"
 #include "nsIWidget.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
@@ -280,21 +279,18 @@ TextInputProcessor::MaybeDispatchKeydown
   // Modifier keys are not allowed because managing modifier state in this
   // method makes this messy.
   if (NS_WARN_IF(aKeyboardEvent->IsModifierKeyEvent())) {
     result.mResult = NS_ERROR_INVALID_ARG;
     result.mCanContinue = false;
     return result;
   }
 
-  uint32_t consumedFlags = 0;
-
   result.mResult = KeydownInternal(*aKeyboardEvent, aKeyFlags, false,
-                                   consumedFlags);
-  result.mDoDefault = !consumedFlags;
+                                   result.mDoDefault);
   if (NS_WARN_IF(NS_FAILED(result.mResult))) {
     result.mCanContinue = false;
     return result;
   }
 
   result.mCanContinue = NS_SUCCEEDED(IsValidStateForComposition());
   return result;
 }
@@ -753,68 +749,50 @@ TextInputProcessor::PrepareKeyboardEvent
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
                             uint32_t aKeyFlags,
                             uint8_t aOptionalArgc,
-                            uint32_t* aConsumedFlags)
+                            bool* aDoDefault)
 {
-  MOZ_RELEASE_ASSERT(aConsumedFlags, "aConsumedFlags must not be nullptr");
+  MOZ_RELEASE_ASSERT(aDoDefault, "aDoDefault must not be nullptr");
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   if (!aOptionalArgc) {
     aKeyFlags = 0;
   }
   if (NS_WARN_IF(!aDOMKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   WidgetKeyboardEvent* originalKeyEvent =
     aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   if (NS_WARN_IF(!originalKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
-  return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
-}
-
-TextEventDispatcher::DispatchTo
-TextInputProcessor::GetDispatchTo() const
-{
-  // Support asynchronous tests.
-  if (mForTests) {
-    return gfxPrefs::TestEventsAsyncEnabled() ?
-             TextEventDispatcher::eDispatchToParentProcess :
-             TextEventDispatcher::eDispatchToCurrentProcess;
-  }
-
-  // Otherwise, TextInputProcessor supports only keyboard apps on B2G.
-  // Keyboard apps on B2G doesn't want to dispatch keyboard events to
-  // chrome process. Therefore, this should dispatch key events only in
-  // the current process.
-  return TextEventDispatcher::eDispatchToCurrentProcess;
+  return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aDoDefault);
 }
 
 nsresult
 TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                                     uint32_t aKeyFlags,
                                     bool aAllowToDispatchKeypress,
-                                    uint32_t& aConsumedFlags)
+                                    bool& aDoDefault)
 {
-  aConsumedFlags = KEYEVENT_NOT_CONSUMED;
+  aDoDefault = false;
 
   // We shouldn't modify the internal WidgetKeyboardEvent.
   WidgetKeyboardEvent keyEvent(aKeyboardEvent);
   nsresult rv = PrepareKeyboardEventToDispatch(keyEvent, aKeyFlags);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  aConsumedFlags = (aKeyFlags & KEY_DEFAULT_PREVENTED) ? KEYDOWN_IS_CONSUMED :
-                                                         KEYEVENT_NOT_CONSUMED;
+  aDoDefault = !(aKeyFlags & KEY_DEFAULT_PREVENTED);
 
   if (WidgetKeyboardEvent::GetModifierForKeyName(keyEvent.mKeyNameIndex)) {
     ModifierKeyData modifierKeyData(keyEvent);
     if (WidgetKeyboardEvent::IsLockableModifier(keyEvent.mKeyNameIndex)) {
       // If the modifier key is lockable modifier key such as CapsLock,
       // let's toggle modifier key state at keydown.
       ToggleModifierKey(modifierKeyData);
     } else {
@@ -831,37 +809,29 @@ TextInputProcessor::KeydownInternal(cons
   keyEvent.modifiers = GetActiveModifiers();
 
   nsRefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
   rv = IsValidStateForComposition();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault :
-                                          nsEventStatus_eIgnore;
-  if (!mDispatcher->DispatchKeyboardEvent(NS_KEY_DOWN, keyEvent, status,
-                                          GetDispatchTo())) {
+  nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
+                                      nsEventStatus_eConsumeNoDefault;
+  if (!mDispatcher->DispatchKeyboardEvent(NS_KEY_DOWN, keyEvent, status)) {
     // If keydown event isn't dispatched, we don't need to dispatch keypress
     // events.
     return NS_OK;
   }
 
-  aConsumedFlags |=
-    (status == nsEventStatus_eConsumeNoDefault) ? KEYDOWN_IS_CONSUMED :
-                                                  KEYEVENT_NOT_CONSUMED;
-
-  if (aAllowToDispatchKeypress &&
-      mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status, 
-                                               GetDispatchTo())) {
-    aConsumedFlags |=
-      (status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED :
-                                                    KEYEVENT_NOT_CONSUMED;
+  if (aAllowToDispatchKeypress) {
+    mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status);
   }
 
+  aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::Keyup(nsIDOMKeyEvent* aDOMKeyEvent,
                           uint32_t aKeyFlags,
                           uint8_t aOptionalArgc,
                           bool* aDoDefault)
@@ -915,18 +885,17 @@ TextInputProcessor::KeyupInternal(const 
   nsRefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
   rv = IsValidStateForComposition();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
                                       nsEventStatus_eConsumeNoDefault;
-  mDispatcher->DispatchKeyboardEvent(NS_KEY_UP, keyEvent, status,
-                                     GetDispatchTo());
+  mDispatcher->DispatchKeyboardEvent(NS_KEY_UP, keyEvent, status);
   aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::GetModifierState(const nsAString& aModifierKeyName,
                                      bool* aActive)
 {
--- a/dom/base/TextInputProcessor.h
+++ b/dom/base/TextInputProcessor.h
@@ -4,25 +4,28 @@
  * 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_textinputprocessor_h_
 #define mozilla_dom_textinputprocessor_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
-#include "mozilla/TextEventDispatcher.h"
 #include "mozilla/TextEventDispatcherListener.h"
 #include "nsAutoPtr.h"
 #include "nsITextInputProcessor.h"
 #include "nsITextInputProcessorCallback.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
+namespace widget{
+class TextEventDispatcher;
+} // namespace widget
+
 class TextInputProcessor final : public nsITextInputProcessor
                                , public widget::TextEventDispatcherListener
 {
   typedef mozilla::widget::IMENotification IMENotification;
   typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
 
 public:
   TextInputProcessor();
@@ -52,21 +55,20 @@ private:
              const nsAString* aCommitString = nullptr,
              bool* aSucceeded = nullptr);
   nsresult CancelCompositionInternal(
              const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
              uint32_t aKeyFlags = 0);
   nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                            uint32_t aKeyFlags,
                            bool aAllowToDispatchKeypress,
-                           uint32_t& aConsumedFlags);
+                           bool& aDoDefault);
   nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                          uint32_t aKeyFlags,
                          bool& aDoDefault);
-  TextEventDispatcher::DispatchTo GetDispatchTo() const;
   nsresult IsValidStateForComposition();
   void UnlinkFromTextEventDispatcher();
   nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
                                           uint32_t aKeyFlags);
   bool IsValidEventTypeForComposition(
          const WidgetKeyboardEvent& aKeyboardEvent) const;
   nsresult PrepareKeyboardEventForComposition(
              nsIDOMKeyEvent* aDOMKeyEvent,
--- a/dom/base/test/chrome/window_nsITextInputProcessor.xul
+++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul
@@ -10,17 +10,17 @@
         src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 <body  xmlns="http://www.w3.org/1999/xhtml">
 <p id="display">
 <input id="input" type="text"/><br/>
 <iframe id="iframe" width="300" height="150"
         src="data:text/html,&lt;textarea id='textarea' cols='20' rows='4'&gt;&lt;/textarea&gt;"></iframe><br/>
 </p>
 <div id="content" style="display: none">
-
+  
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
@@ -2335,18 +2335,18 @@ function runKeyTests()
 
   // Printable key test:
   // Emulates pressing 'a' key.
   var keyA = new KeyboardEvent("", { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
 
   reset();
   var doDefaultKeydown = TIP.keydown(keyA);
 
-  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
-     description + "TIP.keydown(keyA) should return 0x02 because the keypress event should be consumed by the input element");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyA) should return false because the keypress event should be consumed by the input element");
   is(events.length, 2,
      description + "TIP.keydown(keyA) should cause keydown and keypress event");
   checkKeyAttrs("TIP.keydown(keyA)", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0 });
   checkKeyAttrs("TIP.keydown(keyA)", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
   is(input.value, "a",
      description + "input.value should be \"a\" which is inputted by TIP.keydown(keyA)");
@@ -2366,18 +2366,18 @@ function runKeyTests()
 
   // Non-printable key test:
   // Emulates pressing Enter key.
   var keyEnter = new KeyboardEvent("", { key: "Enter", code: "Enter" });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyEnter);
 
-  is(doDefaultKeydown, 0,
-     description + "TIP.keydown(keyEnter) should return 0");
+  ok(doDefaultKeydown,
+     description + "TIP.keydown(keyEnter) should return true");
   is(events.length, 2,
      description + "TIP.keydown(keyEnter) should cause keydown and keypress event");
   checkKeyAttrs("TIP.keydown(keyEnter)", events[0],
                 { type: "keydown",  key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
   checkKeyAttrs("TIP.keydown(keyEnter)", events[1],
                 { type: "keypress", key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
   is(input.value, "a",
      description + "input.value should stay \"a\" which was inputted by TIP.keydown(keyA)");
@@ -2397,18 +2397,18 @@ function runKeyTests()
 
   // KEY_DEFAULT_PREVENTED should cause defaultPrevented = true and not cause keypress event
   var keyB = new KeyboardEvent("", { key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED);
   doDefaultKeyup   = TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED);
 
-  is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
-     description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return 0x01 because it's marked as consumed at dispatching the event");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
   ok(!doDefaultKeyup,
      description + "TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
   is(events.length, 2,
      description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED) should cause keydown and keyup event");
   checkKeyAttrs("TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED)", events[0],
                 { type: "keydown", key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B, defaultPrevented: true });
   checkKeyAttrs("TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED)", events[1],
                 { type: "keyup",   key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B, defaultPrevented: true });
@@ -2418,17 +2418,17 @@ function runKeyTests()
   // Assume that KeyX causes inputting text "abc"
   input.value = "";
   var keyABC = new KeyboardEvent("", { key: "abc", code: "KeyX", keyCode: KeyboardEvent.DOM_VK_A });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyABC);
   doDefaultKeyup   = TIP.keyup(keyABC);
 
-  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
+  ok(!doDefaultKeydown,
      description + "TIP.keydown(keyABC) should return false because the keypress events should be consumed by the input element");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyABC) should return true");
   is(events.length, 5,
      description + "TIP.keydown(keyABC) and TIP.keyup(keyABC) should cause keydown, keypress, keypress, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyABC) and TIP.keyup(keyABC)", events[0],
                 { type: "keydown",  key: "abc",           code: "KeyX", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                   defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyABC) and TIP.keyup(keyABC)", events[1],
@@ -2445,18 +2445,18 @@ function runKeyTests()
   // If KEY_FORCE_PRINTABLE_KEY is specified, registered key names can be a printable key which inputs the specified value.
   input.value = "";
   var keyEnterPrintable = new KeyboardEvent("", { key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
   doDefaultKeyup   = TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
 
-  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
-     description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return 0x02 because the keypress events should be consumed by the input element");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return false because the keypress events should be consumed by the input element");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return true");
   is(events.length, 7,
      description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should cause keydown, keypress, keypress, keypress, keypress, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY)", events[0],
                 { type: "keydown",  key: "Enter",           code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN, charCode: 0,                    defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY)", events[1],
                 { type: "keypress", key: "Enter".charAt(0), code: "Enter", keyCode: 0,                           charCode: "Enter".charCodeAt(0), defaultPrevented: true });
@@ -2475,18 +2475,18 @@ function runKeyTests()
 
   // modifiers should be ignored.
   var keyWithModifiers = new KeyboardEvent("", { key: "Escape", code: "Escape", shiftKey: true, ctrlKey: true, altKey: true, metaKey: true });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyWithModifiers);
   doDefaultKeyup   = TIP.keyup(keyWithModifiers);
 
-  is(doDefaultKeydown, 0,
-     description + "TIP.keydown(keyWithModifiers) should return 0");
+  ok(doDefaultKeydown,
+     description + "TIP.keydown(keyWithModifiers) should return true");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyWithModifiers) should return true");
   is(events.length, 3,
      description + "TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers) should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[0],
                 { type: "keydown",  key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
   checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[1],
                 { type: "keypress", key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
@@ -2497,18 +2497,18 @@ function runKeyTests()
 
   // Call preventDefault() at keydown
   input.value = "";
   reset();
   doPreventDefaults = [ "keydown" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
-     description + "TIP.keydown(keyA) should return 0x01 because keydown event's preventDefault should be called");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyA) should return false because keydown event's preventDefault should be called");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyA) should return true");
   is(events.length, 2,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown should cause keydown and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, defaultPrevented: true });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown", events[1],
                 { type: "keyup",    key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, defaultPrevented: false });
@@ -2516,18 +2516,18 @@ function runKeyTests()
      description + "input.value shouldn't be modified by TIP.keyup(keyA) if the keydown event is consumed");
 
   // Call preventDefault() at keypress
   reset();
   doPreventDefaults = [ "keypress" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
-     description + "TIP.keydown(keyA) should return 0x02 because keypress event's preventDefault should be called");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyA) should return false because keypress event's preventDefault should be called");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyA) should return true");
   is(events.length, 3,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                 defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
@@ -2538,18 +2538,18 @@ function runKeyTests()
 
   // Call preventDefault() at keyup
   input.value = "";
   reset();
   doPreventDefaults = [ "keyup" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
-     description + "TIP.keydown(keyA) should return 0x02 because the key event should be consumed by the input element");
+  ok(!doDefaultKeydown,
+     description + "TIP.keydown(keyA) should return false because the key event should be consumed by the input element");
   ok(!doDefaultKeyup,
      description + "TIP.keyup(keyA) should return false because keyup event's preventDefault should be called");
   is(events.length, 3,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                 defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
--- a/dom/inputmethod/MozKeyboard.js
+++ b/dom/inputmethod/MozKeyboard.js
@@ -568,17 +568,17 @@ MozInputContext.prototype = {
 
     // Update context first before resolving promise to avoid race condition
     if (json.selectioninfo) {
       this.updateSelectionContext(json.selectioninfo, true);
     }
 
     switch (msg.name) {
       case "Keyboard:SendKey:Result:OK":
-        resolver.resolve(true);
+        resolver.resolve();
         break;
       case "Keyboard:SendKey:Result:Error":
         resolver.reject(json.error);
         break;
       case "Keyboard:GetText:Result:OK":
         resolver.resolve(json.text);
         break;
       case "Keyboard:GetText:Result:Error":
@@ -591,17 +591,17 @@ MozInputContext.prototype = {
         break;
       case "Keyboard:SequenceError":
         // Occurs when a new element got focus, but the inputContext was
         // not invalidated yet...
         resolver.reject("InputContext has expired");
         break;
       case "Keyboard:SetComposition:Result:OK": // Fall through.
       case "Keyboard:EndComposition:Result:OK":
-        resolver.resolve(true);
+        resolver.resolve();
         break;
       default:
         dump("Could not find a handler for " + msg.name);
         resolver.reject();
         break;
     }
   },
 
@@ -733,136 +733,60 @@ MozInputContext.prototype = {
       });
     });
   },
 
   deleteSurroundingText: function ic_deleteSurrText(offset, length) {
     return this.replaceSurroundingText(null, offset, length);
   },
 
-  sendKey: function ic_sendKey(dictOrKeyCode, charCode, modifiers, repeat) {
-    if (typeof dictOrKeyCode === 'number') {
-      // XXX: modifiers are ignored in this API method.
-
-      return this._sendPromise((resolverId) => {
-        cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
-          contextId: this._contextId,
-          requestId: resolverId,
-          method: 'sendKey',
-          keyCode: dictOrKeyCode,
-          charCode: charCode,
-          repeat: repeat
-        });
-      });
-    } else if (typeof dictOrKeyCode === 'object') {
-      return this._sendPromise((resolverId) => {
-        cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
-          contextId: this._contextId,
-          requestId: resolverId,
-          method: 'sendKey',
-          keyboardEventDict: this._getkeyboardEventDict(dictOrKeyCode)
-        });
-      });
-    } else {
-      // XXX: Should not reach here; implies WebIDL binding error.
-      throw new TypeError('Unknown argument passed.');
-    }
-  },
-
-  keydown: function ic_keydown(dict) {
-    return this._sendPromise((resolverId) => {
-      cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
-        contextId: this._contextId,
-         requestId: resolverId,
-        method: 'keydown',
-        keyboardEventDict: this._getkeyboardEventDict(dict)
-       });
-     });
-   },
-
-  keyup: function ic_keyup(dict) {
-    return this._sendPromise((resolverId) => {
-      cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
-        contextId: this._contextId,
+  sendKey: function ic_sendKey(keyCode, charCode, modifiers, repeat) {
+    let self = this;
+    return this._sendPromise(function(resolverId) {
+      cpmmSendAsyncMessageWithKbID(self, 'Keyboard:SendKey', {
+        contextId: self._contextId,
         requestId: resolverId,
-        method: 'keyup',
-        keyboardEventDict: this._getkeyboardEventDict(dict)
+        keyCode: keyCode,
+        charCode: charCode,
+        modifiers: modifiers,
+        repeat: repeat
       });
     });
   },
 
-  setComposition: function ic_setComposition(text, cursor, clauses, dict) {
+  setComposition: function ic_setComposition(text, cursor, clauses) {
     let self = this;
-    return this._sendPromise((resolverId) => {
+    return this._sendPromise(function(resolverId) {
       cpmmSendAsyncMessageWithKbID(self, 'Keyboard:SetComposition', {
         contextId: self._contextId,
         requestId: resolverId,
         text: text,
         cursor: (typeof cursor !== 'undefined') ? cursor : text.length,
-        clauses: clauses || null,
-        keyboardEventDict: this._getkeyboardEventDict(dict)
+        clauses: clauses || null
       });
     });
   },
 
-  endComposition: function ic_endComposition(text, dict) {
+  endComposition: function ic_endComposition(text) {
     let self = this;
-    return this._sendPromise((resolverId) => {
+    return this._sendPromise(function(resolverId) {
       cpmmSendAsyncMessageWithKbID(self, 'Keyboard:EndComposition', {
         contextId: self._contextId,
         requestId: resolverId,
-        text: text || '',
-        keyboardEventDict: this._getkeyboardEventDict(dict)
+        text: text || ''
       });
     });
   },
 
   _sendPromise: function(callback) {
     let self = this;
     return this._ipcHelper.createPromiseWithId(function(aResolverId) {
       if (!WindowMap.isActive(self._window)) {
         self._ipcHelper.removePromiseResolver(aResolverId);
         reject('Input method is not active.');
         return;
       }
       callback(aResolverId);
     });
-  },
-
-  // Take a MozInputMethodKeyboardEventDict dict, creates a keyboardEventDict
-  // object that can be sent to forms.js
-  _getkeyboardEventDict: function(dict) {
-    if (typeof dict !== 'object' || !dict.key) {
-      return;
-    }
-
-    var keyboardEventDict = {
-      key: dict.key,
-      code: dict.code,
-      repeat: dict.repeat,
-      flags: 0
-    };
-
-    if (dict.printable) {
-      keyboardEventDict.flags |=
-        Ci.nsITextInputProcessor.KEY_FORCE_PRINTABLE_KEY;
-    }
-
-    if (/^[a-zA-Z0-9]$/.test(dict.key)) {
-      // keyCode must follow the key value in this range;
-      // disregard the keyCode from content.
-      keyboardEventDict.keyCode = dict.key.toUpperCase().charCodeAt(0);
-    } else if (typeof dict.keyCode === 'number') {
-      // Allow keyCode to be specified for other key values.
-      keyboardEventDict.keyCode = dict.keyCode;
-
-      // Allow keyCode to be explicitly set to zero.
-      if (dict.keyCode === 0) {
-        keyboardEventDict.flags |=
-          Ci.nsITextInputProcessor.KEY_KEEP_KEYCODE_ZERO;
-      }
-    }
-
-    return keyboardEventDict;
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozInputMethod]);
--- a/dom/inputmethod/forms.js
+++ b/dom/inputmethod/forms.js
@@ -6,68 +6,27 @@
 
 "use strict";
 
 dump("###################################### forms.js loaded\n");
 
 let Ci = Components.interfaces;
 let Cc = Components.classes;
 let Cu = Components.utils;
-let Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyServiceGetter(Services, "fm",
                                    "@mozilla.org/focus-manager;1",
                                    "nsIFocusManager");
 
-/*
- * A WeakMap to map window to objects keeping it's TextInputProcessor instance.
- */
-let WindowMap = {
-  // WeakMap of <window, object> pairs.
-  _map: null,
-
-  /*
-   * Set the object associated to the window and return it.
-   */
-  _getObjForWin: function(win) {
-    if (!this._map) {
-      this._map = new WeakMap();
-    }
-    if (this._map.has(win)) {
-      return this._map.get(win);
-    } else {
-      let obj = {
-        tip: null
-      };
-      this._map.set(win, obj);
-
-      return obj;
-    }
-  },
-
-  getTextInputProcessor: function(win) {
-    if (!win) {
-      return;
-    }
-    let obj = this._getObjForWin(win);
-    let tip = obj.tip
-
-    if (!tip) {
-      tip = obj.tip = Cc["@mozilla.org/text-input-processor;1"]
-        .createInstance(Ci.nsITextInputProcessor);
-    }
-
-    if (!tip.beginInputTransaction(win, textInputProcessorCallback)) {
-      tip = obj.tip = null;
-    }
-    return tip;
-  }
-};
+XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
+  return content.QueryInterface(Ci.nsIInterfaceRequestor)
+                .getInterface(Ci.nsIDOMWindowUtils);
+});
 
 const RESIZE_SCROLL_DELAY = 20;
 // In content editable node, when there are hidden elements such as <br>, it
 // may need more than one (usually less than 3 times) move/extend operations
 // to change the selection range. If we cannot change the selection range
 // with more than 20 opertations, we are likely being blocked and cannot change
 // the selection range any more.
 const MAX_BLOCKED_COUNT = 20;
@@ -77,161 +36,16 @@ let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlE
 let HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
 let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
 let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
 let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
 let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
 let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
 let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
 
-function guessKeyNameFromKeyCode(KeyboardEvent, aKeyCode) {
-  switch (aKeyCode) {
-    case KeyboardEvent.DOM_VK_CANCEL:
-      return "Cancel";
-    case KeyboardEvent.DOM_VK_HELP:
-      return "Help";
-    case KeyboardEvent.DOM_VK_BACK_SPACE:
-      return "Backspace";
-    case KeyboardEvent.DOM_VK_TAB:
-      return "Tab";
-    case KeyboardEvent.DOM_VK_CLEAR:
-      return "Clear";
-    case KeyboardEvent.DOM_VK_RETURN:
-      return "Enter";
-    case KeyboardEvent.DOM_VK_SHIFT:
-      return "Shift";
-    case KeyboardEvent.DOM_VK_CONTROL:
-      return "Control";
-    case KeyboardEvent.DOM_VK_ALT:
-      return "Alt";
-    case KeyboardEvent.DOM_VK_PAUSE:
-      return "Pause";
-    case KeyboardEvent.DOM_VK_EISU:
-      return "Eisu";
-    case KeyboardEvent.DOM_VK_ESCAPE:
-      return "Escape";
-    case KeyboardEvent.DOM_VK_CONVERT:
-      return "Convert";
-    case KeyboardEvent.DOM_VK_NONCONVERT:
-      return "NonConvert";
-    case KeyboardEvent.DOM_VK_ACCEPT:
-      return "Accept";
-    case KeyboardEvent.DOM_VK_MODECHANGE:
-      return "ModeChange";
-    case KeyboardEvent.DOM_VK_PAGE_UP:
-      return "PageUp";
-    case KeyboardEvent.DOM_VK_PAGE_DOWN:
-      return "PageDown";
-    case KeyboardEvent.DOM_VK_END:
-      return "End";
-    case KeyboardEvent.DOM_VK_HOME:
-      return "Home";
-    case KeyboardEvent.DOM_VK_LEFT:
-      return "ArrowLeft";
-    case KeyboardEvent.DOM_VK_UP:
-      return "ArrowUp";
-    case KeyboardEvent.DOM_VK_RIGHT:
-      return "ArrowRight";
-    case KeyboardEvent.DOM_VK_DOWN:
-      return "ArrowDown";
-    case KeyboardEvent.DOM_VK_SELECT:
-      return "Select";
-    case KeyboardEvent.DOM_VK_PRINT:
-      return "Print";
-    case KeyboardEvent.DOM_VK_EXECUTE:
-      return "Execute";
-    case KeyboardEvent.DOM_VK_PRINTSCREEN:
-      return "PrintScreen";
-    case KeyboardEvent.DOM_VK_INSERT:
-      return "Insert";
-    case KeyboardEvent.DOM_VK_DELETE:
-      return "Delete";
-    case KeyboardEvent.DOM_VK_WIN:
-      return "OS";
-    case KeyboardEvent.DOM_VK_CONTEXT_MENU:
-      return "ContextMenu";
-    case KeyboardEvent.DOM_VK_SLEEP:
-      return "Standby";
-    case KeyboardEvent.DOM_VK_F1:
-      return "F1";
-    case KeyboardEvent.DOM_VK_F2:
-      return "F2";
-    case KeyboardEvent.DOM_VK_F3:
-      return "F3";
-    case KeyboardEvent.DOM_VK_F4:
-      return "F4";
-    case KeyboardEvent.DOM_VK_F5:
-      return "F5";
-    case KeyboardEvent.DOM_VK_F6:
-      return "F6";
-    case KeyboardEvent.DOM_VK_F7:
-      return "F7";
-    case KeyboardEvent.DOM_VK_F8:
-      return "F8";
-    case KeyboardEvent.DOM_VK_F9:
-      return "F9";
-    case KeyboardEvent.DOM_VK_F10:
-      return "F10";
-    case KeyboardEvent.DOM_VK_F11:
-      return "F11";
-    case KeyboardEvent.DOM_VK_F12:
-      return "F12";
-    case KeyboardEvent.DOM_VK_F13:
-      return "F13";
-    case KeyboardEvent.DOM_VK_F14:
-      return "F14";
-    case KeyboardEvent.DOM_VK_F15:
-      return "F15";
-    case KeyboardEvent.DOM_VK_F16:
-      return "F16";
-    case KeyboardEvent.DOM_VK_F17:
-      return "F17";
-    case KeyboardEvent.DOM_VK_F18:
-      return "F18";
-    case KeyboardEvent.DOM_VK_F19:
-      return "F19";
-    case KeyboardEvent.DOM_VK_F20:
-      return "F20";
-    case KeyboardEvent.DOM_VK_F21:
-      return "F21";
-    case KeyboardEvent.DOM_VK_F22:
-      return "F22";
-    case KeyboardEvent.DOM_VK_F23:
-      return "F23";
-    case KeyboardEvent.DOM_VK_F24:
-      return "F24";
-    case KeyboardEvent.DOM_VK_NUM_LOCK:
-      return "NumLock";
-    case KeyboardEvent.DOM_VK_SCROLL_LOCK:
-      return "ScrollLock";
-    case KeyboardEvent.DOM_VK_VOLUME_MUTE:
-      return "VolumeMute";
-    case KeyboardEvent.DOM_VK_VOLUME_DOWN:
-      return "VolumeDown";
-    case KeyboardEvent.DOM_VK_VOLUME_UP:
-      return "VolumeUp";
-    case KeyboardEvent.DOM_VK_META:
-      return "Meta";
-    case KeyboardEvent.DOM_VK_ALTGR:
-      return "AltGraph";
-    case KeyboardEvent.DOM_VK_ATTN:
-      return "Attn";
-    case KeyboardEvent.DOM_VK_CRSEL:
-      return "CrSel";
-    case KeyboardEvent.DOM_VK_EXSEL:
-      return "ExSel";
-    case KeyboardEvent.DOM_VK_EREOF:
-      return "EraseEof";
-    case KeyboardEvent.DOM_VK_PLAY:
-      return "Play";
-    default:
-      return "Unidentified";
-  }
-}
-
 let FormVisibility = {
   /**
    * Searches upwards in the DOM for an element that has been scrolled.
    *
    * @param {HTMLElement} node element to start search at.
    * @return {Window|HTMLElement|Null} null when none are found window/element otherwise.
    */
   findScrolled: function fv_findScrolled(node) {
@@ -365,51 +179,16 @@ let FormVisibility = {
       (parent !== parent.parent) &&
       (parent = parent.parent)
     );
 
     return visible;
   }
 };
 
-// This object implements nsITextInputProcessorCallback
-let textInputProcessorCallback = {
-  onNotify: function(aTextInputProcessor, aNotification) {
-    try {
-      switch (aNotification.type) {
-        case "request-to-commit":
-          // TODO: Send a notification through asyncMessage to the keyboard here.
-          aTextInputProcessor.commitComposition();
-
-          break;
-        case "request-to-cancel":
-          // TODO: Send a notification through asyncMessage to the keyboard here.
-          aTextInputProcessor.cancelComposition();
-
-          break;
-
-        case "notify-detached":
-          // TODO: Send a notification through asyncMessage to the keyboard here.
-          break;
-
-        // TODO: Manage _focusedElement for text input from here instead.
-        //       (except for <select> which will be need to handled elsewhere)
-        case "notify-focus":
-          break;
-
-        case "notify-blur":
-          break;
-      }
-    } catch (e) {
-      return false;
-    }
-    return true;
-  }
-};
-
 let FormAssistant = {
   init: function fa_init() {
     addEventListener("focus", this, true, false);
     addEventListener("blur", this, true, false);
     addEventListener("resize", this, true, false);
     // We should not blur the fucus if the submit event is cancelled,
     // therefore we are binding our event listener in the bubbling phase here.
     addEventListener("submit", this, false, false);
@@ -648,25 +427,25 @@ let FormAssistant = {
             if (this.focusedElement && !FormVisibility.isVisible(this.focusedElement)) {
               scrollSelectionOrElementIntoView(this.focusedElement);
             }
           }.bind(this), RESIZE_SCROLL_DELAY);
         }
         break;
 
       case "keydown":
-        if (!this.focusedElement || this._editing) {
+        if (!this.focusedElement) {
           break;
         }
 
         CompositionManager.endComposition('');
         break;
 
       case "keyup":
-        if (!this.focusedElement || this._editing) {
+        if (!this.focusedElement) {
           break;
         }
 
         CompositionManager.endComposition('');
         break;
 
       case "compositionend":
         if (!this.focusedElement) {
@@ -718,142 +497,44 @@ let FormAssistant = {
         event.initEvent('input', true, false);
         target.dispatchEvent(event);
         break;
       }
 
       case "Forms:Input:SendKey":
         CompositionManager.endComposition('');
 
-        let win = target.ownerDocument.defaultView;
-        let tip = WindowMap.getTextInputProcessor(win);
-        if (!tip) {
-          if (json.requestId) {
-            sendAsyncMessage("Forms:SendKey:Result:Error", {
-              requestId: json.requestId,
-              error: "Unable to start input transaction."
-            });
-          }
+        let flags = domWindowUtils.KEY_FLAG_NOT_SYNTHESIZED_FOR_TESTS;
+        this._editing = true;
+        let doKeypress = domWindowUtils.sendKeyEvent('keydown', json.keyCode,
+                                                     json.charCode, json.modifiers, flags);
+        if (doKeypress) {
+          domWindowUtils.sendKeyEvent('keypress', json.keyCode,
+                                      json.charCode, json.modifiers, flags);
+        }
 
-          break;
+        if(!json.repeat) {
+          domWindowUtils.sendKeyEvent('keyup', json.keyCode,
+                                      json.charCode, json.modifiers, flags);
         }
 
-        // If we receive a keyboardEventDict from json, that means the user
-        // is calling the method with the new arguments.
-        // Otherwise, we would have to construct our own keyboardEventDict
-        // based on legacy values we have received.
-        let keyboardEventDict = json.keyboardEventDict;
-        let flags = 0;
-
-        if (keyboardEventDict) {
-          if ('flags' in keyboardEventDict) {
-            flags = keyboardEventDict.flags;
-          }
-        } else {
-          // The naive way to figure out if the key to dispatch is printable.
-          let printable = !!json.charCode;
-
-          // For printable keys, the value should be the actual character.
-          // For non-printable keys, it should be a value in the D3E spec.
-          // Here we make some educated guess for it.
-          let key = printable ?
-              String.fromCharCode(json.charCode) :
-              guessKeyNameFromKeyCode(win.KeyboardEvent, json.keyCode);
-
-          // keyCode from content is only respected when the key is not an
-          // an alphanumeric character. We also ask TextInputProcessor not to
-          // infer this value for non-printable keys to keep the original
-          // behavior.
-          let keyCode = (printable && /^[a-zA-Z0-9]$/.test(key)) ?
-              key.toUpperCase().charCodeAt(0) :
-              json.keyCode;
-
-          keyboardEventDict = {
-            key: key,
-            keyCode: keyCode,
-            // We don't have any information to tell the virtual key the
-            // user have interacted with.
-            code: "",
-            // We do not have the information to infer location of the virtual key
-            // either (and we would need TextInputProcessor not to compute it).
-            location: 0,
-            // This indicates the key is triggered for repeats.
-            repeat: json.repeat
-          };
-
-          flags = tip.KEY_KEEP_KEY_LOCATION_STANDARD;
-          if (!printable) {
-            flags |= tip.KEY_NON_PRINTABLE_KEY;
-          }
-          if (!keyboardEventDict.keyCode) {
-            flags |= tip.KEY_KEEP_KEYCODE_ZERO;
-          }
-        }
-
-        let keyboardEvent = new win.KeyboardEvent("", keyboardEventDict);
+        this._editing = false;
 
-        let keydownDefaultPrevented = false;
-        try {
-          switch (json.method) {
-            case 'sendKey': {
-              let consumedFlags = tip.keydown(keyboardEvent, flags);
-              keydownDefaultPrevented =
-                !!(tip.KEYDOWN_IS_CONSUMED & consumedFlags);
-              if (!keyboardEventDict.repeat) {
-                tip.keyup(keyboardEvent, flags);
-              }
-              break;
-            }
-            case 'keydown': {
-              let consumedFlags = tip.keydown(keyboardEvent, flags);
-              keydownDefaultPrevented =
-                !!(tip.KEYDOWN_IS_CONSUMED & consumedFlags);
-              break;
-            }
-            case 'keyup': {
-              tip.keyup(keyboardEvent, flags);
-
-              break;
-            }
-          }
-        } catch (err) {
-          dump("forms.js:" + err.toString() + "\n");
-
-          if (json.requestId) {
-            if (err instanceof Ci.nsIException &&
-                err.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
-              sendAsyncMessage("Forms:SendKey:Result:Error", {
-                requestId: json.requestId,
-                error: "The values specified are illegal."
-              });
-            } else {
-              sendAsyncMessage("Forms:SendKey:Result:Error", {
-                requestId: json.requestId,
-                error: "Unable to type into destroyed input."
-              });
-            }
-          }
-
-          break;
+        if (json.requestId && doKeypress) {
+          sendAsyncMessage("Forms:SendKey:Result:OK", {
+            requestId: json.requestId,
+            selectioninfo: this.getSelectionInfo()
+          });
         }
-
-        if (json.requestId) {
-          if (keydownDefaultPrevented) {
-            sendAsyncMessage("Forms:SendKey:Result:Error", {
-              requestId: json.requestId,
-              error: "Key event(s) was cancelled."
-            });
-          } else {
-            sendAsyncMessage("Forms:SendKey:Result:OK", {
-              requestId: json.requestId,
-              selectioninfo: this.getSelectionInfo()
-            });
-          }
+        else if (json.requestId && !doKeypress) {
+          sendAsyncMessage("Forms:SendKey:Result:Error", {
+            requestId: json.requestId,
+            error: "Keydown event got canceled"
+          });
         }
-
         break;
 
       case "Forms:Select:Choice":
         let options = target.options;
         let valueChanged = false;
         if ("index" in json) {
           if (options.selectedIndex != json.index) {
             options.selectedIndex = json.index;
@@ -956,26 +637,26 @@ let FormAssistant = {
       case "Forms:GetContext": {
         let obj = getJSON(target, this._focusCounter);
         sendAsyncMessage("Forms:GetContext:Result:OK", obj);
         break;
       }
 
       case "Forms:SetComposition": {
         CompositionManager.setComposition(target, json.text, json.cursor,
-                                          json.clauses, json.keyboardEventDict);
+                                          json.clauses);
         sendAsyncMessage("Forms:SetComposition:Result:OK", {
           requestId: json.requestId,
           selectioninfo: this.getSelectionInfo()
         });
         break;
       }
 
       case "Forms:EndComposition": {
-        CompositionManager.endComposition(json.text, json.keyboardEventDict);
+        CompositionManager.endComposition(json.text);
         sendAsyncMessage("Forms:EndComposition:Result:OK", {
           requestId: json.requestId,
           selectioninfo: this.getSelectionInfo()
         });
         break;
       }
     }
     this._editing = false;
@@ -1484,30 +1165,57 @@ function replaceSurroundingText(element,
     // Insert the text to be replaced with.
     editor.insertText(text);
   }
   return true;
 }
 
 let CompositionManager =  {
   _isStarted: false,
-  _tip: null,
-  _KeyboardEventForWin: null,
+  _textInputProcessor: null,
   _clauseAttrMap: {
     'raw-input':
       Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE,
     'selected-raw-text':
       Ci.nsITextInputProcessor.ATTR_SELECTED_RAW_CLAUSE,
     'converted-text':
       Ci.nsITextInputProcessor.ATTR_CONVERTED_CLAUSE,
     'selected-converted-text':
       Ci.nsITextInputProcessor.ATTR_SELECTED_CLAUSE
   },
 
-  setComposition: function cm_setComposition(element, text, cursor, clauses, dict) {
+  _callback: function cm_callback(aTIP, aNotification)
+  {
+    try {
+      switch (aNotification.type) {
+        case "request-to-commit":
+          aTIP.commitComposition();
+          break;
+        case "request-to-cancel":
+          aTIP.cancelComposition();
+          break;
+      }
+    } catch (e) {
+      return false;
+    }
+    return true;
+  },
+
+  _prepareTextInputProcessor: function cm_prepareTextInputProcessor(aWindow)
+  {
+    if (!this._textInputProcessor) {
+      this._textInputProcessor =
+        Cc["@mozilla.org/text-input-processor;1"].
+          createInstance(Ci.nsITextInputProcessor);
+    }
+    return this._textInputProcessor.beginInputTransaction(aWindow,
+                                                          this._callback);
+  },
+
+  setComposition: function cm_setComposition(element, text, cursor, clauses) {
     // Check parameters.
     if (!element) {
       return;
     }
     let len = text.length;
     if (cursor > len) {
       cursor = len;
     }
@@ -1535,72 +1243,43 @@ let CompositionManager =  {
         clauseLens[clauseLens.length - 1] += remainingLength;
       }
     } else {
       clauseLens.push(len);
       clauseAttrs.push(Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE);
     }
 
     let win = element.ownerDocument.defaultView;
-    let tip = WindowMap.getTextInputProcessor(win);
-    if (!tip) {
+    if (!this._prepareTextInputProcessor(win)) {
       return;
     }
     // Update the composing text.
-    tip.setPendingCompositionString(text);
+    this._textInputProcessor.setPendingCompositionString(text);
     for (var i = 0; i < clauseLens.length; i++) {
       if (!clauseLens[i]) {
         continue;
       }
-      tip.appendClauseToPendingComposition(clauseLens[i], clauseAttrs[i]);
+      this._textInputProcessor.appendClauseToPendingComposition(clauseLens[i],
+                                                                clauseAttrs[i]);
     }
     if (cursor >= 0) {
-      tip.setCaretInPendingComposition(cursor);
+      this._textInputProcessor.setCaretInPendingComposition(cursor);
     }
-
-    if (!dict) {
-      this._isStarted = tip.flushPendingComposition();
-    } else {
-      let keyboardEvent = new win.KeyboardEvent("", dict);
-      let flags = dict.flags;
-      this._isStarted = tip.flushPendingComposition(keyboardEvent, flags);
-    }
-
-    if (this._isStarted) {
-      this._tip = tip;
-      this._KeyboardEventForWin = win.KeyboardEvent;
-    }
+    this._isStarted = this._textInputProcessor.flushPendingComposition();
   },
 
-  endComposition: function cm_endComposition(text, dict) {
+  endComposition: function cm_endComposition(text) {
     if (!this._isStarted) {
       return;
     }
-    let tip = this._tip;
-    if (!tip) {
-      return;
-    }
-
-    text = text || "";
-    if (!dict) {
-      tip.commitCompositionWith(text);
-    } else {
-      let keyboardEvent = new this._KeyboardEventForWin("", dict);
-      let flags = dict.flags;
-      tip.commitCompositionWith(text, keyboardEvent, flags);
-    }
-
+    this._textInputProcessor.commitCompositionWith(text ? text : "");
     this._isStarted = false;
-    this._tip = null;
-    this._KeyboardEventForWin = null;
   },
 
   // Composition ends due to external actions.
   onCompositionEnd: function cm_onCompositionEnd() {
     if (!this._isStarted) {
       return;
     }
 
     this._isStarted = false;
-    this._tip = null;
-    this._KeyboardEventForWin = null;
   }
 };
--- a/dom/inputmethod/mochitest/mochitest.ini
+++ b/dom/inputmethod/mochitest/mochitest.ini
@@ -21,9 +21,8 @@ support-files =
 [test_bug1059163.html]
 [test_bug1066515.html]
 [test_bug1175399.html]
 [test_sendkey_cancel.html]
 [test_sync_edit.html]
 [test_two_inputs.html]
 [test_two_selects.html]
 [test_unload.html]
-[test_bug1137557.html]
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1137557.html
+++ /dev/null
@@ -1,1674 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1137557
--->
-<head>
-  <title>Test for new API arguments accepting D3E properties</title>
-  <script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1137557">Mozilla Bug 1137557</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let gEventDetails = [];
-let gCurrentValue = '';
-let gTestDescription = '';
-
-let appFrameScript = function appFrameScript() {
-  let input = content.document.body.firstElementChild;
-
-  input.focus();
-
-  function sendEventDetail(evt) {
-    var eventDetail;
-
-    switch (evt.type) {
-      case 'compositionstart':
-      case 'compositionupdate':
-      case 'compositionend':
-        eventDetail = {
-          type: evt.type,
-          value: input.value,
-          data: evt.data
-        };
-        break;
-
-      case 'input':
-        eventDetail = {
-          type: evt.type,
-          value: input.value
-        };
-        break;
-
-      default: // keyboard events
-        eventDetail = {
-          type: evt.type,
-          charCode: evt.charCode,
-          keyCode: evt.keyCode,
-          key: evt.key,
-          code: evt.code,
-          location: evt.location,
-          repeat: evt.repeat,
-          value: input.value,
-          shift: evt.getModifierState('Shift'),
-          capsLock: evt.getModifierState('CapsLock'),
-          control: evt.getModifierState('Control'),
-          alt: evt.getModifierState('Alt')
-        };
-        break;
-    }
-
-    sendAsyncMessage('test:eventDetail', eventDetail);
-  }
-
-  input.addEventListener('compositionstart', sendEventDetail);
-  input.addEventListener('compositionupdate', sendEventDetail);
-  input.addEventListener('compositionend', sendEventDetail);
-  input.addEventListener('input', sendEventDetail);
-  input.addEventListener('keydown', sendEventDetail);
-  input.addEventListener('keypress', sendEventDetail);
-  input.addEventListener('keyup', sendEventDetail);
-};
-
-function waitForInputContextChange() {
-  return new Promise((resolve) => {
-    navigator.mozInputMethod.oninputcontextchange = resolve;
-  });
-}
-
-function assertEventDetail(expectedDetails, testName) {
-  is(gEventDetails.length, expectedDetails.length,
-    testName + ' expects ' + expectedDetails.map(d => d.type).join(', ') + ' events, got ' + gEventDetails.map(d => d.type).join(', '));
-
-  expectedDetails.forEach((expectedDetail, j) => {
-    for (let key in expectedDetail) {
-      is(gEventDetails[j][key], expectedDetail[key],
-        testName + ' expects ' + key + ' of ' + gEventDetails[j].type + ' to be equal to ' + expectedDetail[key]);
-    }
-  });
-}
-
-function sendKeyAndAssertResult(testdata) {
-  var dict = testdata.dict;
-  var testName = gTestDescription + 'sendKey(' + JSON.stringify(dict) + ')';
-  var promise = navigator.mozInputMethod.inputcontext.sendKey(dict);
-
-  if (testdata.expectedReject) {
-    promise = promise
-      .then(() => {
-        ok(false, testName + ' should not resolve.');
-      }, (e) => {
-        ok(true, testName + ' rejects.');
-        ok(e instanceof testdata.expectedReject, 'Reject with type.');
-      })
-
-    return promise;
-  }
-
-  promise = promise
-    .then((res) => {
-      is(res, true,
-        testName + ' should resolve to true.');
-
-      var expectedEventDetail = [];
-
-      var expectedValues = testdata.expectedValues;
-
-      expectedEventDetail.push({
-        type: 'keydown',
-        key: expectedValues.key,
-        charCode: 0,
-        code: expectedValues.code || '',
-        keyCode: expectedValues.keyCode || 0,
-        location: 0,
-        repeat: expectedValues.repeat || false,
-        value: gCurrentValue,
-        shift: false,
-        capsLock: false,
-        control: false,
-        alt: false
-      });
-
-      if (testdata.expectedKeypress) {
-        expectedEventDetail.push({
-          type: 'keypress',
-          key: expectedValues.key,
-          charCode: expectedValues.charCode,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      if (testdata.expectedInput) {
-        expectedEventDetail.push({
-          type: 'input',
-          value: gCurrentValue += testdata.expectedInput
-        });
-      }
-
-      if (!testdata.expectedRepeat) {
-        expectedEventDetail.push({
-          type: 'keyup',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      assertEventDetail(expectedEventDetail, testName);
-      gEventDetails = [];
-    }, (e) => {
-      ok(false, testName + ' should not reject. ' + e);
-    });
-
-  return promise;
-}
-
-function runSendKeyAlphabetTests() {
-  gTestDescription = 'runSendKeyAlphabetTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test the plain alphabets
-  var codeA = 'A'.charCodeAt(0);
-  for (var i = 0; i < 26; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = codeA + i;
-    let code = 'Key' + String.fromCharCode(keyCode);
-
-    [String.fromCharCode(keyCode),
-      String.fromCharCode(keyCode).toLowerCase()]
-    .forEach((chr) => {
-      // Test plain alphabet
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: '',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with keyCode set
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            keyCode: keyCode
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: '',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with keyCode set to keyCode + 1,
-      // expects keyCode to follow key value and ignore the incorrect value.
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            keyCode: keyCode + 1
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: '',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with code set
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            code: code
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: code,
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with code set to Digit1,
-      // expects keyCode to follow key value.
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            code: 'Digit1'
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: 'Digit1',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with keyCode set to DOM_VK_1,
-      // expects keyCode to follow key value.
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            keyCode: KeyboardEvent.DOM_VK_1
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: '',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test plain alphabet with code set to Digit1
-      // and keyCode set to DOM_VK_1,
-      // expects keyCode to follow key value.
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            code: 'Digit1',
-            keyCode: KeyboardEvent.DOM_VK_1
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: 'Digit1',
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyNumberTests() {
-  gTestDescription = 'runSendKeyNumberTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test numbers
-  var code0 = '0'.charCodeAt(0);
-  for (var i = 0; i < 10; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = code0 + i;
-    let chr = String.fromCharCode(keyCode);
-
-    // Test plain number
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain number with keyCode set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: keyCode
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain number with keyCode set to keyCode + 1,
-    // expects keyCode to follow key value and ignore the incorrect value.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: keyCode + 1
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain number with code set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'Digit' + chr
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'Digit' + chr,
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain upper caps alphabet with code set to KeyA,
-    // expects keyCode to follow key value.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA'
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain upper caps alphabet with code set to KeyA,
-    // and keyCode set to DOM_VK_A.
-    // expects keyCode to follow key value.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA',
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyDvorakTests() {
-  gTestDescription = 'runSendKeyDvorakTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test Dvorak layout emulation
-  var qwertyCodeForDvorakKeys = [
-    'KeyR', 'KeyT', 'KeyY', 'KeyU', 'KeyI', 'KeyO', 'KeyP',
-    'KeyA', 'KeyS', 'KeyD', 'KeyF', 'KeyG',
-    'KeyH', 'KeyJ', 'KeyK', 'KeyL', 'Semicolon',
-    'KeyX', 'KeyC', 'KeyV', 'KeyB', 'KeyN',
-    'KeyM', 'Comma', 'Period', 'Slash'];
-  var dvorakKeys = 'PYFGCRL' +
-    'AOEUIDHTNS' +
-    'QJKXBMWVZ';
-  for (var i = 0; i < dvorakKeys.length; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = dvorakKeys.charCodeAt(i);
-    let code = qwertyCodeForDvorakKeys[i];
-
-    [dvorakKeys.charAt(i), dvorakKeys.charAt(i).toLowerCase()]
-    .forEach((chr) => {
-      // Test alphabet with code set to Qwerty code,
-      // expects keyCode to follow key value.
-      // (This is *NOT* the expected scenario for emulating a Dvorak keyboard,
-      //  even though expected results are the same.)
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            code: code
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: code,
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test alphabet with code set to Qwerty code and keyCode set,
-      // expects keyCode to follow key/keyCode value.
-      // (This is the expected scenario for emulating a Dvorak keyboard)
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            keyCode: keyCode,
-            code: code
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: code,
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-    });
-  }
-
-  var qwertyCodeForDvorakSymbols = [
-    'Minus', 'Equal',
-    'KeyQ', 'KeyW', 'KeyE', 'BracketLeft', 'BracketRight', 'Backslash',
-    'Quote', 'KeyZ'];
-
-  var shiftDvorakSymbols = '{}\"<>?+|_:';
-  var dvorakSymbols = '[]\',./=\\-;';
-  var dvorakSymbolsKeyCodes = [
-    KeyboardEvent.DOM_VK_OPEN_BRACKET,
-    KeyboardEvent.DOM_VK_CLOSE_BRACKET,
-    KeyboardEvent.DOM_VK_QUOTE,
-    KeyboardEvent.DOM_VK_COMMA,
-    KeyboardEvent.DOM_VK_PERIOD,
-    KeyboardEvent.DOM_VK_SLASH,
-    KeyboardEvent.DOM_VK_EQUALS,
-    KeyboardEvent.DOM_VK_BACK_SLASH,
-    KeyboardEvent.DOM_VK_HYPHEN_MINUS,
-    KeyboardEvent.DOM_VK_SEMICOLON
-  ];
-
-  for (var i = 0; i < dvorakSymbols.length; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = dvorakSymbolsKeyCodes[i];
-    let code = qwertyCodeForDvorakSymbols[i];
-
-    [dvorakSymbols.charAt(i), shiftDvorakSymbols.charAt(i)]
-    .forEach((chr) => {
-      // Test symbols with code set to Qwerty code,
-      // expects keyCode to be 0.
-      // (This is *NOT* the expected scenario for emulating a Dvorak keyboard)
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            code: code
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: code,
-            keyCode: 0,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-
-      // Test alphabet with code set to Qwerty code and keyCode set,
-      // expects keyCode to follow keyCode value.
-      // (This is the expected scenario for emulating a Dvorak keyboard)
-      promiseQueue = promiseQueue.then(() => {
-        return sendKeyAndAssertResult({
-          dict: {
-            key: chr,
-            keyCode: keyCode,
-            code: code
-          },
-          expectedKeypress: true,
-          expectedInput: chr,
-          expectedValues: {
-            key: chr, code: code,
-            keyCode: keyCode,
-            charCode: chr.charCodeAt(0)
-          }
-        });
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyDigitKeySymbolsTests() {
-  gTestDescription = 'runSendKeyDigitKeySymbolsTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  var digitKeySymbols = ')!@#$%^&*(';
-  for (var i = 0; i < digitKeySymbols.length; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = KeyboardEvent['DOM_VK_' + i];
-    let chr = digitKeySymbols.charAt(i);
-    let code = 'Digit' + i;
-
-    // Test plain symbol
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '', keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with keyCode set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: keyCode
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: code
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: code,
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set to KeyA,
-    // expects keyCode to be 0.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA'
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with keyCode set to DOM_VK_A,
-    // expects keyCode to follow the keyCode set.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set to KeyA
-    // expects keyCode to follow the keyCode set.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA',
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyUSKeyboardSymbolsTests() {
-  gTestDescription = 'runSendKeyUSKeyboardSymbolsTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test printable symbols on US Keyboard
-  var symbols = ' ;:=+,<-_.>/?`~[{\\|]}\'\"';
-  var symbolKeyCodes = [
-    KeyboardEvent.DOM_VK_SPACE,
-    KeyboardEvent.DOM_VK_SEMICOLON,
-    KeyboardEvent.DOM_VK_SEMICOLON,
-    KeyboardEvent.DOM_VK_EQUALS,
-    KeyboardEvent.DOM_VK_EQUALS,
-    KeyboardEvent.DOM_VK_COMMA,
-    KeyboardEvent.DOM_VK_COMMA,
-    KeyboardEvent.DOM_VK_HYPHEN_MINUS,
-    KeyboardEvent.DOM_VK_HYPHEN_MINUS,
-    KeyboardEvent.DOM_VK_PERIOD,
-    KeyboardEvent.DOM_VK_PERIOD,
-    KeyboardEvent.DOM_VK_SLASH,
-    KeyboardEvent.DOM_VK_SLASH,
-    KeyboardEvent.DOM_VK_BACK_QUOTE,
-    KeyboardEvent.DOM_VK_BACK_QUOTE,
-    KeyboardEvent.DOM_VK_OPEN_BRACKET,
-    KeyboardEvent.DOM_VK_OPEN_BRACKET,
-    KeyboardEvent.DOM_VK_BACK_SLASH,
-    KeyboardEvent.DOM_VK_BACK_SLASH,
-    KeyboardEvent.DOM_VK_CLOSE_BRACKET,
-    KeyboardEvent.DOM_VK_CLOSE_BRACKET,
-    KeyboardEvent.DOM_VK_QUOTE,
-    KeyboardEvent.DOM_VK_QUOTE
-  ];
-  var symbolCodes = [
-    'Space',
-    'Semicolon',
-    'Semicolon',
-    'Equal',
-    'Equal',
-    'Comma',
-    'Comma',
-    'Minus',
-    'Minus',
-    'Period',
-    'Period',
-    'Slash',
-    'Slash',
-    'Backquote',
-    'Backquote',
-    'BracketLeft',
-    'BracketLeft',
-    'Backslash',
-    'Backslash',
-    'BracketRight',
-    'BracketRight',
-    'Quote',
-    'Quote'
-  ];
-  for (var i = 0; i < symbols.length; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = symbolKeyCodes[i];
-    let chr = symbols.charAt(i);
-    let code = symbolCodes[i];
-
-    // Test plain symbol
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with keyCode set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: keyCode
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set
-    // expects keyCode to be 0.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: code
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: code,
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set to KeyA,
-    // expects keyCode to be 0.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA'
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with keyCode set to DOM_VK_A,
-    // expects keyCode to follow the keyCode set.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain symbol with code set to KeyA
-    // expects keyCode to follow the keyCode set.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'KeyA',
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'KeyA',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyGreekLettersTests() {
-  gTestDescription = 'runSendKeyGreekLettersTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test Greek letters
-  var greekLetters =
-    '\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c' +
-    '\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9' +
-    '\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc' +
-    '\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9' +
-    '\u03c2';
-  var greekLettersLayoutMap =
-    'ABGDEZHUIKLMNJOPRSTYFXCVABGDEZHUIKLMNJOPRSTYFXCVQ';
-  for (var i = 0; i < greekLetters.length; i++) {
-    // callbacks in then() are deferred; must only reference these block-scoped
-    // variable instead of i.
-    let keyCode = greekLettersLayoutMap.charCodeAt(i);
-    let chr = greekLetters.charAt(i);
-    let code = 'Key' + greekLettersLayoutMap.charAt(i);
-
-    // Test plain alphabet
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain alphabet with keyCode set
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          keyCode: keyCode
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: '',
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain alphabet with code set,
-    // expects keyCode to be 0.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: code
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: code,
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain alphabet with code set to Digit1,
-    // expects keyCode to be 0.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'Digit1'
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'Digit1',
-          keyCode: 0,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-    // Test plain alphabet with code set to Digit1,
-    // and keyCode set to DOM_VK_A.
-    // expects keyCode to follow the keyCode set.
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: chr,
-          code: 'Digit1',
-          keyCode: KeyboardEvent.DOM_VK_A
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: 'Digit1',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-  }
-
-  return promiseQueue;
-}
-
-function runSendKeyEnterTests() {
-  gTestDescription = 'runSendKeyEnterTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test Enter with code unset
-  promiseQueue = promiseQueue.then(() => {
-    return sendKeyAndAssertResult({
-      dict: {
-        key: 'Enter'
-      },
-      expectedKeypress: true,
-      expectedInput: '\n',
-      expectedValues: {
-        key: 'Enter', code: '',
-        keyCode: KeyboardEvent.DOM_VK_RETURN,
-        charCode: 0
-      }
-    });
-  });
-
-  // Test Enter with code set
-  promiseQueue = promiseQueue.then(() => {
-    return sendKeyAndAssertResult({
-      dict: {
-        key: 'Enter',
-        code: 'Enter'
-      },
-      expectedKeypress: true,
-      expectedInput: '\n',
-      expectedValues: {
-        key: 'Enter', code: 'Enter',
-        keyCode: KeyboardEvent.DOM_VK_RETURN,
-        charCode: 0
-      }
-    });
-  });
-
-  // Test Enter with keyCode explict set to zero
-  promiseQueue = promiseQueue.then(() => {
-    return sendKeyAndAssertResult({
-      dict: {
-        key: 'Enter',
-        keyCode: 0
-      },
-      expectedKeypress: true,
-      expectedValues: {
-        key: 'Enter', code: '',
-        keyCode: 0,
-        charCode: 0
-      }
-    });
-  });
-
-  return promiseQueue;
-}
-
-function runSendKeyRejectionTests() {
-  gTestDescription = 'runSendKeyRejectionTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  promiseQueue = promiseQueue.then(() => {
-    return sendKeyAndAssertResult({
-      dict: undefined,
-      expectedReject: TypeError
-    });
-  });
-
-  return promiseQueue;
-}
-
-function setCompositionAndAssertResult(testdata) {
-  var dict = testdata.dict;
-  var testName;
-  var promise;
-
-  if (dict) {
-    testName = gTestDescription +
-      'setComposition(' + testdata.text +
-      ', undefined, undefined, '
-      + JSON.stringify(dict) + ')';
-    promise = navigator.mozInputMethod.inputcontext
-      .setComposition(testdata.text, undefined, undefined, dict);
-  } else {
-    testName = gTestDescription +
-      'setComposition(' + testdata.text + ')';
-    promise = navigator.mozInputMethod.inputcontext
-      .setComposition(testdata.text);
-  }
-
-  if (testdata.expectedReject) {
-    promise = promise
-      .then(() => {
-        ok(false, testName + ' should not resolve.');
-      }, (e) => {
-        ok(true, testName + ' rejects.');
-        ok(e instanceof testdata.expectedReject, 'Reject with type.');
-      })
-
-    return promise;
-  }
-
-  promise = promise
-    .then((res) => {
-      is(res, true,
-        testName + ' should resolve to true.');
-
-      var expectedEventDetail = [];
-
-      var expectedValues = testdata.expectedValues;
-
-      if (testdata.expectsKeyEvents &&
-          (testdata.startsComposition ||
-           testdata.dispatchKeyboardEventDuringComposition)) {
-        expectedEventDetail.push({
-          type: 'keydown',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      if (testdata.startsComposition) {
-        expectedEventDetail.push({
-          type: 'compositionstart',
-          data: '',
-          value: gCurrentValue
-        });
-      }
-
-      expectedEventDetail.push({
-        type: 'compositionupdate',
-        data: testdata.text,
-        value: gCurrentValue
-      });
-
-      expectedEventDetail.push({
-        type: 'input',
-        value: gCurrentValue += testdata.expectedInput
-      });
-
-      if (testdata.expectsKeyEvents &&
-          testdata.dispatchKeyboardEventDuringComposition) {
-        expectedEventDetail.push({
-          type: 'keyup',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      assertEventDetail(expectedEventDetail, testName);
-      gEventDetails = [];
-    }, (e) => {
-      ok(false, testName + ' should not reject. ' + e);
-    });
-
-  return promise;
-}
-
-function endCompositionAndAssertResult(testdata) {
-  var dict = testdata.dict;
-  var testName;
-  var promise;
-  if (dict) {
-    testName = gTestDescription +
-      'endComposition(' + testdata.text + ', ' + JSON.stringify(dict) + ')';
-    promise = navigator.mozInputMethod.inputcontext
-      .endComposition(testdata.text, dict);
-  } else {
-    testName = gTestDescription +
-      'endComposition(' + testdata.text + ')';
-    promise = navigator.mozInputMethod.inputcontext
-      .endComposition(testdata.text);
-  }
-
-  if (testdata.expectedReject) {
-    promise = promise
-      .then(() => {
-        ok(false, testName + ' should not resolve.');
-      }, (e) => {
-        ok(true, testName + ' rejects.');
-        ok(e instanceof testdata.expectedReject, 'Reject with type.');
-      })
-
-    return promise;
-  }
-
-  promise = promise
-    .then((res) => {
-      is(res, true,
-        testName + ' should resolve to true.');
-
-      var expectedEventDetail = [];
-
-      var expectedValues = testdata.expectedValues;
-
-      if (testdata.expectsKeyEvents &&
-          testdata.dispatchKeyboardEventDuringComposition) {
-        expectedEventDetail.push({
-          type: 'keydown',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      expectedEventDetail.push({
-        type: 'compositionend',
-        data: testdata.text,
-        value: gCurrentValue
-      });
-
-      expectedEventDetail.push({
-        type: 'input',
-        value: gCurrentValue
-      });
-
-      if (testdata.expectsKeyEvents) {
-        expectedEventDetail.push({
-          type: 'keyup',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      assertEventDetail(expectedEventDetail, testName);
-      gEventDetails = [];
-    }, (e) => {
-      ok(false, testName + ' should not reject. ' + e);
-    });
-
-  return promise;
-}
-
-function runCompositionWithKeyEventTests() {
-  var promiseQueue = Promise.resolve();
-
-  [true, false].forEach((dispatchKeyboardEventDuringComposition) => {
-    gTestDescription = 'runCompositionWithKeyEventTests() (dispatchKeyboardEvent =' + dispatchKeyboardEventDuringComposition + '): ';
-
-    promiseQueue = promiseQueue
-      .then(() => {
-        SpecialPowers.setBoolPref(
-          'dom.keyboardevent.dispatch_during_composition',
-          dispatchKeyboardEventDuringComposition);
-      })
-      .then(() => {
-        return setCompositionAndAssertResult({
-          text: 'foo',
-          expectsKeyEvents: true,
-          startsComposition: true,
-          dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
-          expectedInput: 'foo',
-          dict: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          },
-          expectedValues: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          }
-        });
-      })
-      .then(() => {
-        return setCompositionAndAssertResult({
-          text: 'foobar',
-          expectsKeyEvents: true,
-          startsComposition: false,
-          dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
-          expectedInput: 'bar',
-          dict: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          },
-          expectedValues: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          }
-        });
-      })
-      .then(() => {
-        return endCompositionAndAssertResult({
-          text: 'foobar',
-          expectsKeyEvents: true,
-          dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
-          expectedInput: '',
-          dict: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          },
-          expectedValues: {
-            key: 'a',
-            code: 'KeyA',
-            keyCode: KeyboardEvent.DOM_VK_A
-          }
-        });
-      })
-      .then(() => {
-        SpecialPowers.clearUserPref(
-          'dom.keyboardevent.dispatch_during_composition');
-      });
-  });
-
-  return promiseQueue;
-}
-
-function runCompositionWithoutKeyEventTests() {
-  var promiseQueue = Promise.resolve();
-
-  gTestDescription = 'runCompositionWithoutKeyEventTests(): ';
-
-  promiseQueue = promiseQueue
-    .then(() => {
-      return setCompositionAndAssertResult({
-        text: 'foo',
-        expectsKeyEvents: false,
-        startsComposition: true,
-        expectedInput: 'foo'
-      });
-    })
-    .then(() => {
-      return setCompositionAndAssertResult({
-        text: 'foobar',
-        expectsKeyEvents: false,
-        startsComposition: false,
-        expectedInput: 'bar'
-      });
-    })
-    .then(() => {
-      return endCompositionAndAssertResult({
-        text: 'foobar',
-        expectsKeyEvents: false,
-        expectedInput: ''
-      });
-    });
-
-  return promiseQueue;
-}
-
-function keydownAndAssertResult(testdata) {
-  var dict = testdata.dict;
-  var testName = gTestDescription + 'keydown(' + JSON.stringify(dict) + ')';
-  var promise = navigator.mozInputMethod.inputcontext.keydown(dict);
-
-  if (testdata.expectedReject) {
-    promise = promise
-      .then(() => {
-        ok(false, testName + ' should not resolve.');
-      }, (e) => {
-        ok(true, testName + ' rejects.');
-        ok(e instanceof testdata.expectedReject, 'Reject with type.');
-      })
-
-    return promise;
-  }
-
-  promise = promise
-    .then((res) => {
-      is(res, true,
-        testName + ' should resolve to true.');
-
-      var expectedEventDetail = [];
-
-      var expectedValues = testdata.expectedValues;
-
-      expectedEventDetail.push({
-        type: 'keydown',
-        key: expectedValues.key,
-        charCode: 0,
-        code: expectedValues.code || '',
-        keyCode: expectedValues.keyCode || 0,
-        location: 0,
-        repeat: expectedValues.repeat || false,
-        value: gCurrentValue,
-        shift: false,
-        capsLock: false,
-        control: false,
-        alt: false
-      });
-
-      if (testdata.expectedKeypress) {
-        expectedEventDetail.push({
-          type: 'keypress',
-          key: expectedValues.key,
-          charCode: expectedValues.charCode,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
-          location: 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      if (testdata.expectedInput) {
-        expectedEventDetail.push({
-          type: 'input',
-          value: gCurrentValue += testdata.expectedInput
-        });
-      }
-
-      assertEventDetail(expectedEventDetail, testName);
-      gEventDetails = [];
-    }, (e) => {
-      ok(false, testName + ' should not reject. ' + e);
-    });
-
-  return promise;
-}
-
-function keyupAndAssertResult(testdata) {
-  var dict = testdata.dict;
-  var testName = gTestDescription + 'keyup(' + JSON.stringify(dict) + ')';
-  var promise = navigator.mozInputMethod.inputcontext.keyup(dict);
-
-  if (testdata.expectedReject) {
-    promise = promise
-      .then(() => {
-        ok(false, testName + ' should not resolve.');
-      }, (e) => {
-        ok(true, testName + ' rejects.');
-        ok(e instanceof testdata.expectedReject, 'Reject with type.');
-      })
-
-    return promise;
-  }
-
-  promise = promise
-    .then((res) => {
-      is(res, true,
-        testName + ' should resolve to true.');
-
-      var expectedEventDetail = [];
-
-      var expectedValues = testdata.expectedValues;
-
-      expectedEventDetail.push({
-        type: 'keyup',
-        key: expectedValues.key,
-        charCode: 0,
-        code: expectedValues.code || '',
-        keyCode: expectedValues.keyCode || 0,
-        location: 0,
-        repeat: expectedValues.repeat || false,
-        value: gCurrentValue,
-        shift: false,
-        capsLock: false,
-        control: false,
-        alt: false
-      });
-
-      assertEventDetail(expectedEventDetail, testName);
-      gEventDetails = [];
-    }, (e) => {
-      ok(false, testName + ' should not reject. ' + e);
-    });
-
-  return promise;
-}
-
-function runKeyDownUpTests() {
-  gTestDescription = 'runKeyDownUpTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  let chr = 'a';
-  let code = 'KeyA';
-  let keyCode = KeyboardEvent.DOM_VK_A;
-
-  promiseQueue = promiseQueue
-    .then(() => {
-      return keydownAndAssertResult({
-        dict: {
-          key: chr,
-          code: code,
-          keyCode: keyCode
-        },
-        expectedKeypress: true,
-        expectedInput: chr,
-        expectedValues: {
-          key: chr, code: code,
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    })
-    .then(() => {
-      return keyupAndAssertResult({
-        dict: {
-          key: chr,
-          code: code,
-          keyCode: keyCode
-        },
-        expectedValues: {
-          key: chr, code: code,
-          keyCode: keyCode,
-          charCode: chr.charCodeAt(0)
-        }
-      });
-    });
-
-  return promiseQueue;
-}
-
-function runKeyDownUpRejectionTests() {
-  gTestDescription = 'runKeyDownUpRejectionTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  promiseQueue = promiseQueue.then(() => {
-    return keydownAndAssertResult({
-      dict: undefined,
-      expectedReject: TypeError
-    });
-  });
-
-  promiseQueue = promiseQueue.then(() => {
-    return keyupAndAssertResult({
-      dict: undefined,
-      expectedReject: TypeError
-    });
-  });
-
-  return promiseQueue;
-}
-
-function runRepeatTests() {
-  gTestDescription = 'runRepeatTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  // Test repeat
-  promiseQueue = promiseQueue
-    .then(() => {
-      return sendKeyAndAssertResult({
-        dict: {
-          key: 'A',
-          repeat: true
-        },
-        expectedKeypress: true,
-        expectedRepeat: true,
-        expectedInput: 'A',
-        expectedValues: {
-          repeat: true,
-          key: 'A', code: '',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: 'A'.charCodeAt(0)
-        }
-      });
-    })
-    .then(() => {
-      return keyupAndAssertResult({
-        dict: {
-          key: 'A'
-        },
-        expectedKeypress: true,
-        expectedRepeat: true,
-        expectedInput: 'A',
-        expectedValues: {
-          key: 'A', code: '',
-          keyCode: KeyboardEvent.DOM_VK_A,
-          charCode: 'A'.charCodeAt(0)
-        }
-      });
-    });
-
-  return promiseQueue;
-}
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'data:text/html,<html><body><textarea rows=30 cols=30></textarea></body></html>';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.addMessageListener('test:eventDetail', function(msg) {
-      gEventDetails.push(msg.data);
-    });
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-
-  waitForInputContextChange()
-    .then(() => {
-      var inputcontext = navigator.mozInputMethod.inputcontext;
-
-      ok(!!inputcontext, 'Receving the first input context');
-    })
-    .then(() => runSendKeyAlphabetTests())
-    .then(() => runSendKeyNumberTests())
-    .then(() => runSendKeyDvorakTests())
-    .then(() => runSendKeyDigitKeySymbolsTests())
-    .then(() => runSendKeyUSKeyboardSymbolsTests())
-    .then(() => runSendKeyGreekLettersTests())
-    .then(() => runSendKeyEnterTests())
-    .then(() => runSendKeyRejectionTests())
-    .then(() => runCompositionWithKeyEventTests())
-    .then(() => runCompositionWithoutKeyEventTests())
-    .then(() => runKeyDownUpTests())
-    .then(() => runKeyDownUpRejectionTests())
-    .then(() => runRepeatTests())
-    .catch((err) => {
-      console.error(err);
-      is(false, err.message);
-    })
-    .then(() => {
-      var p = waitForInputContextChange();
-
-      // Revoke our right from using the IM API.
-      SpecialPowers.wrap(im).setActive(false);
-
-      return p;
-    })
-    .then(() => {
-      var inputcontext = navigator.mozInputMethod.inputcontext;
-
-      is(inputcontext, null, 'Receving null input context');
-
-      inputmethod_cleanup();
-    })
-    .catch((err) => {
-      console.error(err);
-      is(false, err.message);
-    });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
--- a/dom/interfaces/base/nsITextInputProcessor.idl
+++ b/dom/interfaces/base/nsITextInputProcessor.idl
@@ -249,17 +249,17 @@ interface nsITextInputProcessorCallback;
  *
  *   // keyup of one of shift key doesn't cause inactivating "Shift" state.
  *   TIP.keyup(rightShift);
  *
  *   // This causes inactivating "Shift" state completely.
  *   TIP.keyup(leftShift);
  */
 
-[scriptable, builtinclass, uuid(581f6619-76ed-478c-905d-b8e6553a714a)]
+[scriptable, builtinclass, uuid(6617a9f6-3e16-4086-9e1e-c8a6c5d505c7)]
 interface nsITextInputProcessor : nsISupports
 {
   /**
    * Returns true if this instance was dispatched compositionstart but hasn't
    * dispatched compositionend yet.
    */
   readonly attribute boolean hasComposition;
 
@@ -484,22 +484,16 @@ interface nsITextInputProcessor : nsISup
   // non-zero value, this flag causes throwing an exception.
   const unsigned long KEY_KEEP_KEYCODE_ZERO                        = 0x00000010;
   // If KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT is specified when the key event is
   // a modifier key's, keydown() and keyup() only modifies its modifier state
   // without dispatching key events.  This is useful for testing odd behavior
   // or emulating legacy API behavior.
   const unsigned long KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT         = 0x00000020;
 
-  // These values can be used to do bitwise operation with the return value of
-  // the keydown() method.
-  const unsigned long KEYEVENT_NOT_CONSUMED                        = 0x00000000;
-  const unsigned long KEYDOWN_IS_CONSUMED                          = 0x00000001;
-  const unsigned long KEYPRESS_IS_CONSUMED                         = 0x00000002;
-
   /**
    * keydown() may dispatch a keydown event and some keypress events if
    * preceding keydown event isn't consumed and they are necessary.
    * Note that even if this is called during composition, key events may not
    * be dispatched.  In this case, this returns false.
    *
    * You should initialize at least .key value and .code value of the event.
    * Additionally, if you try to emulate a printable key, .keyCode value should
@@ -530,30 +524,23 @@ interface nsITextInputProcessor : nsISup
    *                        defined by any standards, use "" (empty string).
    *                        #4 .keyCode is guessed from .key value if the key
    *                        name is registered and .keyCode isn't initialized.
    *                        #5 modifier key states, e.g., .shiftKey, are
    *                        ignored.  Instead, modifier states are managed by
    *                        each instance and set automatically.
    * @param aKeyFlags       Special flags.  The values can be some of KEY_*
    *                        constants.
-   * @return                KEYEVENT_NOT_CONSUMED, if the keydown event nor
-   *                        the following keypress event(s) are consumed.
-   *                        KEYDOWN_IS_CONSUMED, if the keydown event is
-   *                        consumed. No keypress event will be dispatched in
-   *                        this case.
-   *                        KEYPRESS_IS_CONSUMED, if the keypress event(s) is
-   *                        consumed when dispatched.
-   *                        Note that keypress event is always consumed by
-   *                        native code for the printable keys (indicating the
-   *                        default action has been taken).
+   * @return                true if neither the keydown event or following
+   *                        keypress events is *not* consumed.
+   *                        Otherwise, i.e., preventDefault() is called, false.
    */
   [optional_argc]
-    unsigned long keydown(in nsIDOMKeyEvent aKeyboardEvent,
-                          [optional] in unsigned long aKeyFlags);
+    boolean keydown(in nsIDOMKeyEvent aKeyboardEvent,
+                    [optional] in unsigned long aKeyFlags);
 
   /**
    * Similar to keydown(), but this dispatches only a keyup event.
    */
   [optional_argc]
     boolean keyup(in nsIDOMKeyEvent aKeyboardEvent,
                   [optional] in unsigned long aKeyFlags);
 
--- a/dom/webidl/InputMethod.webidl
+++ b/dom/webidl/InputMethod.webidl
@@ -187,188 +187,79 @@ interface MozInputContext: EventTarget {
      *
      * A dict is provided in the detail property of the event containing the new values, and
      * an "ownAction" property to denote the event is the result of our own mutation to
      * the input field.
      */
     attribute EventHandler onsurroundingtextchange;
 
     /*
-     * Send a string/character with its key events. There are two ways of invocating 
-     * the method for backward compability purpose.
-     *
-     * (1) The recommended way, allow specifying DOM level 3 properties like |code|.
-     * @param dictOrKeyCode See MozInputMethodKeyboardEventDict.
-     * @param charCode disregarded
-     * @param modifiers disregarded
-     * @param repeat disregarded
-     *
-     * (2) Deprecated, reserved for backward compability.
-     * @param dictOrKeyCode keyCode of the key to send, should be one of the DOM_VK_ value in KeyboardEvent.
-     * @param charCode charCode of the character, should be 0 for non-printable keys.
-     * @param modifiers this paramater is no longer honored.
-     * @param repeat indicates whether a key would be sent repeatedly.
-     *
-     * @return A promise. Resolve to true if succeeds.
-     *                    Rejects to a string indicating the error.
-     *
-     * Note that, if you want to send a key n times repeatedly, make sure set
-     * parameter repeat to true and invoke sendKey n times, and invoke keyup
-     * after the end of the input.
-     */
-    Promise<boolean> sendKey((MozInputMethodRequiredKeyboardEventDict or long) dictOrKeyCode,
-                             optional long charCode, 
-                             optional long modifiers, 
-                             optional boolean repeat);
-
-    /*
-     * Send a string/character with keydown, and keypress events.
-     * keyup should be called afterwards to ensure properly sequence.
-     *
-     * @param dict See MozInputMethodKeyboardEventDict.
-     *
-     * @return A promise. Resolve to true if succeeds.
-     *                    Rejects to a string indicating the error.
-     */
-    Promise<boolean> keydown(MozInputMethodRequiredKeyboardEventDict dict);
-
-    /*
-     * Send a keyup event. keydown should be called first to ensure properly sequence.
-     *
-     * @param dict See MozInputMethodKeyboardEventDict.
-     *
-     * @return A promise. Resolve to true if succeeds.
-     *                    Rejects to a string indicating the error.
-     *
-     */
-    Promise<boolean> keyup(MozInputMethodRequiredKeyboardEventDict dict);
+      * send a character with its key events.
+      * @param modifiers see http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/base/nsIDOMWindowUtils.idl#206
+      * @param repeat indicates whether a key would be sent repeatedly.
+      * @return true if succeeds. Otherwise false if the input context becomes void.
+      * Alternative: sendKey(KeyboardEvent event), but we will likely
+      * waste memory for creating the KeyboardEvent object.
+      * Note that, if you want to send a key n times repeatedly, make sure set
+      * parameter repeat to true and invoke sendKey n-1 times, and then set
+      * repeat to false in the last invoke.
+      */
+    Promise<boolean> sendKey(long keyCode, long charCode, long modifiers, optional boolean repeat);
 
     /*
      * Set current composing text. This method will start composition or update
      * composition if it has started. The composition will be started right
      * before the cursor position and any selected text will be replaced by the
      * composing text. When the composition is started, calling this method can
      * update the text and move cursor winthin the range of the composing text.
      * @param text The new composition text to show.
      * @param cursor The new cursor position relative to the start of the
      * composition text. The cursor should be positioned within the composition
      * text. This means the value should be >= 0 and <= the length of
      * composition text. Defaults to the lenght of composition text, i.e., the
      * cursor will be positioned after the composition text.
      * @param clauses The array of composition clause information. If not set,
      * only one clause is supported.
-     * @param dict The properties of the keyboard event that cause the composition
-     * to set. keydown or keyup event will be fired if it's necessary.
-     * For compatibility, we recommend that you should always set this argument 
-     * if it's caused by a key operation.
-     * 
+     *
      * The composing text, which is shown with underlined style to distinguish
      * from the existing text, is used to compose non-ASCII characters from
      * keystrokes, e.g. Pinyin or Hiragana. The composing text is the
      * intermediate text to help input complex character and is not committed to
      * current input field. Therefore if any text operation other than
      * composition is performed, the composition will automatically end. Same
      * apply when the inputContext is lost during an unfinished composition
      * session.
      *
      * To finish composition and commit text to current input field, an IME
      * should call |endComposition|.
      */
-    Promise<boolean> setComposition(DOMString text, 
-                                    optional long cursor,
-                                    optional sequence<CompositionClauseParameters> clauses,
-                                    optional MozInputMethodKeyboardEventDict dict);
+    // XXXbz what is this promise resolved with?
+    Promise<any> setComposition(DOMString text, optional long cursor,
+                                optional sequence<CompositionClauseParameters> clauses);
 
     /*
      * End composition, clear the composing text and commit given text to
      * current input field. The text will be committed before the cursor
      * position.
      * @param text The text to commited before cursor position. If empty string
      * is given, no text will be committed.
-     * @param dict The properties of the keyboard event that cause the composition
-     * to end. keydown or keyup event will be fired if it's necessary.
-     * For compatibility, we recommend that you should always set this argument 
-     * if it's caused by a key operation.
      *
      * Note that composition always ends automatically with nothing to commit if
      * the composition does not explicitly end by calling |endComposition|, but
      * is interrupted by |sendKey|, |setSelectionRange|,
      * |replaceSurroundingText|, |deleteSurroundingText|, user moving the
      * cursor, changing the focus, etc.
      */
-    Promise<boolean> endComposition(optional DOMString text, 
-                                    optional MozInputMethodKeyboardEventDict dict);
+    // XXXbz what is this promise resolved with?
+    Promise<any> endComposition(optional DOMString text);
 };
 
 enum CompositionClauseSelectionType {
   "raw-input",
   "selected-raw-text",
   "converted-text",
   "selected-converted-text"
 };
 
 dictionary CompositionClauseParameters {
   DOMString selectionType = "raw-input";
   long length;
 };
-
-/*
- * A MozInputMethodKeyboardEventDictBase contains the following properties,
- * indicating the properties of the keyboard event caused.
- *
- * This is the base dictionary type for us to create two child types that could
- * be used as argument type in two types of methods, as WebIDL parser required.
- * 
- */
-dictionary MozInputMethodKeyboardEventDictBase {
-  /*
-   * String/character to output, or a registered name of non-printable key.
-   * (To be defined in the inheriting dictionary types.)
-   */
-  // DOMString key;
-  /*
-   * String/char indicating the virtual hardware key pressed. Optional.
-   * Must be a value defined in
-   * http://www.w3.org/TR/DOM-Level-3-Events-code/#keyboard-chording-virtual
-   * If your keyboard app emulates physical keyboard layout, this value should
-   * not be empty string. Otherwise, it should be empty string.
-   */
-  DOMString code = "";
-  /*
-   * keyCode of the keyboard event. Optional.
-   * To be disregarded if |key| is an alphanumeric character.
-   * If the key causes inputting a character and if your keyboard app emulates
-   * a physical keyboard layout, this value should be same as the value used
-   * by Firefox for desktop. If the key causes inputting an ASCII character
-   * but if your keyboard app doesn't emulate any physical keyboard layouts,
-   * the value should be proper value for the key value.
-   */
-  long? keyCode;
-  /*
-   * Indicates whether a key would be sent repeatedly. Optional.
-   */
-  boolean repeat = false;
-  /*
-   * Optional. True if |key| property is explicitly referring to a printable key.
-   * When this is set, key will be printable even if the |key| value matches any
-   * of the registered name of non-printable keys.
-   */
-  boolean printable = false;
-};
-
-/*
- * For methods like setComposition() and endComposition(), the optional
- * dictionary type argument is really optional when all of it's property
- * are optional.
- * This dictionary type is used to denote that argument.
- */
-dictionary MozInputMethodKeyboardEventDict : MozInputMethodKeyboardEventDictBase {
-  DOMString? key;
-};
-
-/*
- * For methods like keydown() and keyup(), the dictionary type argument is
- * considered required only if at least one of it's property is required.
- * This dictionary type is used to denote that argument.
- */
-dictionary MozInputMethodRequiredKeyboardEventDict : MozInputMethodKeyboardEventDictBase {
-  required DOMString key;
-};
--- a/widget/TextEventDispatcher.cpp
+++ b/widget/TextEventDispatcher.cpp
@@ -136,43 +136,25 @@ TextEventDispatcher::InitEvent(WidgetGUI
   aEvent.mFlags.mIsSynthesizedForTests = mForTests;
 }
 
 nsresult
 TextEventDispatcher::DispatchEvent(nsIWidget* aWidget,
                                    WidgetGUIEvent& aEvent,
                                    nsEventStatus& aStatus)
 {
-  MOZ_ASSERT(!aEvent.AsInputEvent(), "Use DispatchInputEvent()");
-
-  nsRefPtr<TextEventDispatcher> kungFuDeathGrip(this);
-  nsCOMPtr<nsIWidget> widget(aWidget);
-  mDispatchingEvent++;
-  nsresult rv = widget->DispatchEvent(&aEvent, aStatus);
-  mDispatchingEvent--;
-  return rv;
-}
-
-nsresult
-TextEventDispatcher::DispatchInputEvent(nsIWidget* aWidget,
-                                        WidgetInputEvent& aEvent,
-                                        nsEventStatus& aStatus,
-                                        DispatchTo aDispatchTo)
-{
   nsRefPtr<TextEventDispatcher> kungFuDeathGrip(this);
   nsCOMPtr<nsIWidget> widget(aWidget);
   mDispatchingEvent++;
 
-  // If the event is dispatched via nsIWidget::DispatchInputEvent(), it
-  // sends the event to the parent process first since APZ needs to handle it
-  // first.  However, some callers (e.g., keyboard apps on B2G and tests
-  // expecting synchronous dispatch) don't want this to do that.
   nsresult rv = NS_OK;
-  if (aDispatchTo == eDispatchToParentProcess) {
-    aStatus = widget->DispatchInputEvent(&aEvent);
+  if (aEvent.AsInputEvent() &&
+      (!aEvent.mFlags.mIsSynthesizedForTests || gfxPrefs::TestEventsAsyncEnabled()))
+  {
+    aStatus = widget->DispatchInputEvent(aEvent.AsInputEvent());
   } else {
     rv = widget->DispatchEvent(&aEvent, aStatus);
   }
 
   mDispatchingEvent--;
   return rv;
 }
 
@@ -299,29 +281,26 @@ TextEventDispatcher::NotifyIME(const IME
   }
   return rv;
 }
 
 bool
 TextEventDispatcher::DispatchKeyboardEvent(
                        uint32_t aMessage,
                        const WidgetKeyboardEvent& aKeyboardEvent,
-                       nsEventStatus& aStatus,
-                       DispatchTo aDispatchTo)
+                       nsEventStatus& aStatus)
 {
-  return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus,
-                                       aDispatchTo);
+  return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus);
 }
 
 bool
 TextEventDispatcher::DispatchKeyboardEventInternal(
                        uint32_t aMessage,
                        const WidgetKeyboardEvent& aKeyboardEvent,
                        nsEventStatus& aStatus,
-                       DispatchTo aDispatchTo,
                        uint32_t aIndexOfKeypress)
 {
   MOZ_ASSERT(aMessage == NS_KEY_DOWN || aMessage == NS_KEY_UP ||
              aMessage == NS_KEY_PRESS, "Invalid aMessage value");
   nsresult rv = GetState();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
@@ -390,25 +369,24 @@ TextEventDispatcher::DispatchKeyboardEve
   // XXX Currently, we don't support to dispatch key event with native key
   //     event information.
   keyEvent.mNativeKeyEvent = nullptr;
   // XXX Currently, we don't support to dispatch key events with data for
   // plugins.
   keyEvent.mPluginEvent.Clear();
   // TODO: Manage mUniqueId here.
 
-  DispatchInputEvent(mWidget, keyEvent, aStatus, aDispatchTo);
+  DispatchEvent(mWidget, keyEvent, aStatus);
   return true;
 }
 
 bool
 TextEventDispatcher::MaybeDispatchKeypressEvents(
                        const WidgetKeyboardEvent& aKeyboardEvent,
-                       nsEventStatus& aStatus,
-                       DispatchTo aDispatchTo)
+                       nsEventStatus& aStatus)
 {
   // If the key event was consumed, keypress event shouldn't be fired.
   if (aStatus == nsEventStatus_eConsumeNoDefault) {
     return false;
   }
 
   // If the key isn't a printable key or just inputting one character or
   // no character, we should dispatch only one keypress.  Otherwise, i.e.,
@@ -418,17 +396,17 @@ TextEventDispatcher::MaybeDispatchKeypre
     aKeyboardEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING ?
       1 : std::max(static_cast<nsAString::size_type>(1),
                    aKeyboardEvent.mKeyValue.Length());
   bool isDispatched = false;
   bool consumed = false;
   for (size_t i = 0; i < keypressCount; i++) {
     aStatus = nsEventStatus_eIgnore;
     if (!DispatchKeyboardEventInternal(NS_KEY_PRESS, aKeyboardEvent,
-                                       aStatus, aDispatchTo, i)) {
+                                       aStatus, i)) {
       // The widget must have been gone.
       break;
     }
     isDispatched = true;
     if (!consumed) {
       consumed = (aStatus == nsEventStatus_eConsumeNoDefault);
     }
   }
--- a/widget/TextEventDispatcher.h
+++ b/widget/TextEventDispatcher.h
@@ -175,76 +175,51 @@ public:
     mPendingComposition.Clear();
   }
 
   /**
    * @see nsIWidget::NotifyIME()
    */
   nsresult NotifyIME(const IMENotification& aIMENotification);
 
-
-  /**
-   * DispatchTo indicates whether the event may be dispatched to its parent
-   * process first (if there is) or not.  If the event is dispatched to the
-   * parent process, APZ will handle it first.  Otherwise, the event won't be
-   * handled by APZ if it's in a child process.
-   */
-  enum DispatchTo
-  {
-    // The event may be dispatched to its parent process if there is a parent.
-    // In such case, the event will be handled asynchronously.  Additionally,
-    // the event may be sent to its child process if a child process (including
-    // the dispatching process) has focus.
-    eDispatchToParentProcess = 0,
-    // The event must be dispatched in the current process.  But of course,
-    // the event may be sent to a child process when it has focus.  If there is
-    // no child process, the event may be handled synchronously.
-    eDispatchToCurrentProcess = 1
-  };
-
   /**
    * DispatchKeyboardEvent() maybe dispatches aKeyboardEvent.
    *
    * @param aMessage        Must be NS_KEY_DOWN or NS_KEY_UP.
    *                        Use MaybeDispatchKeypressEvents() for dispatching
    *                        NS_KEY_PRESS.
    * @param aKeyboardEvent  A keyboard event.
    * @param aStatus         If dispatching event should be marked as consumed,
    *                        set nsEventStatus_eConsumeNoDefault.  Otherwise,
    *                        set nsEventStatus_eIgnore.  After dispatching
    *                        a event and it's consumed this returns
    *                        nsEventStatus_eConsumeNoDefault.
-   * @param aDispatchTo     See comments of DispatchTo.
    * @return                true if an event is dispatched.  Otherwise, false.
    */
   bool DispatchKeyboardEvent(uint32_t aMessage,
                              const WidgetKeyboardEvent& aKeyboardEvent,
-                             nsEventStatus& aStatus,
-                             DispatchTo aDispatchTo = eDispatchToParentProcess);
+                             nsEventStatus& aStatus);
 
   /**
    * MaybeDispatchKeypressEvents() maybe dispatches a keypress event which is
    * generated from aKeydownEvent.
    *
    * @param aKeyboardEvent  A keyboard event.
    * @param aStatus         Sets the result when the caller dispatches
    *                        aKeyboardEvent.  Note that if the value is
    *                        nsEventStatus_eConsumeNoDefault, this does NOT
    *                        dispatch keypress events.
    *                        When this method dispatches one or more keypress
    *                        events and one of them is consumed, this returns
    *                        nsEventStatus_eConsumeNoDefault.
-   * @param aDispatchTo     See comments of DispatchTo.
    * @return                true if one or more events are dispatched.
    *                        Otherwise, false.
    */
   bool MaybeDispatchKeypressEvents(const WidgetKeyboardEvent& aKeyboardEvent,
-                                   nsEventStatus& aStatus,
-                                   DispatchTo aDispatchTo =
-                                     eDispatchToParentProcess);
+                                   nsEventStatus& aStatus);
 
 private:
   // mWidget is owner of the instance.  When this is created, this is set.
   // And when mWidget is released, this is cleared by OnDestroyWidget().
   // Note that mWidget may be destroyed already (i.e., mWidget->Destroyed() may
   // return true).
   nsIWidget* mWidget;
   // mListener is a weak reference to TextEventDispatcherListener.  That might
@@ -293,35 +268,24 @@ private:
              bool aForTests);
 
   /**
    * InitEvent() initializes aEvent.  This must be called before dispatching
    * the event.
    */
   void InitEvent(WidgetGUIEvent& aEvent) const;
 
-
   /**
    * DispatchEvent() dispatches aEvent on aWidget.
    */
   nsresult DispatchEvent(nsIWidget* aWidget,
                          WidgetGUIEvent& aEvent,
                          nsEventStatus& aStatus);
 
   /**
-   * DispatchInputEvent() dispatches aEvent on aWidget.
-   *
-   * @param aDispatchTo     See comments of DispatchTo.
-   */
-  nsresult DispatchInputEvent(nsIWidget* aWidget,
-                              WidgetInputEvent& aEvent,
-                              nsEventStatus& aStatus,
-                              DispatchTo aDispatchTo);
-
-  /**
    * StartCompositionAutomaticallyIfNecessary() starts composition if it hasn't
    * been started it yet.
    *
    * @param aStatus         If it succeeded to start composition normally, this
    *                        returns nsEventStatus_eIgnore.  Otherwise, e.g.,
    *                        the composition is canceled during dispatching
    *                        compositionstart event, this returns
    *                        nsEventStatus_eConsumeNoDefault.  In this case,
@@ -339,30 +303,27 @@ private:
    * @param aKeyboardEvent  A keyboard event.  If aMessage is NS_KEY_PRESS and
    *                        the event is for second or later character, its
    *                        mKeyValue should be empty string.
    * @param aStatus         If dispatching event should be marked as consumed,
    *                        set nsEventStatus_eConsumeNoDefault.  Otherwise,
    *                        set nsEventStatus_eIgnore.  After dispatching
    *                        a event and it's consumed this returns
    *                        nsEventStatus_eConsumeNoDefault.
-   * @param aDispatchTo     See comments of DispatchTo.
    * @param aIndexOfKeypress    This must be 0 if aMessage isn't NS_KEY_PRESS or
    *                            aKeyboard.mKeyNameIndex isn't
    *                            KEY_NAME_INDEX_USE_STRING.  Otherwise, i.e.,
    *                            when an NS_KEY_PRESS event causes inputting
    *                            text, this must be between 0 and
    *                            mKeyValue.Length() - 1 since keypress events
    *                            sending only one character per event.
    * @return                true if an event is dispatched.  Otherwise, false.
    */
   bool DispatchKeyboardEventInternal(uint32_t aMessage,
                                      const WidgetKeyboardEvent& aKeyboardEvent,
                                      nsEventStatus& aStatus,
-                                     DispatchTo aDispatchTo =
-                                       eDispatchToParentProcess,
                                      uint32_t aIndexOfKeypress = 0);
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif // #ifndef mozilla_widget_textcompositionsynthesizer_h_