Bug 1313169 - Remove dom/inputmethod/ and related code. r?ehsan draft
authorMichelangelo De Simone <mdesimone@mozilla.com>
Tue, 20 Dec 2016 16:32:12 -0800
changeset 453158 68a8aba095973284b2cda612f67255067227673e
parent 452993 8460203bc93b9667cea1bc00f9d9990a4b1a9474
child 540375 c097f09cf2bf3d63ea0b3fe8b0be29acf5a6dd98
push id39569
push userbmo:mdesimone@mozilla.com
push dateThu, 22 Dec 2016 21:39:43 +0000
reviewersehsan
bugs1313169
milestone53.0a1
Bug 1313169 - Remove dom/inputmethod/ and related code. r?ehsan MozReview-Commit-ID: 5jkBVon3ZSz
b2g/app/b2g.js
b2g/graphene/graphene.js
b2g/installer/package-manifest.in
browser/installer/package-manifest.in
dom/base/test/mozbrowser_api_utils.js
dom/browser-element/BrowserElementChild.js
dom/browser-element/BrowserElementChildPreload.js
dom/browser-element/BrowserElementParent.js
dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
dom/browser-element/mochitest/chrome.ini
dom/browser-element/mochitest/mochitest-oop.ini
dom/browser-element/mochitest/priority/chrome.ini
dom/browser-element/mochitest/priority/test_Keyboard.html
dom/browser-element/mochitest/test_browserElement_inproc_SetInputMethodActive.html
dom/browser-element/mochitest/test_browserElement_oop_SetInputMethodActive.html
dom/browser-element/nsIBrowserElementAPI.idl
dom/events/EventStateManager.cpp
dom/html/nsBrowserElement.cpp
dom/html/nsBrowserElement.h
dom/inputmethod/HardwareKeyHandler.cpp
dom/inputmethod/HardwareKeyHandler.h
dom/inputmethod/InputMethod.manifest
dom/inputmethod/Keyboard.jsm
dom/inputmethod/MozKeyboard.js
dom/inputmethod/forms.js
dom/inputmethod/jar.mn
dom/inputmethod/mochitest/bug1110030_helper.js
dom/inputmethod/mochitest/chrome.ini
dom/inputmethod/mochitest/file_blank.html
dom/inputmethod/mochitest/file_inputmethod.html
dom/inputmethod/mochitest/file_test_app.html
dom/inputmethod/mochitest/file_test_bug1066515.html
dom/inputmethod/mochitest/file_test_bug1137557.html
dom/inputmethod/mochitest/file_test_bug1175399.html
dom/inputmethod/mochitest/file_test_empty_app.html
dom/inputmethod/mochitest/file_test_focus_blur_manage_events.html
dom/inputmethod/mochitest/file_test_sendkey_cancel.html
dom/inputmethod/mochitest/file_test_setSupportsSwitching.html
dom/inputmethod/mochitest/file_test_simple_manage_events.html
dom/inputmethod/mochitest/file_test_sms_app.html
dom/inputmethod/mochitest/file_test_sms_app_1066515.html
dom/inputmethod/mochitest/file_test_sync_edit.html
dom/inputmethod/mochitest/file_test_two_inputs.html
dom/inputmethod/mochitest/file_test_two_selects.html
dom/inputmethod/mochitest/file_test_unload.html
dom/inputmethod/mochitest/file_test_unload_action.html
dom/inputmethod/mochitest/inputmethod_common.js
dom/inputmethod/mochitest/test_basic.html
dom/inputmethod/mochitest/test_bug1026997.html
dom/inputmethod/mochitest/test_bug1043828.html
dom/inputmethod/mochitest/test_bug1059163.html
dom/inputmethod/mochitest/test_bug1066515.html
dom/inputmethod/mochitest/test_bug1137557.html
dom/inputmethod/mochitest/test_bug1175399.html
dom/inputmethod/mochitest/test_bug944397.html
dom/inputmethod/mochitest/test_bug949059.html
dom/inputmethod/mochitest/test_bug953044.html
dom/inputmethod/mochitest/test_bug960946.html
dom/inputmethod/mochitest/test_bug978918.html
dom/inputmethod/mochitest/test_focus_blur_manage_events.html
dom/inputmethod/mochitest/test_forward_hardware_key_to_ime.html
dom/inputmethod/mochitest/test_input_registry_events.html
dom/inputmethod/mochitest/test_sendkey_cancel.html
dom/inputmethod/mochitest/test_setSupportsSwitching.html
dom/inputmethod/mochitest/test_simple_manage_events.html
dom/inputmethod/mochitest/test_sync_edit.html
dom/inputmethod/mochitest/test_two_inputs.html
dom/inputmethod/mochitest/test_two_selects.html
dom/inputmethod/mochitest/test_unload.html
dom/inputmethod/moz.build
dom/inputmethod/nsIHardwareKeyHandler.idl
dom/ipc/ContentParent.cpp
dom/ipc/ProcessPriorityManager.cpp
dom/moz.build
dom/webidl/BrowserElement.webidl
dom/webidl/InputMethod.webidl
dom/webidl/moz.build
layout/base/PresShell.cpp
layout/base/PresShell.h
layout/base/nsIPresShell.h
layout/build/nsLayoutModule.cpp
modules/libpref/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -803,19 +803,16 @@ pref("network.sntp.pools", // Servers se
      "0.pool.ntp.org;1.pool.ntp.org;2.pool.ntp.org;3.pool.ntp.org");
 pref("network.sntp.port", 123);
 pref("network.sntp.timeout", 30); // In seconds.
 
 // Allow ADB to run for this many hours before disabling.
 // 0 disables the timer.
 pref("b2g.adb.timeout-hours", 12);
 
-// InputMethod so we can do soft keyboards
-pref("dom.mozInputMethod.enabled", true);
-
 // Absolute path to the devtool unix domain socket file used
 // to communicate with a usb cable via adb forward
 pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
 
 // enable Skia/GL (OpenGL-accelerated 2D drawing) for large enough 2d canvases,
 // falling back to Skia/software for smaller canvases
 #ifdef MOZ_WIDGET_GONK
 pref("gfx.canvas.azure.backends", "skia");
--- a/b2g/graphene/graphene.js
+++ b/b2g/graphene/graphene.js
@@ -17,17 +17,16 @@ pref("browser.dom.window.dump.enabled", 
 pref("browser.ignoreNativeFrameTextSelection", false);
 pref("dom.meta-viewport.enabled", false);
 pref("full-screen-api.ignore-widgets", false);
 pref("image.high_quality_downscaling.enabled", true);
 pref("dom.w3c_touch_events.enabled", 0);
 pref("font.size.inflation.minTwips", 0);
 pref("browser.enable_click_image_resizing", true);
 pref("layout.css.scroll-snap.enabled", true);
-pref("dom.mozInputMethod.enabled", false);
 pref("browser.autofocus", true);
 pref("layers.async-pan-zoom.enabled", false);
 pref("network.predictor.enabled", true);
 
 // No AccessibleCaret
 pref("layout.accessiblecaret.enabled", false);
 
 // To be removed once bug 942756 is fixed.
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -547,23 +547,16 @@
 @RESPATH@/components/ActivityProxy.js
 @RESPATH@/components/ActivityRequestHandler.js
 @RESPATH@/components/ActivityWrapper.js
 @RESPATH@/components/ActivityMessageConfigurator.js
 
 @RESPATH@/components/DownloadsAPI.js
 @RESPATH@/components/DownloadsAPI.manifest
 
-; InputMethod API
-@RESPATH@/components/MozKeyboard.js
-@RESPATH@/components/InputMethod.manifest
-#ifdef MOZ_B2G
-@RESPATH@/components/inputmethod.xpt
-#endif
-
 @RESPATH@/components/SystemUpdate.manifest
 @RESPATH@/components/SystemUpdateManager.js
 
 #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
 @RESPATH@/components/TestInterfaceJS.js
 @RESPATH@/components/TestInterfaceJS.manifest
 @RESPATH@/components/TestInterfaceJSMaplike.js
 #endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -542,20 +542,16 @@
 
 @RESPATH@/components/PresentationDeviceInfoManager.manifest
 @RESPATH@/components/PresentationDeviceInfoManager.js
 @RESPATH@/components/BuiltinProviders.manifest
 @RESPATH@/components/PresentationControlService.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.manifest
 
-; InputMethod API
-@RESPATH@/components/MozKeyboard.js
-@RESPATH@/components/InputMethod.manifest
-
 #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
 @RESPATH@/components/TestInterfaceJS.js
 @RESPATH@/components/TestInterfaceJS.manifest
 @RESPATH@/components/TestInterfaceJSMaplike.js
 #endif
 
 ; [Extensions]
 @RESPATH@/components/extensions-toolkit.manifest
--- a/dom/base/test/mozbrowser_api_utils.js
+++ b/dom/base/test/mozbrowser_api_utils.js
@@ -15,17 +15,16 @@ const METHODS = {
   stop: {},
   download: {},
   purgeHistory: {},
   getScreenshot: {},
   zoom: {},
   getCanGoBack: {},
   getCanGoForward: {},
   getContentDimensions: {},
-  setInputMethodActive: {},
   findAll: {},
   findNext: {},
   clearMatch: {},
   executeScript: {},
   getWebManifest: {},
   mute: {},
   unmute: {},
   getMuted: {},
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -34,25 +34,16 @@ function isTopBrowserElement(docShell) {
 }
 
 var BrowserElementIsReady;
 
 debug(`Might load BE scripts: BEIR: ${BrowserElementIsReady}`);
 if (!BrowserElementIsReady) {
   debug("Loading BE scripts")
   if (!("BrowserElementIsPreloaded" in this)) {
-    if (isTopBrowserElement(docShell)) {
-      if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
-        try {
-          Services.scriptloader.loadSubScript("chrome://global/content/forms.js");
-        } catch (e) {
-        }
-      }
-    }
-
     if(Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
       // general content apps
       if (isTopBrowserElement(docShell)) {
         Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
       }
     } else {
       // rocketbar in system app and other in-process case (ex. B2G desktop client)
       Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -126,17 +126,16 @@ function BrowserElementChild() {
   // Our docShell is visible iff _forcedVisible and _ownerVisible are both
   // true.
   this._forcedVisible = true;
   this._ownerVisible = true;
 
   this._nextPaintHandler = null;
 
   this._isContentWindowCreated = false;
-  this._pendingSetInputMethodActive = [];
 
   this._init();
 };
 
 BrowserElementChild.prototype = {
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
@@ -307,17 +306,16 @@ BrowserElementChild.prototype = {
       "stop": this._recvStop,
       "zoom": this._recvZoom,
       "unblock-modal-prompt": this._recvStopWaiting,
       "fire-ctx-callback": this._recvFireCtxCallback,
       "owner-visibility-change": this._recvOwnerVisibilityChange,
       "entered-fullscreen": this._recvEnteredFullscreen,
       "exit-fullscreen": this._recvExitFullscreen,
       "activate-next-paint-listener": this._activateNextPaintListener,
-      "set-input-method-active": this._recvSetInputMethodActive,
       "deactivate-next-paint-listener": this._deactivateNextPaintListener,
       "find-all": this._recvFindAll,
       "find-next": this._recvFindNext,
       "clear-match": this._recvClearMatch,
       "execute-script": this._recvExecuteScript,
       "get-audio-channel-volume": this._recvGetAudioChannelVolume,
       "set-audio-channel-volume": this._recvSetAudioChannelVolume,
       "get-audio-channel-muted": this._recvGetAudioChannelMuted,
@@ -783,20 +781,16 @@ BrowserElementChild.prototype = {
 
     let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
     debug("Window created: " + uri.spec);
     if (uri.spec != "about:blank") {
       this._addMozAfterPaintHandler(function () {
         sendAsyncMsg('documentfirstpaint');
       });
       this._isContentWindowCreated = true;
-      // Handle pending SetInputMethodActive request.
-      while (this._pendingSetInputMethodActive.length > 0) {
-        this._recvSetInputMethodActive(this._pendingSetInputMethodActive.shift());
-      }
     }
   },
 
   _windowResizeHandler: function(e) {
     let win = e.target;
     if (win != content || e.defaultPrevented) {
       return;
     }
@@ -1502,41 +1496,16 @@ BrowserElementChild.prototype = {
     if (!this._finder) {
       debug("clearMach() called before findAll()");
       return;
     }
     this._finder.removeSelection();
     sendAsyncMsg("findchange", {active: false});
   },
 
-  _recvSetInputMethodActive: function(data) {
-    let msgData = { id: data.json.id };
-    if (!this._isContentWindowCreated) {
-      if (data.json.args.isActive) {
-        // To activate the input method, we should wait before the content
-        // window is ready.
-        this._pendingSetInputMethodActive.push(data);
-        return;
-      }
-      msgData.successRv = null;
-      sendAsyncMsg('got-set-input-method-active', msgData);
-      return;
-    }
-    // Unwrap to access webpage content.
-    let nav = XPCNativeWrapper.unwrap(content.document.defaultView.navigator);
-    if (nav.mozInputMethod) {
-      // Wrap to access the chrome-only attribute setActive.
-      new XPCNativeWrapper(nav.mozInputMethod).setActive(data.json.args.isActive);
-      msgData.successRv = null;
-    } else {
-      msgData.errorMsg = 'Cannot access mozInputMethod.';
-    }
-    sendAsyncMsg('got-set-input-method-active', msgData);
-  },
-
   // The docShell keeps a weak reference to the progress listener, so we need
   // to keep a strong ref to it ourselves.
   _progressListener: {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
                                            Ci.nsISupportsWeakReference]),
     _seenLoadStart: false,
 
     onLocationChange: function(webProgress, request, location, flags) {
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -61,17 +61,16 @@ function defineDOMRequestMethod(msgName)
 }
 
 function BrowserElementParent() {
   debug("Creating new BrowserElementParent object");
   this._domRequestCounter = 0;
   this._domRequestReady = false;
   this._pendingAPICalls = [];
   this._pendingDOMRequests = {};
-  this._pendingSetInputMethodActive = [];
   this._nextPaintListeners = [];
   this._pendingDOMFullscreen = false;
 
   Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
   Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
   Services.obs.addObserver(this, 'back-docommand', /* ownsWeak = */ true);
 }
 
@@ -892,31 +891,16 @@ BrowserElementParent.prototype = {
     };
     if (!this._domRequestReady) {
       this._pendingAPICalls.push(run);
     } else {
       run();
     }
   },
 
-  setInputMethodActive: function(isActive) {
-    if (!this._isAlive()) {
-      throw Components.Exception("Dead content process",
-                                 Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
-    }
-
-    if (typeof isActive !== 'boolean') {
-      throw Components.Exception("Invalid argument",
-                                 Cr.NS_ERROR_INVALID_ARG);
-    }
-
-    return this._sendDOMRequest('set-input-method-active',
-                                {isActive: isActive});
-  },
-
   getAudioChannelVolume: function(aAudioChannel) {
     return this._sendDOMRequest('get-audio-channel-volume',
                                 {audioChannel: aAudioChannel});
   },
 
   setAudioChannelVolume: function(aAudioChannel, aVolume) {
     return this._sendDOMRequest('set-audio-channel-volume',
                                 {audioChannel: aAudioChannel,
deleted file mode 100644
--- a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
+++ /dev/null
@@ -1,291 +0,0 @@
-/* Any copyright is dedicated to the public domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Bug 905573 - Add setInputMethodActive to browser elements to allow gaia
-// system set the active IME app.
-'use strict';
-
-SimpleTest.waitForExplicitFinish();
-browserElementTestHelpers.setEnabledPref(true);
-
-function setup() {
-  let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1']
-                .getService(SpecialPowers.Ci.nsIXULAppInfo);
-  if (appInfo.name != 'B2G') {
-    SpecialPowers.Cu.import("resource://gre/modules/Keyboard.jsm", window);
-  }
-
-  SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true);
-  SpecialPowers.addPermission('input-manage', true, document);
-}
-
-function tearDown() {
-  SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", false);
-  SpecialPowers.removePermission('input-manage', document);
-  SimpleTest.finish();
-}
-
-function runTest() {
-  createFrames();
-}
-
-var gInputMethodFrames = [];
-var gInputFrame;
-
-function createFrames() {
-  // Create two input method iframes.
-  let loadendCount = 0;
-  let countLoadend = function() {
-    loadendCount++;
-    if (loadendCount === 3) {
-      setPermissions();
-     }
-   };
-
-   // Create an input field to receive string from input method iframes.
-   gInputFrame = document.createElement('iframe');
-   gInputFrame.setAttribute('mozbrowser', 'true');
-   gInputFrame.src = 'file_browserElement_SetInputMethodActive.html';
-   document.body.appendChild(gInputFrame);
-   gInputFrame.addEventListener('mozbrowserloadend', countLoadend);
-
-   for (let i = 0; i < 2; i++) {
-     let frame = gInputMethodFrames[i] = document.createElement('iframe');
-     frame.setAttribute('mozbrowser', 'true');
-     frame.addEventListener('mozbrowserloadend', countLoadend);
-     frame.src = 'file_empty.html#' + i;
-     document.body.appendChild(frame);
-   }
- }
-
-function setPermissions() {
-  let permissions = [{
-    type: 'input',
-    allow: true,
-    context: {
-      url: SimpleTest.getTestFileURL('/file_empty.html'),
-      originAttributes: {
-        inIsolatedMozBrowser: true
-      }
-    }
-  }];
-
-  SpecialPowers.pushPermissions(permissions,
-    SimpleTest.waitForFocus.bind(SimpleTest, startTest));
-}
-
- function startTest() {
-  // The frame script running in the frame where the input is hosted.
-  let appFrameScript = function appFrameScript() {
-    let input = content.document.body.firstElementChild;
-    input.oninput = function() {
-      sendAsyncMessage('test:InputMethod:oninput', {
-        from: 'input',
-        value: this.value
-      });
-    };
-
-    input.onblur = function() {
-      // "Expected" lost of focus since the test is finished.
-      if (input.value === 'hello#0#1') {
-        return;
-      }
-
-      sendAsyncMessage('test:InputMethod:oninput', {
-        from: 'input',
-        error: true,
-        value: 'Unexpected lost of focus on the input frame!'
-      });
-    };
-
-    input.focus();
-  };
-
-  // Inject frame script to receive input.
-  let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame);
-  mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  mm.addMessageListener("test:InputMethod:oninput", next);
-
-  gInputMethodFrames.forEach((frame) => {
-    ok(frame.setInputMethodActive, 'Can access setInputMethodActive.');
-
-    // The frame script running in the input method frames.
-    let appFrameScript = function appFrameScript() {
-      let im = content.navigator.mozInputMethod;
-      im.oninputcontextchange = function() {
-        let ctx = im.inputcontext;
-        // Report back to parent frame on status of ctx gotten.
-        // (A setTimeout() here to ensure this always happens after
-        //  DOMRequest succeed.)
-        content.setTimeout(() => {
-          sendAsyncMessage('test:InputMethod:imFrameMessage', {
-            from: 'im',
-            value: content.location.hash + !!ctx
-          });
-        });
-
-        // If there is a context, send out the hash.
-        if (ctx) {
-          ctx.replaceSurroundingText(content.location.hash);
-        }
-      };
-    };
-
-    // Inject frame script to receive message.
-    let mm = SpecialPowers.getBrowserFrameMessageManager(frame);
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-    mm.addMessageListener("test:InputMethod:imFrameMessage", next);
-  });
-
-   // Set focus to the input field and wait for input methods' inputting.
-   SpecialPowers.DOMWindowUtils.focus(gInputFrame);
-
-  let req0 = gInputMethodFrames[0].setInputMethodActive(true);
-  req0.onsuccess = function() {
-    ok(true, 'setInputMethodActive succeeded (0).');
-  };
-
-  req0.onerror = function() {
-    ok(false, 'setInputMethodActive failed (0): ' + this.error.name);
-  };
-}
-
-var gCount = 0;
-
-var gFrameMsgCounts = {
-  'input': 0,
-  'im0': 0,
-  'im1': 0
-};
-
-function next(msg) {
-  let wrappedMsg = SpecialPowers.wrap(msg);
-  let from = wrappedMsg.data.from;
-  let value = wrappedMsg.data.value;
-
-  if (wrappedMsg.data.error) {
-    ok(false, wrappedMsg.data.value);
-
-    return;
-  }
-
-  let fromId = from;
-  if (from === 'im') {
-    fromId += value[1];
-  }
-  gFrameMsgCounts[fromId]++;
-
-  // The texts sent from the first and the second input method are '#0' and
-  // '#1' respectively.
-  switch (gCount) {
-    case 0:
-      switch (fromId) {
-        case 'im0':
-          if (gFrameMsgCounts.im0 === 1) {
-            is(value, '#0true', 'First frame should get the context first.');
-          } else {
-            ok(false, 'Unexpected multiple messages from im0.')
-          }
-
-          break;
-
-        case 'im1':
-          is(false, 'Shouldn\'t be hearing anything from second frame.');
-
-          break;
-
-        case 'input':
-          if (gFrameMsgCounts.input === 1) {
-            is(value, 'hello#0',
-              'Failed to get correct input from the first iframe.');
-          } else {
-            ok(false, 'Unexpected multiple messages from input.')
-          }
-
-          break;
-      }
-
-      if (gFrameMsgCounts.input !== 1 ||
-          gFrameMsgCounts.im0 !== 1 ||
-          gFrameMsgCounts.im1 !== 0) {
-        return;
-      }
-
-      gCount++;
-
-      let req0 = gInputMethodFrames[0].setInputMethodActive(false);
-      req0.onsuccess = function() {
-        ok(true, 'setInputMethodActive succeeded (0).');
-      };
-      req0.onerror = function() {
-        ok(false, 'setInputMethodActive failed (0): ' + this.error.name);
-      };
-      let req1 = gInputMethodFrames[1].setInputMethodActive(true);
-      req1.onsuccess = function() {
-        ok(true, 'setInputMethodActive succeeded (1).');
-      };
-      req1.onerror = function() {
-        ok(false, 'setInputMethodActive failed (1): ' + this.error.name);
-      };
-
-      break;
-
-    case 1:
-      switch (fromId) {
-        case 'im0':
-          if (gFrameMsgCounts.im0 === 2) {
-            is(value, '#0false', 'First frame should have the context removed.');
-          } else {
-            ok(false, 'Unexpected multiple messages from im0.')
-          }
-          break;
-
-        case 'im1':
-          if (gFrameMsgCounts.im1 === 1) {
-            is(value, '#1true', 'Second frame should get the context.');
-          } else {
-            ok(false, 'Unexpected multiple messages from im0.')
-          }
-
-          break;
-
-        case 'input':
-          if (gFrameMsgCounts.input === 2) {
-            is(value, 'hello#0#1',
-               'Failed to get correct input from the second iframe.');
-          } else {
-            ok(false, 'Unexpected multiple messages from input.')
-          }
-          break;
-      }
-
-      if (gFrameMsgCounts.input !== 2 ||
-          gFrameMsgCounts.im0 !== 2 ||
-          gFrameMsgCounts.im1 !== 1) {
-        return;
-      }
-
-      gCount++;
-
-      // Receive the second input from the second iframe.
-      // Deactive the second iframe.
-      let req3 = gInputMethodFrames[1].setInputMethodActive(false);
-      req3.onsuccess = function() {
-        ok(true, 'setInputMethodActive(false) succeeded (2).');
-      };
-      req3.onerror = function() {
-        ok(false, 'setInputMethodActive(false) failed (2): ' + this.error.name);
-      };
-      break;
-
-    case 2:
-      is(fromId, 'im1', 'Message sequence unexpected (3).');
-      is(value, '#1false', 'Second frame should have the context removed.');
-
-      tearDown();
-      break;
-  }
-}
-
-setup();
-addEventListener('testready', runTest);
--- a/dom/browser-element/mochitest/chrome.ini
+++ b/dom/browser-element/mochitest/chrome.ini
@@ -21,32 +21,30 @@ support-files =
   browserElement_GetScreenshot.js
   browserElement_GetScreenshotDppx.js
   browserElement_getWebManifest.js
   browserElement_NextPaint.js
   browserElement_NoAudioTrack.js
   browserElement_PurgeHistory.js
   browserElement_ReloadPostRequest.js
   browserElement_SendEvent.js
-  browserElement_SetInputMethodActive.js
   browserElement_SetVisible.js
   browserElement_SetVisibleFrames.js
   browserElement_SetVisibleFrames2.js
   browserElement_Stop.js
   browserElement_VisibilityChange.js
   file_audio.html
   file_browserElement_ActiveStateChange.html
   file_browserElement_AudioChannelSeeking.html
   file_browserElement_AudioChannel_nested.html
   file_browserElement_AudioChannelMutedByDefault.html
   file_browserElement_ExecuteScript.html
   file_browserElement_NextPaint.html
   file_browserElement_NoAudioTrack.html
   file_browserElement_SendEvent.html
-  file_browserElement_SetInputMethodActive.html
   file_browserElement_SetVisibleFrames2_Outer.html
   file_browserElement_SetVisibleFrames_Inner.html
   file_browserElement_SetVisibleFrames_Outer.html
   file_bug709759.sjs
   file_empty.html
   file_post_request.html
   file_web_manifest.html
   file_web_manifest.json
@@ -77,16 +75,13 @@ tags = audiochannel
 [test_browserElement_inproc_getWebManifest.html]
 [test_browserElement_inproc_NextPaint.html]
 [test_browserElement_inproc_NoAudioTrack.html]
 tags = audiochannel
 [test_browserElement_inproc_PurgeHistory.html]
 [test_browserElement_inproc_ReloadPostRequest.html]
 disabled = no modal prompt on POST reload for chrome window
 [test_browserElement_inproc_SendEvent.html]
-# The setInputMethodActive() tests will timed out on Android
-[test_browserElement_inproc_SetInputMethodActive.html]
-skip-if = (os == "android")
 [test_browserElement_inproc_SetVisible.html]
 [test_browserElement_inproc_SetVisibleFrames.html]
 [test_browserElement_inproc_SetVisibleFrames2.html]
 [test_browserElement_inproc_Stop.html]
 [test_browserElement_inproc_VisibilityChange.html]
--- a/dom/browser-element/mochitest/mochitest-oop.ini
+++ b/dom/browser-element/mochitest/mochitest-oop.ini
@@ -80,19 +80,16 @@ disabled = Disabling some OOP tests for 
 [test_browserElement_oop_ReloadPostRequest.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
 [test_browserElement_oop_RemoveBrowserElement.html]
 [test_browserElement_oop_ScrollEvent.html]
 [test_browserElement_oop_SecurityChange.html]
 skip-if = toolkit == 'android' #TIMED_OUT, bug 766586
 [test_browserElement_oop_SendEvent.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
-[test_browserElement_oop_SetInputMethodActive.html]
-# skip-if = (os == "android")
-disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
 [test_browserElement_oop_SetVisible.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
 [test_browserElement_oop_SetVisibleFrames.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
 [test_browserElement_oop_SetVisibleFrames2.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
 [test_browserElement_oop_Stop.html]
 disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
--- a/dom/browser-element/mochitest/priority/chrome.ini
+++ b/dom/browser-element/mochitest/priority/chrome.ini
@@ -8,12 +8,11 @@ support-files =
   file_WebGLContextLost.html
   silence.ogg
   !/dom/browser-element/mochitest/browserElementTestHelpers.js
   !/dom/browser-element/mochitest/file_empty.html
 
 [test_Activity.html]
 [test_Audio.html]
 [test_Background.html]
-[test_Keyboard.html]
 [test_MultipleFrames.html]
 [test_NestedFrames.html]
 [test_Visibility.html]
deleted file mode 100644
--- a/dom/browser-element/mochitest/priority/test_Keyboard.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-Test that frames with mozapptype=inputmethod gets the keyboard-specific
-priority level when in the foreground.
--->
-<head>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="../browserElementTestHelpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<script type="application/javascript;version=1.7">
-"use strict";
-
-SimpleTest.waitForExplicitFinish();
-browserElementTestHelpers.setEnabledPref(true);
-browserElementTestHelpers.enableProcessPriorityManager();
-
-function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', true);
-  iframe.setAttribute('mozapptype', 'inputmethod');
-  iframe.src = browserElementTestHelpers.emptyPage1;
-
-  var childID = null;
-  Promise.all([
-    expectOnlyOneProcessCreated('FOREGROUND_KEYBOARD').then(function(chid) {
-      childID = chid;
-    }),
-    expectMozbrowserEvent(iframe, 'loadend')
-  ]).then(function() {
-    var p = expectPriorityChange(childID, 'BACKGROUND');
-
-    /* We wait until mozbrowserloadend before calling setVisible, because
-     * setVisible isn't available until mozbrowser has loaded.  In practice,
-     * that means we can call setVisible once we've gotten /any/ mozbrowser
-     * event. */
-    iframe.setVisible(false);
-    return p;
-  }).then(function() {
-    var p = expectPriorityChange(childID, 'FOREGROUND_KEYBOARD');
-    iframe.setVisible(true);
-  }).then(SimpleTest.finish);
-
-  document.body.appendChild(iframe);
-}
-
-addEventListener('testready', runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/browser-element/mochitest/test_browserElement_inproc_SetInputMethodActive.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for Bug 905573</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<script type="application/javascript;version=1.7" src="browserElement_SetInputMethodActive.js">
-</script>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/browser-element/mochitest/test_browserElement_oop_SetInputMethodActive.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for Bug 905573</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<script type="application/javascript;version=1.7" src="browserElement_SetInputMethodActive.js">
-</script>
-</body>
-</html>
-
--- a/dom/browser-element/nsIBrowserElementAPI.idl
+++ b/dom/browser-element/nsIBrowserElementAPI.idl
@@ -87,18 +87,16 @@ interface nsIBrowserElementAPI : nsISupp
   nsIDOMDOMRequest getMuted();
 
   void setVolume(in float volume);
   nsIDOMDOMRequest getVolume();
 
   void addNextPaintListener(in nsIBrowserElementNextPaintListener listener);
   void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener);
 
-  nsIDOMDOMRequest setInputMethodActive(in boolean isActive);
-
   nsIDOMDOMRequest getAudioChannelVolume(in uint32_t audioChannel);
   nsIDOMDOMRequest setAudioChannelVolume(in uint32_t audioChannel, in float volume);
 
   nsIDOMDOMRequest getAudioChannelMuted(in uint32_t audioChannel);
   nsIDOMDOMRequest setAudioChannelMuted(in uint32_t audioChannel, in bool muted);
 
   nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
 
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -2827,18 +2827,17 @@ NodeAllowsClickThrough(nsINode* aNode)
 }
 #endif
 
 void
 EventStateManager::PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent,
                                            nsEventStatus& aStatus,
                                            bool dispatchedToContentProcess)
 {
-  if (aStatus == nsEventStatus_eConsumeNoDefault ||
-      aKeyboardEvent->mInputMethodAppState == WidgetKeyboardEvent::eHandling) {
+  if (aStatus == nsEventStatus_eConsumeNoDefault) {
     return;
   }
 
   // XXX Currently, our automated tests don't support mKeyNameIndex.
   //     Therefore, we still need to handle this with keyCode.
   switch(aKeyboardEvent->mKeyCode) {
     case NS_VK_TAB:
     case NS_VK_F6:
--- a/dom/html/nsBrowserElement.cpp
+++ b/dom/html/nsBrowserElement.cpp
@@ -452,37 +452,16 @@ nsBrowserElement::RemoveNextPaintListene
 
   nsresult rv = mBrowserElementAPI->RemoveNextPaintListener(listener);
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
   }
 }
 
-already_AddRefed<DOMRequest>
-nsBrowserElement::SetInputMethodActive(bool aIsActive,
-                                       ErrorResult& aRv)
-{
-  NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
-
-  nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv = mBrowserElementAPI->SetInputMethodActive(aIsActive,
-                                                         getter_AddRefs(req));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    if (rv == NS_ERROR_INVALID_ARG) {
-      aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    } else {
-      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    }
-    return nullptr;
-  }
-
-  return req.forget().downcast<DOMRequest>();
-}
-
 void
 nsBrowserElement::GetAllowedAudioChannels(
                  nsTArray<RefPtr<BrowserElementAudioChannel>>& aAudioChannels,
                  ErrorResult& aRv)
 {
   aAudioChannels.Clear();
 
   // If empty, it means that this is the first call of this method.
--- a/dom/html/nsBrowserElement.h
+++ b/dom/html/nsBrowserElement.h
@@ -100,19 +100,16 @@ public:
   void FindNext(dom::BrowserFindDirection aDirection, ErrorResult& aRv);
   void ClearMatch(ErrorResult& aRv);
 
   void AddNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
                             ErrorResult& aRv);
   void RemoveNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
                                ErrorResult& aRv);
 
-  already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
-                                                         ErrorResult& aRv);
-
   already_AddRefed<dom::DOMRequest> ExecuteScript(const nsAString& aScript,
                                                   const dom::BrowserElementExecuteScriptOptions& aOptions,
                                                   ErrorResult& aRv);
 
   already_AddRefed<dom::DOMRequest> GetWebManifest(ErrorResult& aRv);
 
   // Helper
   static void GenerateAllowedAudioChannels(
deleted file mode 100644
--- a/dom/inputmethod/HardwareKeyHandler.cpp
+++ /dev/null
@@ -1,526 +0,0 @@
-/* -*- 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 "HardwareKeyHandler.h"
-#include "mozilla/BasicEvents.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/KeyboardEvent.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/EventDispatcher.h"
-#include "mozilla/EventStateManager.h"
-#include "mozilla/PresShell.h"
-#include "mozilla/TextEvents.h"
-#include "nsDeque.h"
-#include "nsFocusManager.h"
-#include "nsFrameLoader.h"
-#include "nsIContent.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsPIDOMWindow.h"
-#include "nsPresContext.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-NS_IMPL_ISUPPORTS(HardwareKeyHandler, nsIHardwareKeyHandler)
-
-StaticRefPtr<HardwareKeyHandler> HardwareKeyHandler::sInstance;
-
-HardwareKeyHandler::HardwareKeyHandler()
-  : mInputMethodAppConnected(false)
-{
-}
-
-HardwareKeyHandler::~HardwareKeyHandler()
-{
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnInputMethodAppConnected()
-{
-  if (NS_WARN_IF(mInputMethodAppConnected)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  mInputMethodAppConnected = true;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnInputMethodAppDisconnected()
-{
-  if (NS_WARN_IF(!mInputMethodAppConnected)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  mInputMethodAppConnected = false;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::RegisterListener(nsIHardwareKeyEventListener* aListener)
-{
-  // Make sure the listener is not nullptr and there is no available
-  // hardwareKeyEventListener now
-  if (NS_WARN_IF(!aListener)) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  if (NS_WARN_IF(mHardwareKeyEventListener)) {
-    return NS_ERROR_ALREADY_INITIALIZED;
-  }
-
-  mHardwareKeyEventListener = do_GetWeakReference(aListener);
-
-  if (NS_WARN_IF(!mHardwareKeyEventListener)) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::UnregisterListener()
-{
-  // Clear the HardwareKeyEventListener
-  mHardwareKeyEventListener = nullptr;
-  return NS_OK;
-}
-
-bool
-HardwareKeyHandler::ForwardKeyToInputMethodApp(nsINode* aTarget,
-                                               WidgetKeyboardEvent* aEvent,
-                                               nsEventStatus* aEventStatus)
-{
-  MOZ_ASSERT(aTarget, "No target provided");
-  MOZ_ASSERT(aEvent, "No event provided");
-
-  // No need to forward hardware key event to IME
-  // if key's defaultPrevented is true
-  if (aEvent->mFlags.mDefaultPrevented) {
-    return false;
-  }
-
-  // No need to forward hardware key event to IME if IME is disabled
-  if (!mInputMethodAppConnected) {
-    return false;
-  }
-
-  // No need to forward hardware key event to IME
-  // if this key event is generated by IME itself(from nsITextInputProcessor)
-  if (aEvent->mIsSynthesizedByTIP) {
-    return false;
-  }
-
-  // No need to forward hardware key event to IME
-  // if the key event is handling or already handled
-  if (aEvent->mInputMethodAppState != WidgetKeyboardEvent::eNotHandled) {
-    return false;
-  }
-
-  // No need to forward hardware key event to IME
-  // if there is no nsIHardwareKeyEventListener in use
-  nsCOMPtr<nsIHardwareKeyEventListener>
-    keyHandler(do_QueryReferent(mHardwareKeyEventListener));
-  if (!keyHandler) {
-    return false;
-  }
-
-  // Set the flags to specify the keyboard event is in forwarding phase.
-  aEvent->mInputMethodAppState = WidgetKeyboardEvent::eHandling;
-
-  // For those keypress events coming after their heading keydown's reply
-  // already arrives, they should be dispatched directly instead of
-  // being stored into the event queue. Otherwise, without the heading keydown
-  // in the event queue, the stored keypress will never be withdrawn to be fired.
-  if (aEvent->mMessage == eKeyPress && mEventQueue.IsEmpty()) {
-    DispatchKeyPress(aTarget, *aEvent, *aEventStatus);
-    return true;
-  }
-
-  // Push the key event into queue for reuse when its reply arrives.
-  KeyboardInfo* copiedInfo =
-    new KeyboardInfo(aTarget,
-                     *aEvent,
-                     aEventStatus ? *aEventStatus : nsEventStatus_eIgnore);
-
-  // No need to forward hardware key event to IME if the event queue is full
-  if (!mEventQueue.Push(copiedInfo)) {
-    delete copiedInfo;
-    return false;
-  }
-
-  // We only forward keydown and keyup event to input-method-app
-  // because input-method-app will generate keypress by itself.
-  if (aEvent->mMessage == eKeyPress) {
-    return true;
-  }
-
-  // Create a keyboard event to pass into
-  // nsIHardwareKeyEventListener.onHardwareKey
-  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
-  nsPresContext* presContext = GetPresContext(aTarget);
-  RefPtr<KeyboardEvent> keyboardEvent =
-    NS_NewDOMKeyboardEvent(eventTarget, presContext, aEvent->AsKeyboardEvent());
-  // Duplicate the internal event data in the heap for the keyboardEvent,
-  // or the internal data from |aEvent| in the stack may be destroyed by others.
-  keyboardEvent->DuplicatePrivateData();
-
-  // Forward the created keyboard event to input-method-app
-  bool isSent = false;
-  keyHandler->OnHardwareKey(keyboardEvent, &isSent);
-
-  // Pop the pending key event if it can't be forwarded
-  if (!isSent) {
-    mEventQueue.RemoveFront();
-  }
-
-  return isSent;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnHandledByInputMethodApp(const nsAString& aType,
-                                              uint16_t aDefaultPrevented)
-{
-  // We can not handle this reply because the pending events had been already
-  // removed from the forwarding queue before this reply arrives.
-  if (mEventQueue.IsEmpty()) {
-    return NS_OK;
-  }
-
-  RefPtr<KeyboardInfo> keyInfo = mEventQueue.PopFront();
-
-  // Only allow keydown and keyup to call this method
-  if (NS_WARN_IF(aType.EqualsLiteral("keydown") &&
-                 keyInfo->mEvent.mMessage != eKeyDown) ||
-      NS_WARN_IF(aType.EqualsLiteral("keyup") &&
-                 keyInfo->mEvent.mMessage != eKeyUp)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  // The value of defaultPrevented depends on whether or not
-  // the key is consumed by input-method-app
-  SetDefaultPrevented(keyInfo->mEvent, aDefaultPrevented);
-
-  // Set the flag to specify the reply phase
-  keyInfo->mEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
-
-  // Check whether the event is still valid to be fired
-  if (CanDispatchEvent(keyInfo->mTarget, keyInfo->mEvent)) {
-    // If input-method-app doesn't handle this key,
-    // so we need to dispatch it to its current event target.
-    if (!keyInfo->mEvent.mFlags.mDefaultPrevented) {
-      DispatchToTargetApp(keyInfo->mTarget,
-                          keyInfo->mEvent,
-                          keyInfo->mStatus);
-    }
-  }
-
-  // No need to do further processing if the event is not keydown
-  if (keyInfo->mEvent.mMessage != eKeyDown) {
-    return NS_OK;
-  }
-
-  // Update the latest keydown data:
-  //   Release the holding reference to the previous keydown's data and
-  //   add a reference count to the current keydown's data.
-  mLatestKeyDownInfo = keyInfo;
-
-  // Handle the pending keypress event once keydown's reply arrives:
-  // It may have many keypress events per keydown on some platforms,
-  // so we use loop to dispatch keypress events.
-  // (But Gonk dispatch only one keypress per keydown)
-  // However, if there is no keypress after this keydown,
-  // then those following keypress will be handled in
-  // ForwardKeyToInputMethodApp directly.
-  for (KeyboardInfo* keypressInfo;
-       !mEventQueue.IsEmpty() &&
-       (keypressInfo = mEventQueue.PeekFront()) &&
-       keypressInfo->mEvent.mMessage == eKeyPress;
-       mEventQueue.RemoveFront()) {
-    DispatchKeyPress(keypressInfo->mTarget,
-                     keypressInfo->mEvent,
-                     keypressInfo->mStatus);
-  }
-
-  return NS_OK;
-}
-
-bool
-HardwareKeyHandler::DispatchKeyPress(nsINode* aTarget,
-                                     WidgetKeyboardEvent& aEvent,
-                                     nsEventStatus& aStatus)
-{
-  MOZ_ASSERT(aTarget, "No target provided");
-  MOZ_ASSERT(aEvent.mMessage == eKeyPress, "Event is not keypress");
-
-  // No need to dispatch keypress to the event target
-  // if the keydown event is consumed by the input-method-app.
-  if (mLatestKeyDownInfo &&
-      mLatestKeyDownInfo->mEvent.mFlags.mDefaultPrevented) {
-    return false;
-  }
-
-  // No need to dispatch keypress to the event target
-  // if the previous keydown event is modifier key's
-  if (mLatestKeyDownInfo &&
-      mLatestKeyDownInfo->mEvent.IsModifierKeyEvent()) {
-    return false;
-  }
-
-  // No need to dispatch keypress to the event target
-  // if it's invalid to be dispatched
-  if (!CanDispatchEvent(aTarget, aEvent)) {
-    return false;
-  }
-
-  // Set the flag to specify the reply phase.
-  aEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
-
-  // Dispatch the pending keypress event
-  bool ret = DispatchToTargetApp(aTarget, aEvent, aStatus);
-
-  // Re-trigger EventStateManager::PostHandleKeyboardEvent for keypress
-  PostHandleKeyboardEvent(aTarget, aEvent, aStatus);
-
-  return ret;
-}
-
-bool
-HardwareKeyHandler::DispatchToTargetApp(nsINode* aTarget,
-                                        WidgetKeyboardEvent& aEvent,
-                                        nsEventStatus& aStatus)
-{
-  MOZ_ASSERT(aTarget, "No target provided");
-
-  // Get current focused element as the event target
-  nsCOMPtr<nsIContent> currentTarget = GetCurrentTarget();
-  if (NS_WARN_IF(!currentTarget)) {
-    return false;
-  }
-
-  // The event target should be set to the current focused element.
-  // However, it might have security issue if the event is dispatched to
-  // the unexpected application, and it might cause unexpected operation
-  // in the new app.
-  nsCOMPtr<nsPIDOMWindowOuter> originalRootWindow = GetRootWindow(aTarget);
-  nsCOMPtr<nsPIDOMWindowOuter> currentRootWindow = GetRootWindow(currentTarget);
-  if (currentRootWindow != originalRootWindow) {
-    NS_WARNING("The root window is changed during the event is dispatching");
-    return false;
-  }
-
-  // If the current focused element is still in the same app,
-  // then we can use it as the current target to dispatch event.
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell(currentTarget);
-  if (!presShell) {
-    return false;
-  }
-
-  if (!presShell->CanDispatchEvent(&aEvent)) {
-    return false;
-  }
-
-  // In-process case: the event target is in the current process
-  if (!PresShell::IsTargetIframe(currentTarget)) {
-    DispatchToCurrentProcess(presShell, currentTarget, aEvent, aStatus);
-    return true;
-  }
-
-  // OOP case: the event target is in the child process
-  return DispatchToCrossProcess(aTarget, aEvent);
-}
-
-void
-HardwareKeyHandler::DispatchToCurrentProcess(nsIPresShell* presShell,
-                                             nsIContent* aTarget,
-                                             WidgetKeyboardEvent& aEvent,
-                                             nsEventStatus& aStatus)
-{
-  EventDispatcher::Dispatch(aTarget, presShell->GetPresContext(),
-                            &aEvent, nullptr, &aStatus, nullptr);
-}
-
-bool
-HardwareKeyHandler::DispatchToCrossProcess(nsINode* aTarget,
-                                           WidgetKeyboardEvent& aEvent)
-{
-  nsCOMPtr<nsIFrameLoaderOwner> remoteLoaderOwner = do_QueryInterface(aTarget);
-  if (NS_WARN_IF(!remoteLoaderOwner)) {
-    return false;
-  }
-
-  RefPtr<nsFrameLoader> remoteFrameLoader =
-    remoteLoaderOwner->GetFrameLoader();
-  if (NS_WARN_IF(!remoteFrameLoader)) {
-    return false;
-  }
-
-  uint32_t eventMode;
-  remoteFrameLoader->GetEventMode(&eventMode);
-  if (eventMode == nsIFrameLoader::EVENT_MODE_DONT_FORWARD_TO_CHILD) {
-    return false;
-  }
-
-  PBrowserParent* remoteBrowser = remoteFrameLoader->GetRemoteBrowser();
-  TabParent* remote = static_cast<TabParent*>(remoteBrowser);
-  if (NS_WARN_IF(!remote)) {
-    return false;
-  }
-
-  return remote->SendRealKeyEvent(aEvent);
-}
-
-void
-HardwareKeyHandler::PostHandleKeyboardEvent(nsINode* aTarget,
-                                            WidgetKeyboardEvent& aEvent,
-                                            nsEventStatus& aStatus)
-{
-  MOZ_ASSERT(aTarget, "No target provided");
-
-  nsPresContext* presContext = GetPresContext(aTarget);
-
-  RefPtr<mozilla::EventStateManager> esm = presContext->EventStateManager();
-  bool dispatchedToChildProcess = PresShell::IsTargetIframe(aTarget);
-  esm->PostHandleKeyboardEvent(&aEvent, aStatus, dispatchedToChildProcess);
-}
-
-void
-HardwareKeyHandler::SetDefaultPrevented(WidgetKeyboardEvent& aEvent,
-                                        uint16_t aDefaultPrevented) {
-  if (aDefaultPrevented & DEFAULT_PREVENTED) {
-    aEvent.mFlags.mDefaultPrevented = true;
-  }
-
-  if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CHROME) {
-    aEvent.mFlags.mDefaultPreventedByChrome = true;
-  }
-
-  if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CONTENT) {
-    aEvent.mFlags.mDefaultPreventedByContent = true;
-  }
-}
-
-bool
-HardwareKeyHandler::CanDispatchEvent(nsINode* aTarget,
-                                     WidgetKeyboardEvent& aEvent)
-{
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell(aTarget);
-  if (NS_WARN_IF(!presShell)) {
-    return false;
-  }
-  return presShell->CanDispatchEvent(&aEvent);
-}
-
-already_AddRefed<nsPIDOMWindowOuter>
-HardwareKeyHandler::GetRootWindow(nsINode* aNode)
-{
-  // Get nsIPresShell's pointer first
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
-  if (NS_WARN_IF(!presShell)) {
-    return nullptr;
-  }
-  nsCOMPtr<nsPIDOMWindowOuter> rootWindow = presShell->GetRootWindow();
-  return rootWindow.forget();
-}
-
-already_AddRefed<nsIContent>
-HardwareKeyHandler::GetCurrentTarget()
-{
-  nsFocusManager* fm = nsFocusManager::GetFocusManager();
-  if (NS_WARN_IF(!fm)) {
-    return nullptr;
-  }
-
-  nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
-  fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
-  if (NS_WARN_IF(!focusedWindow)) {
-    return nullptr;
-  }
-
-  auto* ourWindow = nsPIDOMWindowOuter::From(focusedWindow);
-
-  nsCOMPtr<nsPIDOMWindowOuter> rootWindow = ourWindow->GetPrivateRoot();
-  if (NS_WARN_IF(!rootWindow)) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
-  nsCOMPtr<nsIContent> focusedContent =
-    fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame));
-
-  // If there is no focus, then we use document body instead
-  if (NS_WARN_IF(!focusedContent || !focusedContent->GetPrimaryFrame())) {
-    nsIDocument* document = ourWindow->GetExtantDoc();
-    if (NS_WARN_IF(!document)) {
-      return nullptr;
-    }
-
-    focusedContent = document->GetRootElement();
-
-    nsCOMPtr<nsIDOMHTMLDocument> htmlDocument = do_QueryInterface(document);
-    if (htmlDocument) {
-      nsCOMPtr<nsIDOMHTMLElement> body;
-      htmlDocument->GetBody(getter_AddRefs(body));
-      nsCOMPtr<nsIContent> bodyContent = do_QueryInterface(body);
-      if (bodyContent) {
-        focusedContent = bodyContent;
-      }
-    }
-  }
-
-  return focusedContent ? focusedContent.forget() : nullptr;
-}
-
-nsPresContext*
-HardwareKeyHandler::GetPresContext(nsINode* aNode)
-{
-  // Get nsIPresShell's pointer first
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
-  if (NS_WARN_IF(!presShell)) {
-    return nullptr;
-  }
-
-  // then use nsIPresShell to get nsPresContext's pointer
-  return presShell->GetPresContext();
-}
-
-already_AddRefed<nsIPresShell>
-HardwareKeyHandler::GetPresShell(nsINode* aNode)
-{
-  nsIDocument* doc = aNode->OwnerDoc();
-  if (NS_WARN_IF(!doc)) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
-  if (NS_WARN_IF(!presShell)) {
-    return nullptr;
-  }
-
-  return presShell.forget();
-}
-
-/* static */
-already_AddRefed<HardwareKeyHandler>
-HardwareKeyHandler::GetInstance()
-{
-  if (!XRE_IsParentProcess()) {
-    return nullptr;
-  }
-
-  if (!sInstance) {
-    sInstance = new HardwareKeyHandler();
-    ClearOnShutdown(&sInstance);
-  }
-
-  RefPtr<HardwareKeyHandler> service = sInstance.get();
-  return service.forget();
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/inputmethod/HardwareKeyHandler.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_HardwareKeyHandler_h_
-#define mozilla_HardwareKeyHandler_h_
-
-#include "mozilla/EventForwards.h"          // for nsEventStatus
-#include "mozilla/StaticPtr.h"
-#include "mozilla/TextEvents.h"
-#include "nsCOMPtr.h"
-#include "nsDeque.h"
-#include "nsIHardwareKeyHandler.h"
-#include "nsIWeakReferenceUtils.h"          // for nsWeakPtr
-
-class nsIContent;
-class nsINode;
-class nsIPresShell;
-class nsPIDOMWindowOuter;
-class nsPresContext;
-
-namespace mozilla {
-
-// This module will copy the events' data into its event queue for reuse
-// after receiving input-method-app's reply, so we use the following struct
-// for storing these information.
-// RefCounted<T> is a helper class for adding reference counting mechanism.
-struct KeyboardInfo : public RefCounted<KeyboardInfo>
-{
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(KeyboardInfo)
-
-  nsINode* mTarget;
-  WidgetKeyboardEvent mEvent;
-  nsEventStatus mStatus;
-
-  KeyboardInfo(nsINode* aTarget,
-               WidgetKeyboardEvent& aEvent,
-               nsEventStatus aStatus)
-    : mTarget(aTarget)
-    , mEvent(aEvent)
-    , mStatus(aStatus)
-  {
-  }
-};
-
-// The following is the type-safe wrapper around nsDeque
-// for storing events' data.
-// The T must be one class that supports reference counting mechanism.
-// The EventQueueDeallocator will be called in nsDeque::~nsDeque() or
-// nsDeque::Erase() to deallocate the objects. nsDeque::Erase() will remove
-// and delete all items in the queue. See more from nsDeque.h.
-template <class T>
-class EventQueueDeallocator : public nsDequeFunctor
-{
-  virtual void* operator() (void* aObject)
-  {
-    RefPtr<T> releaseMe = dont_AddRef(static_cast<T*>(aObject));
-    return nullptr;
-  }
-};
-
-// The type-safe queue to be used to store the KeyboardInfo data
-template <class T>
-class EventQueue : private nsDeque
-{
-public:
-  EventQueue()
-    : nsDeque(new EventQueueDeallocator<T>())
-  {
-  };
-
-  ~EventQueue()
-  {
-    Clear();
-  }
-
-  inline size_t GetSize()
-  {
-    return nsDeque::GetSize();
-  }
-
-  bool IsEmpty()
-  {
-    return !nsDeque::GetSize();
-  }
-
-  inline bool Push(T* aItem)
-  {
-    MOZ_ASSERT(aItem);
-    NS_ADDREF(aItem);
-    size_t sizeBefore = GetSize();
-    nsDeque::Push(aItem);
-    if (GetSize() != sizeBefore + 1) {
-      NS_RELEASE(aItem);
-      return false;
-    }
-    return true;
-  }
-
-  inline already_AddRefed<T> PopFront()
-  {
-    RefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
-    return rv.forget();
-  }
-
-  inline void RemoveFront()
-  {
-    RefPtr<T> releaseMe = PopFront();
-  }
-
-  inline T* PeekFront()
-  {
-    return static_cast<T*>(nsDeque::PeekFront());
-  }
-
-  void Clear()
-  {
-    while (GetSize() > 0) {
-      RemoveFront();
-    }
-  }
-};
-
-class HardwareKeyHandler : public nsIHardwareKeyHandler
-{
-public:
-  HardwareKeyHandler();
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIHARDWAREKEYHANDLER
-
-  static already_AddRefed<HardwareKeyHandler> GetInstance();
-
-  virtual bool ForwardKeyToInputMethodApp(nsINode* aTarget,
-                                          WidgetKeyboardEvent* aEvent,
-                                          nsEventStatus* aEventStatus) override;
-
-private:
-  virtual ~HardwareKeyHandler();
-
-  // Return true if the keypress is successfully dispatched.
-  // Otherwise, return false.
-  bool DispatchKeyPress(nsINode* aTarget,
-                        WidgetKeyboardEvent& aEvent,
-                        nsEventStatus& aStatus);
-
-  void DispatchToCurrentProcess(nsIPresShell* aPresShell,
-                                nsIContent* aTarget,
-                                WidgetKeyboardEvent& aEvent,
-                                nsEventStatus& aStatus);
-
-  bool DispatchToCrossProcess(nsINode* aTarget, WidgetKeyboardEvent& aEvent);
-
-  // This method will dispatch not only key* event to its event target,
-  // no mather it's in the current process or in its child process,
-  // but also mozbrowserafterkey* to the corresponding target if it needs.
-  // Return true if the key is successfully dispatched.
-  // Otherwise, return false.
-  bool DispatchToTargetApp(nsINode* aTarget,
-                           WidgetKeyboardEvent& aEvent,
-                           nsEventStatus& aStatus);
-
-  // This method will be called after dispatching keypress to its target,
-  // if the input-method-app doesn't handle the key.
-  // In normal dispatching path, EventStateManager::PostHandleKeyboardEvent
-  // will be called when event is keypress.
-  // However, the ::PostHandleKeyboardEvent mentioned above will be aborted
-  // when we try to forward key event to the input-method-app.
-  // If the input-method-app consumes the key, then we don't need to do anything
-  // because the input-method-app will generate a new key event by itself.
-  // On the other hand, if the input-method-app doesn't consume the key,
-  // then we need to dispatch the key event by ourselves
-  // and call ::PostHandleKeyboardEvent again after the event is forwarded.
-  // Note that the EventStateManager::PreHandleEvent is already called before
-  // forwarding, so we don't need to call it in this module.
-  void PostHandleKeyboardEvent(nsINode* aTarget,
-                               WidgetKeyboardEvent& aEvent,
-                               nsEventStatus& aStatus);
-
-  void SetDefaultPrevented(WidgetKeyboardEvent& aEvent,
-                           uint16_t aDefaultPrevented);
-
-  // Check whether the event is valid to be fired.
-  // This method should be called every time before dispatching next event.
-  bool CanDispatchEvent(nsINode* aTarget,
-                        WidgetKeyboardEvent& aEvent);
-
-  already_AddRefed<nsPIDOMWindowOuter> GetRootWindow(nsINode* aNode);
-
-  already_AddRefed<nsIContent> GetCurrentTarget();
-
-  nsPresContext* GetPresContext(nsINode* aNode);
-
-  already_AddRefed<nsIPresShell> GetPresShell(nsINode* aNode);
-
-  static StaticRefPtr<HardwareKeyHandler> sInstance;
-
-  // The event queue is used to store the forwarded keyboard events.
-  // Those stored events will be dispatched if input-method-app doesn't
-  // consume them.
-  EventQueue<KeyboardInfo> mEventQueue;
-
-  // Hold the pointer to the latest keydown's data
-  RefPtr<KeyboardInfo> mLatestKeyDownInfo;
-
-  // input-method-app needs to register a listener by
-  // |nsIHardwareKeyHandler.registerListener| to receive
-  // the hardware keyboard event, and |nsIHardwareKeyHandler.registerListener|
-  // will set an nsIHardwareKeyEventListener to mHardwareKeyEventListener.
-  // Then, mHardwareKeyEventListener is used to forward the event
-  // to the input-method-app.
-  nsWeakPtr mHardwareKeyEventListener;
-
-  // To keep tracking the input-method-app is active or disabled.
-  bool mInputMethodAppConnected;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_HardwareKeyHandler_h_
deleted file mode 100644
--- a/dom/inputmethod/InputMethod.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {4607330d-e7d2-40a4-9eb8-43967eae0142} MozKeyboard.js
-contract @mozilla.org/b2g-inputmethod;1 {4607330d-e7d2-40a4-9eb8-43967eae0142}
deleted file mode 100644
--- a/dom/inputmethod/Keyboard.jsm
+++ /dev/null
@@ -1,571 +0,0 @@
-/* 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/. */
-
-'use strict';
-
-this.EXPORTED_SYMBOLS = ['Keyboard'];
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-  "@mozilla.org/parentprocessmessagemanager;1", "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
-                                  "resource://gre/modules/SystemAppProxy.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "hardwareKeyHandler", function() {
-#ifdef MOZ_B2G
-  return Cc["@mozilla.org/HardwareKeyHandler;1"]
-         .getService(Ci.nsIHardwareKeyHandler);
-#else
-  return null;
-#endif
-});
-
-var Utils = {
-  getMMFromMessage: function u_getMMFromMessage(msg) {
-    let mm;
-    try {
-      mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
-                     .frameLoader.messageManager;
-    } catch(e) {
-      mm = msg.target;
-    }
-
-    return mm;
-  }
-};
-
-this.Keyboard = {
-#ifdef MOZ_B2G
-  // For receving keyboard event fired from hardware before it's dispatched,
-  // |this| object is used to be the listener to get the forwarded event.
-  // As the listener, |this| object must implement nsIHardwareKeyEventListener
-  // and nsSupportsWeakReference.
-  // Please see nsIHardwareKeyHandler.idl to get more information.
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIHardwareKeyEventListener,
-    Ci.nsISupportsWeakReference
-  ]),
-#endif
-  _isConnectedToHardwareKeyHandler: false,
-  _formMM: null,      // The current web page message manager.
-  _keyboardMM: null,  // The keyboard app message manager.
-  _keyboardID: -1,    // The keyboard app's ID number. -1 = invalid
-  _nextKeyboardID: 0, // The ID number counter.
-  _systemMMs: [],     // The message managers registered to handle system async
-                      // messages.
-  _supportsSwitchingTypes: [],
-  _systemMessageNames: [
-    'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions',
-    'SetSupportsSwitchingTypes', 'RegisterSync', 'Unregister'
-  ],
-
-  _messageNames: [
-    'RemoveFocus',
-    'SetSelectionRange', 'ReplaceSurroundingText', 'ShowInputMethodPicker',
-    'SwitchToNextInputMethod', 'HideInputMethod',
-    'SendKey', 'GetContext',
-    'SetComposition', 'EndComposition',
-    'RegisterSync', 'Unregister',
-    'ReplyHardwareKeyEvent'
-  ],
-
-  get formMM() {
-    if (this._formMM && !Cu.isDeadWrapper(this._formMM))
-      return this._formMM;
-
-    return null;
-  },
-
-  set formMM(mm) {
-    this._formMM = mm;
-  },
-
-  sendToForm: function(name, data) {
-    if (!this.formMM) {
-      dump("Keyboard.jsm: Attempt to send message " + name +
-        " to form but no message manager exists.\n");
-
-      return;
-    }
-    try {
-      this.formMM.sendAsyncMessage(name, data);
-    } catch(e) { }
-  },
-
-  sendToKeyboard: function(name, data) {
-    try {
-      this._keyboardMM.sendAsyncMessage(name, data);
-    } catch(e) {
-      return false;
-    }
-    return true;
-  },
-
-  sendToSystem: function(name, data) {
-    if (!this._systemMMs.length) {
-      dump("Keyboard.jsm: Attempt to send message " + name +
-        " to system but no message manager registered.\n");
-
-      return;
-    }
-
-    this._systemMMs.forEach((mm, i) => {
-      data.inputManageId = i;
-      mm.sendAsyncMessage(name, data);
-    });
-  },
-
-  init: function keyboardInit() {
-    Services.obs.addObserver(this, 'inprocess-browser-shown', false);
-    Services.obs.addObserver(this, 'remote-browser-shown', false);
-    Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
-    Services.obs.addObserver(this, 'message-manager-close', false);
-
-    // For receiving the native hardware keyboard event
-    if (hardwareKeyHandler) {
-      hardwareKeyHandler.registerListener(this);
-    }
-
-    for (let name of this._messageNames) {
-      ppmm.addMessageListener('Keyboard:' + name, this);
-    }
-
-    for (let name of this._systemMessageNames) {
-      ppmm.addMessageListener('System:' + name, this);
-    }
-
-    this.inputRegistryGlue = new InputRegistryGlue();
-  },
-
-  // This method will be registered into nsIHardwareKeyHandler:
-  // Send the initialized dictionary retrieved from the native keyboard event
-  // to input-method-app for generating a new event.
-  onHardwareKey: function onHardwareKeyReceived(evt) {
-    return this.sendToKeyboard('Keyboard:ReceiveHardwareKeyEvent', {
-      type: evt.type,
-      keyDict: evt.initDict
-    });
-  },
-
-  observe: function keyboardObserve(subject, topic, data) {
-    let frameLoader = null;
-    let mm = null;
-
-    if (topic == 'message-manager-close') {
-      mm = subject;
-    } else {
-      frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
-      mm = frameLoader.messageManager;
-    }
-
-    if (topic == 'oop-frameloader-crashed' ||
-	      topic == 'message-manager-close') {
-      if (this.formMM == mm) {
-        // The application has been closed unexpectingly. Let's tell the
-        // keyboard app that the focus has been lost.
-        this.sendToKeyboard('Keyboard:Blur', {});
-        // Notify system app to hide keyboard.
-        this.sendToSystem('System:Blur', {});
-        // XXX: To be removed when content migrate away from mozChromeEvents.
-        SystemAppProxy.dispatchEvent({
-          type: 'inputmethod-contextchange',
-          inputType: 'blur'
-        });
-
-        this.formMM = null;
-      }
-    } else {
-      // Ignore notifications that aren't from a Browser
-      if (!frameLoader.ownerIsMozBrowserFrame) {
-        return;
-      }
-      this.initFormsFrameScript(mm);
-    }
-  },
-
-  initFormsFrameScript: function(mm) {
-    mm.addMessageListener('Forms:Focus', this);
-    mm.addMessageListener('Forms:Blur', this);
-    mm.addMessageListener('Forms:SelectionChange', this);
-    mm.addMessageListener('Forms:SetSelectionRange:Result:OK', this);
-    mm.addMessageListener('Forms:SetSelectionRange:Result:Error', this);
-    mm.addMessageListener('Forms:ReplaceSurroundingText:Result:OK', this);
-    mm.addMessageListener('Forms:ReplaceSurroundingText:Result:Error', this);
-    mm.addMessageListener('Forms:SendKey:Result:OK', this);
-    mm.addMessageListener('Forms:SendKey:Result:Error', this);
-    mm.addMessageListener('Forms:SequenceError', this);
-    mm.addMessageListener('Forms:GetContext:Result:OK', this);
-    mm.addMessageListener('Forms:SetComposition:Result:OK', this);
-    mm.addMessageListener('Forms:EndComposition:Result:OK', this);
-  },
-
-  receiveMessage: function keyboardReceiveMessage(msg) {
-    let mm = Utils.getMMFromMessage(msg);
-
-    // we don't process kb messages (other than register)
-    // if they come from a kb that we're currently not regsitered for.
-    // this decision is made with the kbID kept by us and kb app
-    let kbID = null;
-    if ('kbID' in msg.data) {
-      kbID = msg.data.kbID;
-    }
-
-    if (0 === msg.name.indexOf('Keyboard:') &&
-        ('Keyboard:RegisterSync' !== msg.name && this._keyboardID !== kbID)
-       ) {
-      return;
-    }
-
-    switch (msg.name) {
-      case 'Forms:Focus':
-        this.handleFocus(msg);
-        break;
-      case 'Forms:Blur':
-        this.handleBlur(msg);
-        break;
-      case 'Forms:SelectionChange':
-      case 'Forms:SetSelectionRange:Result:OK':
-      case 'Forms:ReplaceSurroundingText:Result:OK':
-      case 'Forms:SendKey:Result:OK':
-      case 'Forms:SendKey:Result:Error':
-      case 'Forms:SequenceError':
-      case 'Forms:GetContext:Result:OK':
-      case 'Forms:SetComposition:Result:OK':
-      case 'Forms:EndComposition:Result:OK':
-      case 'Forms:SetSelectionRange:Result:Error':
-      case 'Forms:ReplaceSurroundingText:Result:Error':
-        let name = msg.name.replace(/^Forms/, 'Keyboard');
-        this.forwardEvent(name, msg);
-        break;
-
-      case 'System:SetValue':
-        this.setValue(msg);
-        break;
-      case 'Keyboard:RemoveFocus':
-      case 'System:RemoveFocus':
-        this.removeFocus();
-        break;
-      case 'System:RegisterSync': {
-        if (this._systemMMs.length !== 0) {
-          dump('Keyboard.jsm Warning: There are more than one content page ' +
-            'with input-manage permission. There will be undeterministic ' +
-            'responses to addInput()/removeInput() if both content pages are ' +
-            'trying to respond to the same request event.\n');
-        }
-
-        let id = this._systemMMs.length;
-        this._systemMMs.push(mm);
-
-        return id;
-      }
-
-      case 'System:Unregister':
-        this._systemMMs.splice(msg.data.id, 1);
-
-        break;
-      case 'System:SetSelectedOption':
-        this.setSelectedOption(msg);
-        break;
-      case 'System:SetSelectedOptions':
-        this.setSelectedOption(msg);
-        break;
-      case 'System:SetSupportsSwitchingTypes':
-        this.setSupportsSwitchingTypes(msg);
-        break;
-      case 'Keyboard:SetSelectionRange':
-        this.setSelectionRange(msg);
-        break;
-      case 'Keyboard:ReplaceSurroundingText':
-        this.replaceSurroundingText(msg);
-        break;
-      case 'Keyboard:SwitchToNextInputMethod':
-        this.switchToNextInputMethod();
-        break;
-      case 'Keyboard:ShowInputMethodPicker':
-        this.showInputMethodPicker();
-        break;
-      case 'Keyboard:SendKey':
-        this.sendKey(msg);
-        break;
-      case 'Keyboard:GetContext':
-        this.getContext(msg);
-        break;
-      case 'Keyboard:SetComposition':
-        this.setComposition(msg);
-        break;
-      case 'Keyboard:EndComposition':
-        this.endComposition(msg);
-        break;
-      case 'Keyboard:RegisterSync':
-        this._keyboardMM = mm;
-        if (kbID) {
-          // keyboard identifies itself, use its kbID
-          // this msg would be async, so no need to return
-          this._keyboardID = kbID;
-        }else{
-          // generate the id for the keyboard
-          this._keyboardID = this._nextKeyboardID;
-          this._nextKeyboardID++;
-          // this msg is sync,
-          // and we want to return the id back to inputmethod
-          return this._keyboardID;
-        }
-        break;
-      case 'Keyboard:Unregister':
-        this._keyboardMM = null;
-        this._keyboardID = -1;
-        break;
-      case 'Keyboard:ReplyHardwareKeyEvent':
-        if (hardwareKeyHandler) {
-          let reply = msg.data;
-          hardwareKeyHandler.onHandledByInputMethodApp(reply.type,
-                                                       reply.defaultPrevented);
-        }
-        break;
-    }
-  },
-
-  handleFocus: function keyboardHandleFocus(msg) {
-    // Set the formMM to the new message manager received.
-    let mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
-                .frameLoader.messageManager;
-    this.formMM = mm;
-
-    // Notify the nsIHardwareKeyHandler that the input-method-app is active now.
-    if (hardwareKeyHandler && !this._isConnectedToHardwareKeyHandler) {
-      this._isConnectedToHardwareKeyHandler = true;
-      hardwareKeyHandler.onInputMethodAppConnected();
-    }
-
-    // Notify the current active input app to gain focus.
-    this.forwardEvent('Keyboard:Focus', msg);
-
-    // Notify System app, used also to render value selectors for now;
-    // that's why we need the info about choices / min / max here as well...
-    this.sendToSystem('System:Focus', msg.data);
-
-    // XXX: To be removed when content migrate away from mozChromeEvents.
-    SystemAppProxy.dispatchEvent({
-      type: 'inputmethod-contextchange',
-      inputType: msg.data.inputType,
-      value: msg.data.value,
-      choices: JSON.stringify(msg.data.choices),
-      min: msg.data.min,
-      max: msg.data.max
-    });
-  },
-
-  handleBlur: function keyboardHandleBlur(msg) {
-    let mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
-                .frameLoader.messageManager;
-    // A blur message can't be sent to the keyboard if the focus has
-    // already been taken away at first place.
-    // This check is here to prevent problem caused by out-of-order
-    // ipc messages from two processes.
-    if (mm !== this.formMM) {
-      return;
-    }
-
-    // unset formMM
-    this.formMM = null;
-
-    // Notify the nsIHardwareKeyHandler that
-    // the input-method-app is disabled now.
-    if (hardwareKeyHandler && this._isConnectedToHardwareKeyHandler) {
-      this._isConnectedToHardwareKeyHandler = false;
-      hardwareKeyHandler.onInputMethodAppDisconnected();
-    }
-
-    this.forwardEvent('Keyboard:Blur', msg);
-    this.sendToSystem('System:Blur', {});
-
-    // XXX: To be removed when content migrate away from mozChromeEvents.
-    SystemAppProxy.dispatchEvent({
-      type: 'inputmethod-contextchange',
-      inputType: 'blur'
-    });
-  },
-
-  forwardEvent: function keyboardForwardEvent(newEventName, msg) {
-    this.sendToKeyboard(newEventName, msg.data);
-  },
-
-  setSelectedOption: function keyboardSetSelectedOption(msg) {
-    this.sendToForm('Forms:Select:Choice', msg.data);
-  },
-
-  setSelectedOptions: function keyboardSetSelectedOptions(msg) {
-    this.sendToForm('Forms:Select:Choice', msg.data);
-  },
-
-  setSelectionRange: function keyboardSetSelectionRange(msg) {
-    this.sendToForm('Forms:SetSelectionRange', msg.data);
-  },
-
-  setValue: function keyboardSetValue(msg) {
-    this.sendToForm('Forms:Input:Value', msg.data);
-  },
-
-  removeFocus: function keyboardRemoveFocus() {
-    if (!this.formMM) {
-      return;
-    }
-
-    this.sendToForm('Forms:Select:Blur', {});
-  },
-
-  replaceSurroundingText: function keyboardReplaceSurroundingText(msg) {
-    this.sendToForm('Forms:ReplaceSurroundingText', msg.data);
-  },
-
-  showInputMethodPicker: function keyboardShowInputMethodPicker() {
-    this.sendToSystem('System:ShowAll', {});
-
-    // XXX: To be removed with mozContentEvent support from shell.js
-    SystemAppProxy.dispatchEvent({
-      type: "inputmethod-showall"
-    });
-  },
-
-  switchToNextInputMethod: function keyboardSwitchToNextInputMethod() {
-    this.sendToSystem('System:Next', {});
-
-    // XXX: To be removed with mozContentEvent support from shell.js
-    SystemAppProxy.dispatchEvent({
-      type: "inputmethod-next"
-    });
-  },
-
-  sendKey: function keyboardSendKey(msg) {
-    this.sendToForm('Forms:Input:SendKey', msg.data);
-  },
-
-  getContext: function keyboardGetContext(msg) {
-    if (!this.formMM) {
-      return;
-    }
-
-    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
-      types: this._supportsSwitchingTypes
-    });
-
-    this.sendToForm('Forms:GetContext', msg.data);
-  },
-
-  setComposition: function keyboardSetComposition(msg) {
-    this.sendToForm('Forms:SetComposition', msg.data);
-  },
-
-  endComposition: function keyboardEndComposition(msg) {
-    this.sendToForm('Forms:EndComposition', msg.data);
-  },
-
-  setSupportsSwitchingTypes: function setSupportsSwitchingTypes(msg) {
-    this._supportsSwitchingTypes = msg.data.types;
-    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', msg.data);
-  },
-  // XXX: To be removed with mozContentEvent support from shell.js
-  setLayouts: function keyboardSetLayouts(layouts) {
-    // The input method plugins may not have loaded yet,
-    // cache the layouts so on init we can respond immediately instead
-    // of going back and forth between keyboard_manager
-    var types = [];
-
-    Object.keys(layouts).forEach((type) => {
-      if (layouts[type] > 1) {
-        types.push(type);
-      }
-    });
-
-    this._supportsSwitchingTypes = types;
-
-    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
-      types: types
-    });
-  }
-};
-
-function InputRegistryGlue() {
-  this._messageId = 0;
-  this._msgMap = new Map();
-
-  ppmm.addMessageListener('InputRegistry:Add', this);
-  ppmm.addMessageListener('InputRegistry:Remove', this);
-  ppmm.addMessageListener('System:InputRegistry:Add:Done', this);
-  ppmm.addMessageListener('System:InputRegistry:Remove:Done', this);
-};
-
-InputRegistryGlue.prototype.receiveMessage = function(msg) {
-  let mm = Utils.getMMFromMessage(msg);
-
-  switch (msg.name) {
-    case 'InputRegistry:Add':
-      this.addInput(msg, mm);
-
-      break;
-
-    case 'InputRegistry:Remove':
-      this.removeInput(msg, mm);
-
-      break;
-
-    case 'System:InputRegistry:Add:Done':
-    case 'System:InputRegistry:Remove:Done':
-      this.returnMessage(msg.data);
-
-      break;
-  }
-};
-
-InputRegistryGlue.prototype.addInput = function(msg, mm) {
-  let msgId = this._messageId++;
-  this._msgMap.set(msgId, {
-    mm: mm,
-    requestId: msg.data.requestId
-  });
-};
-
-InputRegistryGlue.prototype.removeInput = function(msg, mm) {
-  let msgId = this._messageId++;
-  this._msgMap.set(msgId, {
-    mm: mm,
-    requestId: msg.data.requestId
-  });
-};
-
-InputRegistryGlue.prototype.returnMessage = function(detail) {
-  if (!this._msgMap.has(detail.id)) {
-    dump('InputRegistryGlue: Ignoring already handled message response. ' +
-         'id=' + detail.id + '\n');
-    return;
-  }
-
-  let { mm, requestId } = this._msgMap.get(detail.id);
-  this._msgMap.delete(detail.id);
-
-  if (Cu.isDeadWrapper(mm)) {
-    dump('InputRegistryGlue: Message manager has already died.\n');
-    return;
-  }
-
-  if (!('error' in detail)) {
-    mm.sendAsyncMessage('InputRegistry:Result:OK', {
-      requestId: requestId
-    });
-  } else {
-    mm.sendAsyncMessage('InputRegistry:Result:Error', {
-      error: detail.error,
-      requestId: requestId
-    });
-  }
-};
-
-this.Keyboard.init();
deleted file mode 100644
--- a/dom/inputmethod/MozKeyboard.js
+++ /dev/null
@@ -1,1255 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
-  "@mozilla.org/childprocessmessagemanager;1", "nsISyncMessageSender");
-
-XPCOMUtils.defineLazyServiceGetter(this, "tm",
-  "@mozilla.org/thread-manager;1", "nsIThreadManager");
-
-/*
- * A WeakMap to map input method iframe window to
- * it's active status, kbID, and ipcHelper.
- */
-var 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 = {
-        active: false,
-        kbID: undefined,
-        ipcHelper: null
-      };
-      this._map.set(win, obj);
-
-      return obj;
-    }
-  },
-
-  /*
-   * Check if the given window is active.
-   */
-  isActive: function(win) {
-    if (!this._map || !win) {
-      return false;
-    }
-
-    return this._getObjForWin(win).active;
-  },
-
-  /*
-   * Set the active status of the given window.
-   */
-  setActive: function(win, isActive) {
-    if (!win) {
-      return;
-    }
-    let obj = this._getObjForWin(win);
-    obj.active = isActive;
-  },
-
-  /*
-   * Get the keyboard ID (assigned by Keyboard.jsm) of the given window.
-   */
-  getKbID: function(win) {
-    if (!this._map || !win) {
-      return undefined;
-    }
-
-    let obj = this._getObjForWin(win);
-    return obj.kbID;
-  },
-
-  /*
-   * Set the keyboard ID (assigned by Keyboard.jsm) of the given window.
-   */
-  setKbID: function(win, kbID) {
-    if (!win) {
-      return;
-    }
-    let obj = this._getObjForWin(win);
-    obj.kbID = kbID;
-  },
-
-  /*
-   * Get InputContextDOMRequestIpcHelper instance attached to this window.
-   */
-  getInputContextIpcHelper: function(win) {
-    if (!win) {
-      return;
-    }
-    let obj = this._getObjForWin(win);
-    if (!obj.ipcHelper) {
-      obj.ipcHelper = new InputContextDOMRequestIpcHelper(win);
-    }
-    return obj.ipcHelper;
-  },
-
-  /*
-   * Unset InputContextDOMRequestIpcHelper instance.
-   */
-  unsetInputContextIpcHelper: function(win) {
-    if (!win) {
-      return;
-    }
-    let obj = this._getObjForWin(win);
-    if (!obj.ipcHelper) {
-      return;
-    }
-    obj.ipcHelper = null;
-  }
-};
-
-var cpmmSendAsyncMessageWithKbID = function (self, msg, data) {
-  data.kbID = WindowMap.getKbID(self._window);
-  cpmm.sendAsyncMessage(msg, data);
-};
-
-/**
- * ==============================================
- * InputMethodManager
- * ==============================================
- */
-function MozInputMethodManager(win) {
-  this._window = win;
-}
-
-MozInputMethodManager.prototype = {
-  supportsSwitchingForCurrentInputContext: false,
-  _window: null,
-
-  classID: Components.ID("{7e9d7280-ef86-11e2-b778-0800200c9a66}"),
-
-  QueryInterface: XPCOMUtils.generateQI([]),
-
-  set oninputcontextfocus(handler) {
-    this.__DOM_IMPL__.setEventHandler("oninputcontextfocus", handler);
-  },
-
-  get oninputcontextfocus() {
-    return this.__DOM_IMPL__.getEventHandler("oninputcontextfocus");
-  },
-
-  set oninputcontextblur(handler) {
-    this.__DOM_IMPL__.setEventHandler("oninputcontextblur", handler);
-  },
-
-  get oninputcontextblur() {
-    return this.__DOM_IMPL__.getEventHandler("oninputcontextblur");
-  },
-
-  set onshowallrequest(handler) {
-    this.__DOM_IMPL__.setEventHandler("onshowallrequest", handler);
-  },
-
-  get onshowallrequest() {
-    return this.__DOM_IMPL__.getEventHandler("onshowallrequest");
-  },
-
-  set onnextrequest(handler) {
-    this.__DOM_IMPL__.setEventHandler("onnextrequest", handler);
-  },
-
-  get onnextrequest() {
-    return this.__DOM_IMPL__.getEventHandler("onnextrequest");
-  },
-
-  set onaddinputrequest(handler) {
-    this.__DOM_IMPL__.setEventHandler("onaddinputrequest", handler);
-  },
-
-  get onaddinputrequest() {
-    return this.__DOM_IMPL__.getEventHandler("onaddinputrequest");
-  },
-
-  set onremoveinputrequest(handler) {
-    this.__DOM_IMPL__.setEventHandler("onremoveinputrequest", handler);
-  },
-
-  get onremoveinputrequest() {
-    return this.__DOM_IMPL__.getEventHandler("onremoveinputrequest");
-  },
-
-  showAll: function() {
-    if (!WindowMap.isActive(this._window)) {
-      return;
-    }
-    cpmmSendAsyncMessageWithKbID(this, 'Keyboard:ShowInputMethodPicker', {});
-  },
-
-  next: function() {
-    if (!WindowMap.isActive(this._window)) {
-      return;
-    }
-    cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SwitchToNextInputMethod', {});
-  },
-
-  supportsSwitching: function() {
-    if (!WindowMap.isActive(this._window)) {
-      return false;
-    }
-    return this.supportsSwitchingForCurrentInputContext;
-  },
-
-  hide: function() {
-    if (!WindowMap.isActive(this._window)) {
-      return;
-    }
-    cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RemoveFocus', {});
-  },
-
-  setSupportsSwitchingTypes: function(types) {
-    cpmm.sendAsyncMessage('System:SetSupportsSwitchingTypes', {
-      types: types
-    });
-  },
-
-  handleFocus: function(data) {
-    let detail = new MozInputContextFocusEventDetail(this._window, data);
-    let wrappedDetail =
-      this._window.MozInputContextFocusEventDetail._create(this._window, detail);
-    let event = new this._window.CustomEvent('inputcontextfocus',
-      { cancelable: true, detail: wrappedDetail });
-
-    let handled = !this.__DOM_IMPL__.dispatchEvent(event);
-
-    // A gentle warning if the event is not preventDefault() by the content.
-    if (!handled) {
-      dump('MozKeyboard.js: A frame with input-manage permission did not' +
-        ' handle the inputcontextfocus event dispatched.\n');
-    }
-  },
-
-  handleBlur: function(data) {
-    let event =
-      new this._window.Event('inputcontextblur', { cancelable: true });
-
-    let handled = !this.__DOM_IMPL__.dispatchEvent(event);
-
-    // A gentle warning if the event is not preventDefault() by the content.
-    if (!handled) {
-      dump('MozKeyboard.js: A frame with input-manage permission did not' +
-        ' handle the inputcontextblur event dispatched.\n');
-    }
-  },
-
-  dispatchShowAllRequestEvent: function() {
-    this._fireSimpleEvent('showallrequest');
-  },
-
-  dispatchNextRequestEvent: function() {
-    this._fireSimpleEvent('nextrequest');
-  },
-
-  _fireSimpleEvent: function(eventType) {
-    let event = new this._window.Event(eventType);
-    let handled = !this.__DOM_IMPL__.dispatchEvent(event, { cancelable: true });
-
-    // A gentle warning if the event is not preventDefault() by the content.
-    if (!handled) {
-      dump('MozKeyboard.js: A frame with input-manage permission did not' +
-        ' handle the ' + eventType + ' event dispatched.\n');
-    }
-  },
-
-  handleAddInput: function(data) {
-    let p = this._fireInputRegistryEvent('addinputrequest', data);
-    if (!p) {
-      return;
-    }
-
-    p.then(() => {
-      cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', {
-        id: data.id
-      });
-    }, (error) => {
-      cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', {
-        id: data.id,
-        error: error || 'Unknown Error'
-      });
-    });
-  },
-
-  handleRemoveInput: function(data) {
-    let p = this._fireInputRegistryEvent('removeinputrequest', data);
-    if (!p) {
-      return;
-    }
-
-    p.then(() => {
-      cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', {
-        id: data.id
-      });
-    }, (error) => {
-      cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', {
-        id: data.id,
-        error: error || 'Unknown Error'
-      });
-    });
-  },
-
-  _fireInputRegistryEvent: function(eventType, data) {
-    let detail = new MozInputRegistryEventDetail(this._window, data);
-    let wrappedDetail =
-      this._window.MozInputRegistryEventDetail._create(this._window, detail);
-    let event = new this._window.CustomEvent(eventType,
-      { cancelable: true, detail: wrappedDetail });
-    let handled = !this.__DOM_IMPL__.dispatchEvent(event);
-
-    // A gentle warning if the event is not preventDefault() by the content.
-    if (!handled) {
-      dump('MozKeyboard.js: A frame with input-manage permission did not' +
-        ' handle the ' + eventType + ' event dispatched.\n');
-
-      return null;
-    }
-    return detail.takeChainedPromise();
-  }
-};
-
-function MozInputContextFocusEventDetail(win, data) {
-  this.type = data.type;
-  this.inputType = data.inputType;
-  this.value = data.value;
-  // Exposed as MozInputContextChoicesInfo dictionary defined in WebIDL
-  this.choices = data.choices;
-  this.min = data.min;
-  this.max = data.max;
-}
-MozInputContextFocusEventDetail.prototype = {
-  classID: Components.ID("{e0794208-ac50-40e8-b22e-6ee0b4c4e6e8}"),
-  QueryInterface: XPCOMUtils.generateQI([]),
-
-  type: undefined,
-  inputType: undefined,
-  value: '',
-  choices: null,
-  min: undefined,
-  max: undefined
-};
-
-function MozInputRegistryEventDetail(win, data) {
-  this._window = win;
-
-  this.manifestURL = data.manifestURL;
-  this.inputId = data.inputId;
-  // Exposed as MozInputMethodInputManifest dictionary defined in WebIDL
-  this.inputManifest = data.inputManifest;
-
-  this._chainedPromise = Promise.resolve();
-}
-MozInputRegistryEventDetail.prototype = {
-  classID: Components.ID("{02130070-9b3e-4f38-bbd9-f0013aa36717}"),
-  QueryInterface: XPCOMUtils.generateQI([]),
-
-  _window: null,
-
-  manifestURL: undefined,
-  inputId: undefined,
-  inputManifest: null,
-
-  waitUntil: function(p) {
-    // Need an extra protection here since waitUntil will be an no-op
-    // when chainedPromise is already returned.
-    if (!this._chainedPromise) {
-      throw new this._window.DOMException(
-        'Must call waitUntil() within the event handling loop.',
-        'InvalidStateError');
-    }
-
-    this._chainedPromise = this._chainedPromise
-      .then(function() { return p; });
-  },
-
-  takeChainedPromise: function() {
-    var p = this._chainedPromise;
-    this._chainedPromise = null;
-    return p;
-  }
-};
-
-/**
- * ==============================================
- * InputMethod
- * ==============================================
- */
-function MozInputMethod() { }
-
-MozInputMethod.prototype = {
-  __proto__: DOMRequestIpcHelper.prototype,
-
-  _window: null,
-  _inputcontext: null,
-  _wrappedInputContext: null,
-  _mgmt: null,
-  _wrappedMgmt: null,
-  _supportsSwitchingTypes: [],
-  _inputManageId: undefined,
-
-  classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
-
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIDOMGlobalPropertyInitializer,
-    Ci.nsIObserver,
-    Ci.nsISupportsWeakReference
-  ]),
-
-  init: function mozInputMethodInit(win) {
-    this._window = win;
-    this._mgmt = new MozInputMethodManager(win);
-    this._wrappedMgmt = win.MozInputMethodManager._create(win, this._mgmt);
-    this.innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindowUtils)
-                            .currentInnerWindowID;
-
-    Services.obs.addObserver(this, "inner-window-destroyed", false);
-
-    cpmm.addWeakMessageListener('Keyboard:Focus', this);
-    cpmm.addWeakMessageListener('Keyboard:Blur', this);
-    cpmm.addWeakMessageListener('Keyboard:SelectionChange', this);
-    cpmm.addWeakMessageListener('Keyboard:GetContext:Result:OK', this);
-    cpmm.addWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
-    cpmm.addWeakMessageListener('Keyboard:ReceiveHardwareKeyEvent', this);
-    cpmm.addWeakMessageListener('InputRegistry:Result:OK', this);
-    cpmm.addWeakMessageListener('InputRegistry:Result:Error', this);
-
-    if (this._hasInputManagePerm(win)) {
-      this._inputManageId = cpmm.sendSyncMessage('System:RegisterSync', {})[0];
-      cpmm.addWeakMessageListener('System:Focus', this);
-      cpmm.addWeakMessageListener('System:Blur', this);
-      cpmm.addWeakMessageListener('System:ShowAll', this);
-      cpmm.addWeakMessageListener('System:Next', this);
-      cpmm.addWeakMessageListener('System:InputRegistry:Add', this);
-      cpmm.addWeakMessageListener('System:InputRegistry:Remove', this);
-    }
-  },
-
-  uninit: function mozInputMethodUninit() {
-    this._window = null;
-    this._mgmt = null;
-    this._wrappedMgmt = null;
-
-    cpmm.removeWeakMessageListener('Keyboard:Focus', this);
-    cpmm.removeWeakMessageListener('Keyboard:Blur', this);
-    cpmm.removeWeakMessageListener('Keyboard:SelectionChange', this);
-    cpmm.removeWeakMessageListener('Keyboard:GetContext:Result:OK', this);
-    cpmm.removeWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
-    cpmm.removeWeakMessageListener('Keyboard:ReceiveHardwareKeyEvent', this);
-    cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this);
-    cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this);
-    this.setActive(false);
-
-    if (typeof this._inputManageId === 'number') {
-      cpmm.sendAsyncMessage('System:Unregister', {
-        'id': this._inputManageId
-      });
-      cpmm.removeWeakMessageListener('System:Focus', this);
-      cpmm.removeWeakMessageListener('System:Blur', this);
-      cpmm.removeWeakMessageListener('System:ShowAll', this);
-      cpmm.removeWeakMessageListener('System:Next', this);
-      cpmm.removeWeakMessageListener('System:InputRegistry:Add', this);
-      cpmm.removeWeakMessageListener('System:InputRegistry:Remove', this);
-    }
-  },
-
-  receiveMessage: function mozInputMethodReceiveMsg(msg) {
-    if (msg.name.startsWith('Keyboard') &&
-        !WindowMap.isActive(this._window)) {
-      return;
-    }
-
-    let data = msg.data;
-
-    if (msg.name.startsWith('System') &&
-      this._inputManageId !== data.inputManageId) {
-      return;
-    }
-    delete data.inputManageId;
-
-    let resolver = ('requestId' in data) ?
-      this.takePromiseResolver(data.requestId) : null;
-
-    switch(msg.name) {
-      case 'Keyboard:Focus':
-        // XXX Bug 904339 could receive 'text' event twice
-        this.setInputContext(data);
-        break;
-      case 'Keyboard:Blur':
-        this.setInputContext(null);
-        break;
-      case 'Keyboard:SelectionChange':
-        if (this.inputcontext) {
-          this._inputcontext.updateSelectionContext(data, false);
-        }
-        break;
-      case 'Keyboard:GetContext:Result:OK':
-        this.setInputContext(data);
-        break;
-      case 'Keyboard:SupportsSwitchingTypesChange':
-        this._supportsSwitchingTypes = data.types;
-        break;
-      case 'Keyboard:ReceiveHardwareKeyEvent':
-        if (!Ci.nsIHardwareKeyHandler) {
-          break;
-        }
-
-        let defaultPrevented = Ci.nsIHardwareKeyHandler.NO_DEFAULT_PREVENTED;
-
-        // |event.preventDefault()| is allowed to be called only when
-        // |event.cancelable| is true
-        if (this._inputcontext && data.keyDict.cancelable) {
-          defaultPrevented |= this._inputcontext.forwardHardwareKeyEvent(data);
-        }
-
-        cpmmSendAsyncMessageWithKbID(this, 'Keyboard:ReplyHardwareKeyEvent', {
-                                       type: data.type,
-                                       defaultPrevented: defaultPrevented
-                                     });
-        break;
-      case 'InputRegistry:Result:OK':
-        resolver.resolve();
-
-        break;
-
-      case 'InputRegistry:Result:Error':
-        resolver.reject(data.error);
-
-        break;
-
-      case 'System:Focus':
-        this._mgmt.handleFocus(data);
-        break;
-
-      case 'System:Blur':
-        this._mgmt.handleBlur(data);
-        break;
-
-      case 'System:ShowAll':
-        this._mgmt.dispatchShowAllRequestEvent();
-        break;
-
-      case 'System:Next':
-        this._mgmt.dispatchNextRequestEvent();
-        break;
-
-      case 'System:InputRegistry:Add':
-        this._mgmt.handleAddInput(data);
-        break;
-
-      case 'System:InputRegistry:Remove':
-        this._mgmt.handleRemoveInput(data);
-        break;
-    }
-  },
-
-  observe: function mozInputMethodObserve(subject, topic, data) {
-    let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    if (wId == this.innerWindowID)
-      this.uninit();
-  },
-
-  get mgmt() {
-    return this._wrappedMgmt;
-  },
-
-  get inputcontext() {
-    if (!WindowMap.isActive(this._window)) {
-      return null;
-    }
-    return this._wrappedInputContext;
-  },
-
-  set oninputcontextchange(handler) {
-    this.__DOM_IMPL__.setEventHandler("oninputcontextchange", handler);
-  },
-
-  get oninputcontextchange() {
-    return this.__DOM_IMPL__.getEventHandler("oninputcontextchange");
-  },
-
-  setInputContext: function mozKeyboardContextChange(data) {
-    if (this._inputcontext) {
-      this._inputcontext.destroy();
-      this._inputcontext = null;
-      this._wrappedInputContext = null;
-      this._mgmt.supportsSwitchingForCurrentInputContext = false;
-    }
-
-    if (data) {
-      this._mgmt.supportsSwitchingForCurrentInputContext =
-        (this._supportsSwitchingTypes.indexOf(data.inputType) !== -1);
-
-      this._inputcontext = new MozInputContext(data);
-      this._inputcontext.init(this._window);
-      // inputcontext will be exposed as a WebIDL object. Create its
-      // content-side object explicitly to avoid Bug 1001325.
-      this._wrappedInputContext =
-        this._window.MozInputContext._create(this._window, this._inputcontext);
-    }
-
-    let event = new this._window.Event("inputcontextchange");
-    this.__DOM_IMPL__.dispatchEvent(event);
-  },
-
-  setActive: function mozInputMethodSetActive(isActive) {
-    if (WindowMap.isActive(this._window) === isActive) {
-      return;
-    }
-
-    WindowMap.setActive(this._window, isActive);
-
-    if (isActive) {
-      // Activate current input method.
-      // If there is already an active context, then this will trigger
-      // a GetContext:Result:OK event, and we can initialize ourselves.
-      // Otherwise silently ignored.
-
-      // get keyboard ID from Keyboard.jsm,
-      // or if we already have it, get it from our map
-      // Note: if we need to get it from Keyboard.jsm,
-      // we have to use a synchronous message
-      var kbID = WindowMap.getKbID(this._window);
-      if (kbID) {
-        cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RegisterSync', {});
-      } else {
-        let res = cpmm.sendSyncMessage('Keyboard:RegisterSync', {});
-        WindowMap.setKbID(this._window, res[0]);
-      }
-
-      cpmmSendAsyncMessageWithKbID(this, 'Keyboard:GetContext', {});
-    } else {
-      // Deactive current input method.
-      cpmmSendAsyncMessageWithKbID(this, 'Keyboard:Unregister', {});
-      if (this._inputcontext) {
-        this.setInputContext(null);
-      }
-    }
-  },
-
-  addInput: function(inputId, inputManifest) {
-    return this.createPromiseWithId(function(resolverId) {
-      let appId = this._window.document.nodePrincipal.appId;
-
-      cpmm.sendAsyncMessage('InputRegistry:Add', {
-        requestId: resolverId,
-        inputId: inputId,
-        inputManifest: inputManifest,
-        appId: appId
-      });
-    }.bind(this));
-  },
-
-  removeInput: function(inputId) {
-    return this.createPromiseWithId(function(resolverId) {
-      let appId = this._window.document.nodePrincipal.appId;
-
-      cpmm.sendAsyncMessage('InputRegistry:Remove', {
-        requestId: resolverId,
-        inputId: inputId,
-        appId: appId
-      });
-    }.bind(this));
-  },
-
-  setValue: function(value) {
-    cpmm.sendAsyncMessage('System:SetValue', {
-      'value': value
-    });
-  },
-
-  setSelectedOption: function(index) {
-    cpmm.sendAsyncMessage('System:SetSelectedOption', {
-      'index': index
-    });
-  },
-
-  setSelectedOptions: function(indexes) {
-    cpmm.sendAsyncMessage('System:SetSelectedOptions', {
-      'indexes': indexes
-    });
-  },
-
-  removeFocus: function() {
-    cpmm.sendAsyncMessage('System:RemoveFocus', {});
-  },
-
-  // Only the system app needs that, so instead of testing a permission which
-  // is allowed for all chrome:// url, we explicitly test that this is the
-  // system app's start URL.
-  _hasInputManagePerm: function(win) {
-    let url = win.location.href;
-    let systemAppIndex;
-    try {
-      systemAppIndex = Services.prefs.getCharPref('b2g.system_startup_url');
-    } catch(e) {
-      dump('MozKeyboard.jsm: no system app startup url set (pref is b2g.system_startup_url)');
-    }
-
-    dump(`MozKeyboard.jsm expecting ${systemAppIndex}\n`);
-    return url == systemAppIndex;
-  }
-};
-
-/**
- * ==============================================
- * InputContextDOMRequestIpcHelper
- * ==============================================
- */
-function InputContextDOMRequestIpcHelper(win) {
-  this.initDOMRequestHelper(win,
-    ["Keyboard:GetText:Result:OK",
-     "Keyboard:GetText:Result:Error",
-     "Keyboard:SetSelectionRange:Result:OK",
-     "Keyboard:ReplaceSurroundingText:Result:OK",
-     "Keyboard:SendKey:Result:OK",
-     "Keyboard:SendKey:Result:Error",
-     "Keyboard:SetComposition:Result:OK",
-     "Keyboard:EndComposition:Result:OK",
-     "Keyboard:SequenceError"]);
-}
-
-InputContextDOMRequestIpcHelper.prototype = {
-  __proto__: DOMRequestIpcHelper.prototype,
-  _inputContext: null,
-
-  attachInputContext: function(inputCtx) {
-    if (this._inputContext) {
-      throw new Error("InputContextDOMRequestIpcHelper: detach the context first.");
-    }
-
-    this._inputContext = inputCtx;
-  },
-
-  // Unset ourselves when the window is destroyed.
-  uninit: function() {
-    WindowMap.unsetInputContextIpcHelper(this._window);
-  },
-
-  detachInputContext: function() {
-    // All requests that are still pending need to be invalidated
-    // because the context is no longer valid.
-    this.forEachPromiseResolver(k => {
-      this.takePromiseResolver(k).reject("InputContext got destroyed");
-    });
-
-    this._inputContext = null;
-  },
-
-  receiveMessage: function(msg) {
-    if (!this._inputContext) {
-      dump('InputContextDOMRequestIpcHelper received message without context attached.\n');
-      return;
-    }
-
-    this._inputContext.receiveMessage(msg);
-  }
-};
-
-function MozInputContextSelectionChangeEventDetail(ctx, ownAction) {
-  this._ctx = ctx;
-  this.ownAction = ownAction;
-}
-
-MozInputContextSelectionChangeEventDetail.prototype = {
-  classID: Components.ID("ef35443e-a400-4ae3-9170-c2f4e05f7aed"),
-  QueryInterface: XPCOMUtils.generateQI([]),
-
-  ownAction: false,
-
-  get selectionStart() {
-    return this._ctx.selectionStart;
-  },
-
-  get selectionEnd() {
-    return this._ctx.selectionEnd;
-  }
-};
-
-function MozInputContextSurroundingTextChangeEventDetail(ctx, ownAction) {
-  this._ctx = ctx;
-  this.ownAction = ownAction;
-}
-
-MozInputContextSurroundingTextChangeEventDetail.prototype = {
-  classID: Components.ID("1c50fdaf-74af-4b2e-814f-792caf65a168"),
-  QueryInterface: XPCOMUtils.generateQI([]),
-
-  ownAction: false,
-
-  get text() {
-    return this._ctx.text;
-  },
-
-  get textBeforeCursor() {
-    return this._ctx.textBeforeCursor;
-  },
-
-  get textAfterCursor() {
-    return this._ctx.textAfterCursor;
-  }
-};
-
-/**
- * ==============================================
- * HardwareInput
- * ==============================================
- */
-function MozHardwareInput() {
-}
-
-MozHardwareInput.prototype = {
-  classID: Components.ID("{1e38633d-d08b-4867-9944-afa5c648adb6}"),
-  QueryInterface: XPCOMUtils.generateQI([]),
-};
-
-/**
- * ==============================================
- * InputContext
- * ==============================================
- */
-function MozInputContext(data) {
-  this._context = {
-    type: data.type,
-    inputType: data.inputType,
-    inputMode: data.inputMode,
-    lang: data.lang,
-    selectionStart: data.selectionStart,
-    selectionEnd: data.selectionEnd,
-    text: data.value
-  };
-
-  this._contextId = data.contextId;
-}
-
-MozInputContext.prototype = {
-  _window: null,
-  _context: null,
-  _contextId: -1,
-  _ipcHelper: null,
-  _hardwareinput: null,
-  _wrappedhardwareinput: null,
-
-  classID: Components.ID("{1e38633d-d08b-4867-9944-afa5c648adb6}"),
-
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIObserver,
-    Ci.nsISupportsWeakReference
-  ]),
-
-  init: function ic_init(win) {
-    this._window = win;
-
-    this._ipcHelper = WindowMap.getInputContextIpcHelper(win);
-    this._ipcHelper.attachInputContext(this);
-    this._hardwareinput = new MozHardwareInput();
-    this._wrappedhardwareinput =
-      this._window.MozHardwareInput._create(this._window, this._hardwareinput);
-  },
-
-  destroy: function ic_destroy() {
-    // A consuming application might still hold a cached version of
-    // this object. After destroying all methods will throw because we
-    // cannot create new promises anymore, but we still hold
-    // (outdated) information in the context. So let's clear that out.
-    for (var k in this._context) {
-      if (this._context.hasOwnProperty(k)) {
-        this._context[k] = null;
-      }
-    }
-
-    this._ipcHelper.detachInputContext();
-    this._ipcHelper = null;
-
-    this._window = null;
-    this._hardwareinput = null;
-    this._wrappedhardwareinput = null;
-  },
-
-  receiveMessage: function ic_receiveMessage(msg) {
-    if (!msg || !msg.json) {
-      dump('InputContext received message without data\n');
-      return;
-    }
-
-    let json = msg.json;
-    let resolver = this._ipcHelper.takePromiseResolver(json.requestId);
-
-    if (!resolver) {
-      dump('InputContext received invalid requestId.\n');
-      return;
-    }
-
-    // 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);
-        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":
-        resolver.reject(json.error);
-        break;
-      case "Keyboard:SetSelectionRange:Result:OK":
-      case "Keyboard:ReplaceSurroundingText:Result:OK":
-        resolver.resolve(
-          Cu.cloneInto(json.selectioninfo, this._window));
-        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);
-        break;
-      default:
-        dump("Could not find a handler for " + msg.name);
-        resolver.reject();
-        break;
-    }
-  },
-
-  updateSelectionContext: function ic_updateSelectionContext(data, ownAction) {
-    if (!this._context) {
-      return;
-    }
-
-    let selectionDirty =
-      this._context.selectionStart !== data.selectionStart ||
-      this._context.selectionEnd !== data.selectionEnd;
-    let surroundDirty = selectionDirty || data.text !== this._contextId.text;
-
-    this._context.text = data.text;
-    this._context.selectionStart = data.selectionStart;
-    this._context.selectionEnd = data.selectionEnd;
-
-    if (selectionDirty) {
-      let selectionChangeDetail =
-        new MozInputContextSelectionChangeEventDetail(this, ownAction);
-      let wrappedSelectionChangeDetail =
-        this._window.MozInputContextSelectionChangeEventDetail
-          ._create(this._window, selectionChangeDetail);
-      let selectionChangeEvent = new this._window.CustomEvent("selectionchange",
-        { cancelable: false, detail: wrappedSelectionChangeDetail });
-
-      this.__DOM_IMPL__.dispatchEvent(selectionChangeEvent);
-    }
-
-    if (surroundDirty) {
-      let surroundingTextChangeDetail =
-        new MozInputContextSurroundingTextChangeEventDetail(this, ownAction);
-      let wrappedSurroundingTextChangeDetail =
-        this._window.MozInputContextSurroundingTextChangeEventDetail
-          ._create(this._window, surroundingTextChangeDetail);
-      let selectionChangeEvent = new this._window.CustomEvent("surroundingtextchange",
-        { cancelable: false, detail: wrappedSurroundingTextChangeDetail });
-
-      this.__DOM_IMPL__.dispatchEvent(selectionChangeEvent);
-    }
-  },
-
-  // tag name of the input field
-  get type() {
-    return this._context.type;
-  },
-
-  // type of the input field
-  get inputType() {
-    return this._context.inputType;
-  },
-
-  get inputMode() {
-    return this._context.inputMode;
-  },
-
-  get lang() {
-    return this._context.lang;
-  },
-
-  getText: function ic_getText(offset, length) {
-    let text;
-    if (offset && length) {
-      text = this._context.text.substr(offset, length);
-    } else if (offset) {
-      text = this._context.text.substr(offset);
-    } else {
-      text = this._context.text;
-    }
-
-    return this._window.Promise.resolve(text);
-  },
-
-  get selectionStart() {
-    return this._context.selectionStart;
-  },
-
-  get selectionEnd() {
-    return this._context.selectionEnd;
-  },
-
-  get text() {
-    return this._context.text;
-  },
-
-  get textBeforeCursor() {
-    let text = this._context.text;
-    let start = this._context.selectionStart;
-    return (start < 100) ?
-      text.substr(0, start) :
-      text.substr(start - 100, 100);
-  },
-
-  get textAfterCursor() {
-    let text = this._context.text;
-    let start = this._context.selectionStart;
-    let end = this._context.selectionEnd;
-    return text.substr(start, end - start + 100);
-  },
-
-  get hardwareinput() {
-    return this._wrappedhardwareinput;
-  },
-
-  setSelectionRange: function ic_setSelectionRange(start, length) {
-    let self = this;
-    return this._sendPromise(function(resolverId) {
-      cpmmSendAsyncMessageWithKbID(self, 'Keyboard:SetSelectionRange', {
-        contextId: self._contextId,
-        requestId: resolverId,
-        selectionStart: start,
-        selectionEnd: start + length
-      });
-    });
-  },
-
-  get onsurroundingtextchange() {
-    return this.__DOM_IMPL__.getEventHandler("onsurroundingtextchange");
-  },
-
-  set onsurroundingtextchange(handler) {
-    this.__DOM_IMPL__.setEventHandler("onsurroundingtextchange", handler);
-  },
-
-  get onselectionchange() {
-    return this.__DOM_IMPL__.getEventHandler("onselectionchange");
-  },
-
-  set onselectionchange(handler) {
-    this.__DOM_IMPL__.setEventHandler("onselectionchange", handler);
-  },
-
-  replaceSurroundingText: function ic_replaceSurrText(text, offset, length) {
-    let self = this;
-    return this._sendPromise(function(resolverId) {
-      cpmmSendAsyncMessageWithKbID(self, 'Keyboard:ReplaceSurroundingText', {
-        contextId: self._contextId,
-        requestId: resolverId,
-        text: text,
-        offset: offset || 0,
-        length: length || 0
-      });
-    });
-  },
-
-  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,
-        requestId: resolverId,
-        method: 'keyup',
-        keyboardEventDict: this._getkeyboardEventDict(dict)
-      });
-    });
-  },
-
-  setComposition: function ic_setComposition(text, cursor, clauses, dict) {
-    let self = this;
-    return this._sendPromise((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)
-      });
-    });
-  },
-
-  endComposition: function ic_endComposition(text, dict) {
-    let self = this;
-    return this._sendPromise((resolverId) => {
-      cpmmSendAsyncMessageWithKbID(self, 'Keyboard:EndComposition', {
-        contextId: self._contextId,
-        requestId: resolverId,
-        text: text || '',
-        keyboardEventDict: this._getkeyboardEventDict(dict)
-      });
-    });
-  },
-
-  // Generate a new keyboard event by the received keyboard dictionary
-  // and return defaultPrevented's result of the event after dispatching.
-  forwardHardwareKeyEvent: function ic_forwardHardwareKeyEvent(data) {
-    if (!Ci.nsIHardwareKeyHandler) {
-      return;
-    }
-
-    if (!this._context) {
-      return Ci.nsIHardwareKeyHandler.NO_DEFAULT_PREVENTED;
-    }
-    let evt = new this._window.KeyboardEvent(data.type,
-                                             Cu.cloneInto(data.keyDict,
-                                                          this._window));
-    this._hardwareinput.__DOM_IMPL__.dispatchEvent(evt);
-    return this._getDefaultPreventedValue(evt);
-  },
-
-  _getDefaultPreventedValue: function(evt) {
-    if (!Ci.nsIHardwareKeyHandler) {
-      return;
-    }
-
-    let flags = Ci.nsIHardwareKeyHandler.NO_DEFAULT_PREVENTED;
-
-    if (evt.defaultPrevented) {
-      flags |= Ci.nsIHardwareKeyHandler.DEFAULT_PREVENTED;
-    }
-
-    if (evt.defaultPreventedByChrome) {
-      flags |= Ci.nsIHardwareKeyHandler.DEFAULT_PREVENTED_BY_CHROME;
-    }
-
-    if (evt.defaultPreventedByContent) {
-      flags |= Ci.nsIHardwareKeyHandler.DEFAULT_PREVENTED_BY_CONTENT;
-    }
-
-    return flags;
-  },
-
-  _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]);
deleted file mode 100644
--- a/dom/inputmethod/forms.js
+++ /dev/null
@@ -1,1561 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* 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/. */
-
-"use strict";
-
-dump("###################################### forms.js loaded\n");
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cu = Components.utils;
-var 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.
- */
-var 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;
-  }
-};
-
-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;
-
-var HTMLDocument = Ci.nsIDOMHTMLDocument;
-var HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
-var HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
-var HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
-var HTMLInputElement = Ci.nsIDOMHTMLInputElement;
-var HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
-var HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
-var HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
-var 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 "AudioVolumeMute";
-    case KeyboardEvent.DOM_VK_VOLUME_DOWN:
-      return "AudioVolumeDown";
-    case KeyboardEvent.DOM_VK_VOLUME_UP:
-      return "AudioVolumeUp";
-    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";
-  }
-}
-
-var 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) {
-    let win = node.ownerDocument.defaultView;
-
-    while (!(node instanceof HTMLBodyElement)) {
-
-      // We can skip elements that have not been scrolled.
-      // We only care about top now remember to add the scrollLeft
-      // check if we decide to care about the X axis.
-      if (node.scrollTop !== 0) {
-        // the element has been scrolled so we may need to adjust
-        // where we think the root element is located.
-        //
-        // Otherwise it may seem visible but be scrolled out of the viewport
-        // inside this scrollable node.
-        return node;
-      } else {
-        // this node does not effect where we think
-        // the node is even if it is scrollable it has not hidden
-        // the element we are looking for.
-        node = node.parentNode;
-        continue;
-      }
-    }
-
-    // we also care about the window this is the more
-    // common case where the content is larger then
-    // the viewport/screen.
-    if (win.scrollMaxX != win.scrollMinX || win.scrollMaxY != win.scrollMinY) {
-      return win;
-    }
-
-    return null;
-  },
-
-  /**
-   * Checks if "top  and "bottom" points of the position is visible.
-   *
-   * @param {Number} top position.
-   * @param {Number} height of the element.
-   * @param {Number} maxHeight of the window.
-   * @return {Boolean} true when visible.
-   */
-  yAxisVisible: function fv_yAxisVisible(top, height, maxHeight) {
-    return (top > 0 && (top + height) < maxHeight);
-  },
-
-  /**
-   * Searches up through the dom for scrollable elements
-   * which are not currently visible (relative to the viewport).
-   *
-   * @param {HTMLElement} element to start search at.
-   * @param {Object} pos .top, .height and .width of element.
-   */
-  scrollablesVisible: function fv_scrollablesVisible(element, pos) {
-    while ((element = this.findScrolled(element))) {
-      if (element.window && element.self === element)
-        break;
-
-      // remember getBoundingClientRect does not care
-      // about scrolling only where the element starts
-      // in the document.
-      let offset = element.getBoundingClientRect();
-
-      // the top of both the scrollable area and
-      // the form element itself are in the same document.
-      // We  adjust the "top" so if the elements coordinates
-      // are relative to the viewport in the current document.
-      let adjustedTop = pos.top - offset.top;
-
-      let visible = this.yAxisVisible(
-        adjustedTop,
-        pos.height,
-        offset.height
-      );
-
-      if (!visible)
-        return false;
-
-      element = element.parentNode;
-    }
-
-    return true;
-  },
-
-  /**
-   * Verifies the element is visible in the viewport.
-   * Handles scrollable areas, frames and scrollable viewport(s) (windows).
-   *
-   * @param {HTMLElement} element to verify.
-   * @return {Boolean} true when visible.
-   */
-  isVisible: function fv_isVisible(element) {
-    // scrollable frames can be ignored we just care about iframes...
-    let rect = element.getBoundingClientRect();
-    let parent = element.ownerDocument.defaultView;
-
-    // used to calculate the inner position of frames / scrollables.
-    // The intent was to use this information to scroll either up or down.
-    // scrollIntoView(true) will _break_ some web content so we can't do
-    // this today. If we want that functionality we need to manually scroll
-    // the individual elements.
-    let pos = {
-      top: rect.top,
-      height: rect.height,
-      width: rect.width
-    };
-
-    let visible = true;
-
-    do {
-      let frame = parent.frameElement;
-      visible = visible &&
-                this.yAxisVisible(pos.top, pos.height, parent.innerHeight) &&
-                this.scrollablesVisible(element, pos);
-
-      // nothing we can do about this now...
-      // In the future we can use this information to scroll
-      // only the elements we need to at this point as we should
-      // have all the details we need to figure out how to scroll.
-      if (!visible)
-        return false;
-
-      if (frame) {
-        let frameRect = frame.getBoundingClientRect();
-
-        pos.top += frameRect.top + frame.clientTop;
-      }
-    } while (
-      (parent !== parent.parent) &&
-      (parent = parent.parent)
-    );
-
-    return visible;
-  }
-};
-
-// This object implements nsITextInputProcessorCallback
-var 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;
-  }
-};
-
-var 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);
-    addEventListener("pagehide", this, true, false);
-    addEventListener("beforeunload", this, true, false);
-    addEventListener("input", this, true, false);
-    addEventListener("keydown", this, true, false);
-    addEventListener("keyup", this, true, false);
-    addMessageListener("Forms:Select:Choice", this);
-    addMessageListener("Forms:Input:Value", this);
-    addMessageListener("Forms:Select:Blur", this);
-    addMessageListener("Forms:SetSelectionRange", this);
-    addMessageListener("Forms:ReplaceSurroundingText", this);
-    addMessageListener("Forms:Input:SendKey", this);
-    addMessageListener("Forms:GetContext", this);
-    addMessageListener("Forms:SetComposition", this);
-    addMessageListener("Forms:EndComposition", this);
-  },
-
-  ignoredInputTypes: new Set([
-    'button', 'file', 'checkbox', 'radio', 'reset', 'submit', 'image',
-    'range'
-  ]),
-
-  isHandlingFocus: false,
-  selectionStart: -1,
-  selectionEnd: -1,
-  text: "",
-
-  scrollIntoViewTimeout: null,
-  _focusedElement: null,
-  _focusCounter: 0, // up one for every time we focus a new element
-  _focusDeleteObserver: null,
-  _focusContentObserver: null,
-  _documentEncoder: null,
-  _editor: null,
-  _editing: false,
-  _selectionPrivate: null,
-
-  get focusedElement() {
-    if (this._focusedElement && Cu.isDeadWrapper(this._focusedElement))
-      this._focusedElement = null;
-
-    return this._focusedElement;
-  },
-
-  set focusedElement(val) {
-    this._focusCounter++;
-    this._focusedElement = val;
-  },
-
-  setFocusedElement: function fa_setFocusedElement(element) {
-    let self = this;
-
-    if (element === this.focusedElement)
-      return;
-
-    if (this.focusedElement) {
-      this.focusedElement.removeEventListener('compositionend', this);
-      if (this._focusDeleteObserver) {
-        this._focusDeleteObserver.disconnect();
-        this._focusDeleteObserver = null;
-      }
-      if (this._focusContentObserver) {
-        this._focusContentObserver.disconnect();
-        this._focusContentObserver = null;
-      }
-      if (this._selectionPrivate) {
-        this._selectionPrivate.removeSelectionListener(this);
-        this._selectionPrivate = null;
-      }
-    }
-
-    this._documentEncoder = null;
-    if (this._editor) {
-      // When the nsIFrame of the input element is reconstructed by
-      // CSS restyling, the editor observers are removed. Catch
-      // [nsIEditor.removeEditorObserver] failure exception if that
-      // happens.
-      try {
-        this._editor.removeEditorObserver(this);
-      } catch (e) {}
-      this._editor = null;
-    }
-
-    if (element) {
-      element.addEventListener('compositionend', this);
-      if (isContentEditable(element)) {
-        this._documentEncoder = getDocumentEncoder(element);
-      }
-      this._editor = getPlaintextEditor(element);
-      if (this._editor) {
-        // Add a nsIEditorObserver to monitor the text content of the focused
-        // element.
-        this._editor.addEditorObserver(this);
-
-        let selection = this._editor.selection;
-        if (selection) {
-          this._selectionPrivate = selection.QueryInterface(Ci.nsISelectionPrivate);
-          this._selectionPrivate.addSelectionListener(this);
-        }
-      }
-
-      // If our focusedElement is removed from DOM we want to handle it properly
-      let MutationObserver = element.ownerDocument.defaultView.MutationObserver;
-      this._focusDeleteObserver = new MutationObserver(function(mutations) {
-        var del = [].some.call(mutations, function(m) {
-          return [].some.call(m.removedNodes, function(n) {
-            return n.contains(element);
-          });
-        });
-        if (del && element === self.focusedElement) {
-          self.unhandleFocus();
-        }
-      });
-
-      this._focusDeleteObserver.observe(element.ownerDocument.body, {
-        childList: true,
-        subtree: true
-      });
-
-      // If contenteditable, also add a mutation observer on its content and
-      // call selectionChanged when a change occurs
-      if (isContentEditable(element)) {
-        this._focusContentObserver = new MutationObserver(function() {
-          this.updateSelection();
-        }.bind(this));
-
-        this._focusContentObserver.observe(element, {
-          childList: true,
-          subtree: true
-        });
-      }
-    }
-
-    this.focusedElement = element;
-  },
-
-  notifySelectionChanged: function(aDocument, aSelection, aReason) {
-    this.updateSelection();
-  },
-
-  get documentEncoder() {
-    return this._documentEncoder;
-  },
-
-  // Get the nsIPlaintextEditor object of current input field.
-  get editor() {
-    return this._editor;
-  },
-
-  // Implements nsIEditorObserver get notification when the text content of
-  // current input field has changed.
-  EditAction: function fa_editAction() {
-    if (this._editing || !this.isHandlingFocus) {
-      return;
-    }
-    this.sendInputState(this.focusedElement);
-  },
-
-  handleEvent: function fa_handleEvent(evt) {
-    let target = evt.composedTarget;
-
-    let range = null;
-    switch (evt.type) {
-      case "focus":
-        if (!target) {
-          break;
-        }
-
-        // Focusing on Window, Document or iFrame should focus body
-        if (target instanceof HTMLHtmlElement) {
-          target = target.document.body;
-        } else if (target instanceof HTMLDocument) {
-          target = target.body;
-        } else if (target instanceof HTMLIFrameElement) {
-          target = target.contentDocument ? target.contentDocument.body
-                                          : null;
-        }
-
-        if (!target) {
-          break;
-        }
-
-        if (isContentEditable(target)) {
-          this.handleFocus(this.getTopLevelEditable(target));
-          this.updateSelection();
-          break;
-        }
-
-        if (this.isFocusableElement(target)) {
-          this.handleFocus(target);
-          this.updateSelection();
-        }
-        break;
-
-      case "pagehide":
-      case "beforeunload":
-        // We are only interested to the pagehide and beforeunload events from
-        // the root document.
-        if (target && target != content.document) {
-          break;
-        }
-        // fall through
-      case "submit":
-        if (this.focusedElement && !evt.defaultPrevented) {
-          this.focusedElement.blur();
-        }
-        break;
-
-      case "blur":
-        if (this.focusedElement) {
-          this.unhandleFocus();
-        }
-        break;
-
-      case "resize":
-        if (!this.isHandlingFocus)
-          return;
-
-        if (this.scrollIntoViewTimeout) {
-          content.clearTimeout(this.scrollIntoViewTimeout);
-          this.scrollIntoViewTimeout = null;
-        }
-
-        // We may receive multiple resize events in quick succession, so wait
-        // a bit before scrolling the input element into view.
-        if (this.focusedElement) {
-          this.scrollIntoViewTimeout = content.setTimeout(function () {
-            this.scrollIntoViewTimeout = null;
-            if (this.focusedElement && !FormVisibility.isVisible(this.focusedElement)) {
-              scrollSelectionOrElementIntoView(this.focusedElement);
-            }
-          }.bind(this), RESIZE_SCROLL_DELAY);
-        }
-        break;
-
-      case "keydown":
-        if (!this.focusedElement || this._editing) {
-          break;
-        }
-
-        CompositionManager.endComposition('');
-        break;
-
-      case "keyup":
-        if (!this.focusedElement || this._editing) {
-          break;
-        }
-
-        CompositionManager.endComposition('');
-        break;
-
-      case "compositionend":
-        if (!this.focusedElement) {
-          break;
-        }
-
-        CompositionManager.onCompositionEnd();
-        break;
-    }
-  },
-
-  receiveMessage: function fa_receiveMessage(msg) {
-    let target = this.focusedElement;
-    let json = msg.json;
-
-    // To not break mozKeyboard contextId is optional
-    if ('contextId' in json &&
-        json.contextId !== this._focusCounter &&
-        json.requestId) {
-      // Ignore messages that are meant for a previously focused element
-      sendAsyncMessage("Forms:SequenceError", {
-        requestId: json.requestId,
-        error: "Expected contextId " + this._focusCounter +
-               " but was " + json.contextId
-      });
-      return;
-    }
-
-    if (!target) {
-      return;
-    }
-
-    this._editing = true;
-    switch (msg.name) {
-      case "Forms:Input:Value": {
-        CompositionManager.endComposition('');
-
-        target.value = json.value;
-
-        let event = target.ownerDocument.createEvent('HTMLEvents');
-        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."
-            });
-          }
-
-          break;
-        }
-
-        // 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);
-
-        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) {
-          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()
-            });
-          }
-        }
-
-        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;
-            valueChanged = true;
-          }
-        } else if ("indexes" in json) {
-          for (let i = 0; i < options.length; i++) {
-            let newValue = (json.indexes.indexOf(i) != -1);
-            if (options.item(i).selected != newValue) {
-              options.item(i).selected = newValue;
-              valueChanged = true;
-            }
-          }
-        }
-
-        // only fire onchange event if any selected option is changed
-        if (valueChanged) {
-          let event = target.ownerDocument.createEvent('HTMLEvents');
-          event.initEvent('change', true, true);
-          target.dispatchEvent(event);
-        }
-        break;
-
-      case "Forms:Select:Blur": {
-        if (this.focusedElement) {
-          this.focusedElement.blur();
-        }
-
-        break;
-      }
-
-      case "Forms:SetSelectionRange":  {
-        CompositionManager.endComposition('');
-
-        let start = json.selectionStart;
-        let end =  json.selectionEnd;
-
-        if (!setSelectionRange(target, start, end)) {
-          if (json.requestId) {
-            sendAsyncMessage("Forms:SetSelectionRange:Result:Error", {
-              requestId: json.requestId,
-              error: "failed"
-            });
-          }
-          break;
-        }
-
-        if (json.requestId) {
-          sendAsyncMessage("Forms:SetSelectionRange:Result:OK", {
-            requestId: json.requestId,
-            selectioninfo: this.getSelectionInfo()
-          });
-        }
-        break;
-      }
-
-      case "Forms:ReplaceSurroundingText": {
-        CompositionManager.endComposition('');
-
-        if (!replaceSurroundingText(target,
-                                    json.text,
-                                    json.offset,
-                                    json.length)) {
-          if (json.requestId) {
-            sendAsyncMessage("Forms:ReplaceSurroundingText:Result:Error", {
-              requestId: json.requestId,
-              error: "failed"
-            });
-          }
-          break;
-        }
-
-        if (json.requestId) {
-          sendAsyncMessage("Forms:ReplaceSurroundingText:Result:OK", {
-            requestId: json.requestId,
-            selectioninfo: this.getSelectionInfo()
-          });
-        }
-        break;
-      }
-
-      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);
-        sendAsyncMessage("Forms:SetComposition:Result:OK", {
-          requestId: json.requestId,
-          selectioninfo: this.getSelectionInfo()
-        });
-        break;
-      }
-
-      case "Forms:EndComposition": {
-        CompositionManager.endComposition(json.text, json.keyboardEventDict);
-        sendAsyncMessage("Forms:EndComposition:Result:OK", {
-          requestId: json.requestId,
-          selectioninfo: this.getSelectionInfo()
-        });
-        break;
-      }
-    }
-    this._editing = false;
-
-  },
-
-  handleFocus: function fa_handleFocus(target) {
-    if (this.focusedElement === target)
-      return;
-
-    if (target instanceof HTMLOptionElement)
-      target = target.parentNode;
-
-    this.setFocusedElement(target);
-    this.sendInputState(target);
-    this.isHandlingFocus = true;
-  },
-
-  unhandleFocus: function fa_unhandleFocus() {
-    this.setFocusedElement(null);
-    this.isHandlingFocus = false;
-    this.selectionStart = -1;
-    this.selectionEnd = -1;
-    this.text = "";
-    sendAsyncMessage("Forms:Blur", {});
-  },
-
-  isFocusableElement: function fa_isFocusableElement(element) {
-    if (element instanceof HTMLSelectElement ||
-        element instanceof HTMLTextAreaElement)
-      return true;
-
-    if (element instanceof HTMLOptionElement &&
-        element.parentNode instanceof HTMLSelectElement)
-      return true;
-
-    return (element instanceof HTMLInputElement &&
-            !this.ignoredInputTypes.has(element.type) &&
-            !element.readOnly);
-  },
-
-  getTopLevelEditable: function fa_getTopLevelEditable(element) {
-    function retrieveTopLevelEditable(element) {
-      while (element && !isContentEditable(element))
-        element = element.parentNode;
-
-      return element;
-    }
-
-    return retrieveTopLevelEditable(element) || element;
-  },
-
-  sendInputState: function(element) {
-    sendAsyncMessage("Forms:Focus", getJSON(element, this._focusCounter));
-  },
-
-  getSelectionInfo: function fa_getSelectionInfo() {
-    let element = this.focusedElement;
-    let range =  getSelectionRange(element);
-
-    let text = isContentEditable(element) ? getContentEditableText(element)
-                                          : element.value;
-
-    let changed = this.selectionStart !== range[0] ||
-      this.selectionEnd !== range[1] ||
-      this.text !== text;
-
-    this.selectionStart = range[0];
-    this.selectionEnd = range[1];
-    this.text = text;
-
-    return {
-      selectionStart: range[0],
-      selectionEnd: range[1],
-      text: text,
-      changed: changed
-    };
-  },
-
-  _selectionTimeout: null,
-
-  // Notify when the selection range changes
-  updateSelection: function fa_updateSelection() {
-    // A call to setSelectionRange on input field causes 2 selection changes
-    // one to [0,0] and one to actual value. Both are sent in same tick.
-    // Prevent firing two events in that scenario, always only use the last 1.
-    //
-    // It is also a workaround for Bug 1053048, which prevents
-    // getSelectionInfo() accessing selectionStart or selectionEnd in the
-    // callback function of nsISelectionListener::NotifySelectionChanged().
-    if (this._selectionTimeout) {
-      content.clearTimeout(this._selectionTimeout);
-    }
-    this._selectionTimeout = content.setTimeout(function() {
-      if (!this.focusedElement) {
-        return;
-      }
-      let selectionInfo = this.getSelectionInfo();
-      if (selectionInfo.changed) {
-        sendAsyncMessage("Forms:SelectionChange", selectionInfo);
-      }
-    }.bind(this), 0);
-  }
-};
-
-FormAssistant.init();
-
-function isContentEditable(element) {
-  if (!element) {
-    return false;
-  }
-
-  if (element.isContentEditable || element.designMode == "on")
-    return true;
-
-  return element.ownerDocument && element.ownerDocument.designMode == "on";
-}
-
-function isPlainTextField(element) {
-  if (!element) {
-    return false;
-  }
-
-  return element instanceof HTMLTextAreaElement ||
-         (element instanceof HTMLInputElement &&
-          element.mozIsTextField(false));
-}
-
-function getJSON(element, focusCounter) {
-  // <input type=number> has a nested anonymous <input type=text> element that
-  // takes focus on behalf of the number control when someone tries to focus
-  // the number control. If |element| is such an anonymous text control then we
-  // need it's number control here in order to get the correct 'type' etc.:
-  element = element.ownerNumberControl || element;
-
-  let type = element.tagName.toLowerCase();
-  let inputType = (element.type || "").toLowerCase();
-  let value = element.value || "";
-  let max = element.max || "";
-  let min = element.min || "";
-
-  // Treat contenteditable element as a special text area field
-  if (isContentEditable(element)) {
-    type = "contenteditable";
-    inputType = "textarea";
-    value = getContentEditableText(element);
-  }
-
-  // Until the input type=date/datetime/range have been implemented
-  // let's return their real type even if the platform returns 'text'
-  let attributeInputType = element.getAttribute("type") || "";
-
-  if (attributeInputType) {
-    let inputTypeLowerCase = attributeInputType.toLowerCase();
-    switch (inputTypeLowerCase) {
-      case "datetime":
-      case "datetime-local":
-      case "month":
-      case "week":
-      case "range":
-        inputType = inputTypeLowerCase;
-        break;
-    }
-  }
-
-  // Gecko has some support for @inputmode but behind a preference and
-  // it is disabled by default.
-  // Gaia is then using @x-inputmode has its proprietary way to set
-  // inputmode for fields. This shouldn't be used outside of pre-installed
-  // apps because the attribute is going to disappear as soon as a definitive
-  // solution will be find.
-  let inputMode = element.getAttribute('x-inputmode');
-  if (inputMode) {
-    inputMode = inputMode.toLowerCase();
-  } else {
-    inputMode = '';
-  }
-
-  let range = getSelectionRange(element);
-
-  return {
-    "contextId": focusCounter,
-
-    "type": type,
-    "inputType": inputType,
-    "inputMode": inputMode,
-
-    "choices": getListForElement(element),
-    "value": value,
-    "selectionStart": range[0],
-    "selectionEnd": range[1],
-    "max": max,
-    "min": min,
-    "lang": element.lang || ""
-  };
-}
-
-function getListForElement(element) {
-  if (!(element instanceof HTMLSelectElement))
-    return null;
-
-  let optionIndex = 0;
-  let result = {
-    "multiple": element.multiple,
-    "choices": []
-  };
-
-  // Build up a flat JSON array of the choices.
-  // In HTML, it's possible for select element choices to be under a
-  // group header (but not recursively). We distinguish between headers
-  // and entries using the boolean "list.group".
-  let children = element.children;
-  for (let i = 0; i < children.length; i++) {
-    let child = children[i];
-
-    if (child instanceof HTMLOptGroupElement) {
-      result.choices.push({
-        "group": true,
-        "text": child.label || child.firstChild.data,
-        "disabled": child.disabled
-      });
-
-      let subchildren = child.children;
-      for (let j = 0; j < subchildren.length; j++) {
-        let subchild = subchildren[j];
-        result.choices.push({
-          "group": false,
-          "inGroup": true,
-          "text": subchild.text,
-          "disabled": child.disabled || subchild.disabled,
-          "selected": subchild.selected,
-          "optionIndex": optionIndex++
-        });
-      }
-    } else if (child instanceof HTMLOptionElement) {
-      result.choices.push({
-        "group": false,
-        "inGroup": false,
-        "text": child.text,
-        "disabled": child.disabled,
-        "selected": child.selected,
-        "optionIndex": optionIndex++
-      });
-    }
-  }
-
-  return result;
-};
-
-// Create a plain text document encode from the focused element.
-function getDocumentEncoder(element) {
-  let encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
-                .createInstance(Ci.nsIDocumentEncoder);
-  let flags = Ci.nsIDocumentEncoder.SkipInvisibleContent |
-              Ci.nsIDocumentEncoder.OutputRaw |
-              Ci.nsIDocumentEncoder.OutputDropInvisibleBreak |
-              // Bug 902847. Don't trim trailing spaces of a line.
-              Ci.nsIDocumentEncoder.OutputDontRemoveLineEndingSpaces |
-              Ci.nsIDocumentEncoder.OutputLFLineBreak |
-              Ci.nsIDocumentEncoder.OutputNonTextContentAsPlaceholder;
-  encoder.init(element.ownerDocument, "text/plain", flags);
-  return encoder;
-}
-
-// Get the visible content text of a content editable element
-function getContentEditableText(element) {
-  if (!element || !isContentEditable(element)) {
-    return null;
-  }
-
-  let doc = element.ownerDocument;
-  let range = doc.createRange();
-  range.selectNodeContents(element);
-  let encoder = FormAssistant.documentEncoder;
-  encoder.setRange(range);
-  return encoder.encodeToString();
-}
-
-function getSelectionRange(element) {
-  let start = 0;
-  let end = 0;
-  if (isPlainTextField(element)) {
-    // Get the selection range of <input> and <textarea> elements
-    start = element.selectionStart;
-    end = element.selectionEnd;
-  } else if (isContentEditable(element)){
-    // Get the selection range of contenteditable elements
-    let win = element.ownerDocument.defaultView;
-    let sel = win.getSelection();
-    if (sel && sel.rangeCount > 0) {
-      start = getContentEditableSelectionStart(element, sel);
-      end = start + getContentEditableSelectionLength(element, sel);
-    } else {
-      dump("Failed to get window.getSelection()\n");
-    }
-   }
-   return [start, end];
- }
-
-function getContentEditableSelectionStart(element, selection) {
-  let doc = element.ownerDocument;
-  let range = doc.createRange();
-  range.setStart(element, 0);
-  range.setEnd(selection.anchorNode, selection.anchorOffset);
-  let encoder = FormAssistant.documentEncoder;
-  encoder.setRange(range);
-  return encoder.encodeToString().length;
-}
-
-function getContentEditableSelectionLength(element, selection) {
-  let encoder = FormAssistant.documentEncoder;
-  encoder.setRange(selection.getRangeAt(0));
-  return encoder.encodeToString().length;
-}
-
-function setSelectionRange(element, start, end) {
-  let isTextField = isPlainTextField(element);
-
-  // Check the parameters
-
-  if (!isTextField && !isContentEditable(element)) {
-    // Skip HTMLOptionElement and HTMLSelectElement elements, as they don't
-    // support the operation of setSelectionRange
-    return false;
-  }
-
-  let text = isTextField ? element.value : getContentEditableText(element);
-  let length = text.length;
-  if (start < 0) {
-    start = 0;
-  }
-  if (end > length) {
-    end = length;
-  }
-  if (start > end) {
-    start = end;
-  }
-
-  if (isTextField) {
-    // Set the selection range of <input> and <textarea> elements
-    element.setSelectionRange(start, end, "forward");
-    return true;
-  } else {
-    // set the selection range of contenteditable elements
-    let win = element.ownerDocument.defaultView;
-    let sel = win.getSelection();
-
-    // Move the caret to the start position
-    sel.collapse(element, 0);
-    for (let i = 0; i < start; i++) {
-      sel.modify("move", "forward", "character");
-    }
-
-    // Avoid entering infinite loop in case we cannot change the selection
-    // range. See bug https://bugzilla.mozilla.org/show_bug.cgi?id=978918
-    let oldStart = getContentEditableSelectionStart(element, sel);
-    let counter = 0;
-    while (oldStart < start) {
-      sel.modify("move", "forward", "character");
-      let newStart = getContentEditableSelectionStart(element, sel);
-      if (oldStart == newStart) {
-        counter++;
-        if (counter > MAX_BLOCKED_COUNT) {
-          return false;
-        }
-      } else {
-        counter = 0;
-        oldStart = newStart;
-      }
-    }
-
-    // Extend the selection to the end position
-    for (let i = start; i < end; i++) {
-      sel.modify("extend", "forward", "character");
-    }
-
-    // Avoid entering infinite loop in case we cannot change the selection
-    // range. See bug https://bugzilla.mozilla.org/show_bug.cgi?id=978918
-    counter = 0;
-    let selectionLength = end - start;
-    let oldSelectionLength = getContentEditableSelectionLength(element, sel);
-    while (oldSelectionLength  < selectionLength) {
-      sel.modify("extend", "forward", "character");
-      let newSelectionLength = getContentEditableSelectionLength(element, sel);
-      if (oldSelectionLength == newSelectionLength ) {
-        counter++;
-        if (counter > MAX_BLOCKED_COUNT) {
-          return false;
-        }
-      } else {
-        counter = 0;
-        oldSelectionLength = newSelectionLength;
-      }
-    }
-    return true;
-  }
-}
-
-/**
- * Scroll the given element into view.
- *
- * Calls scrollSelectionIntoView for contentEditable elements.
- */
-function scrollSelectionOrElementIntoView(element) {
-  let editor = getPlaintextEditor(element);
-  if (editor) {
-    editor.selectionController.scrollSelectionIntoView(
-      Ci.nsISelectionController.SELECTION_NORMAL,
-      Ci.nsISelectionController.SELECTION_FOCUS_REGION,
-      Ci.nsISelectionController.SCROLL_SYNCHRONOUS);
-  } else {
-      element.scrollIntoView(false);
-  }
-}
-
-// Get nsIPlaintextEditor object from an input field
-function getPlaintextEditor(element) {
-  let editor = null;
-  // Get nsIEditor
-  if (isPlainTextField(element)) {
-    // Get from the <input> and <textarea> elements
-    editor = element.QueryInterface(Ci.nsIDOMNSEditableElement).editor;
-  } else if (isContentEditable(element)) {
-    // Get from content editable element
-    let win = element.ownerDocument.defaultView;
-    let editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIWebNavigation)
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIEditingSession);
-    if (editingSession) {
-      editor = editingSession.getEditorForWindow(win);
-    }
-  }
-  if (editor) {
-    editor.QueryInterface(Ci.nsIPlaintextEditor);
-  }
-  return editor;
-}
-
-function replaceSurroundingText(element, text, offset, length) {
-  let editor = FormAssistant.editor;
-  if (!editor) {
-    return false;
-  }
-
-  // Check the parameters.
-  if (length < 0) {
-    length = 0;
-  }
-
-  // Change selection range before replacing. For content editable element,
-  // searching the node for setting selection range is not needed when the
-  // selection is collapsed within a text node.
-  let fastPathHit = false;
-  if (!isPlainTextField(element)) {
-    let sel = element.ownerDocument.defaultView.getSelection();
-    let node = sel.anchorNode;
-    if (sel.isCollapsed && node && node.nodeType == 3 /* TEXT_NODE */) {
-      let start = sel.anchorOffset + offset;
-      let end = start + length;
-      // Fallback to setSelectionRange() if the replacement span multiple nodes.
-      if (start >= 0 && end <= node.textContent.length) {
-        fastPathHit = true;
-        sel.collapse(node, start);
-        sel.extend(node, end);
-      }
-    }
-  }
-  if (!fastPathHit) {
-    let range = getSelectionRange(element);
-    let start = range[0] + offset;
-    if (start < 0) {
-      start = 0;
-    }
-    let end = start + length;
-    if (start != range[0] || end != range[1]) {
-      if (!setSelectionRange(element, start, end)) {
-        return false;
-      }
-    }
-  }
-
-  if (length) {
-    // Delete the selected text.
-    editor.deleteSelection(Ci.nsIEditor.ePrevious, Ci.nsIEditor.eStrip);
-  }
-
-  if (text) {
-    // We don't use CR but LF
-    // see https://bugzilla.mozilla.org/show_bug.cgi?id=902847
-    text = text.replace(/\r/g, '\n');
-    // Insert the text to be replaced with.
-    editor.insertText(text);
-  }
-  return true;
-}
-
-var CompositionManager =  {
-  _isStarted: false,
-  _tip: null,
-  _KeyboardEventForWin: 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) {
-    // Check parameters.
-    if (!element) {
-      return;
-    }
-    let len = text.length;
-    if (cursor > len) {
-      cursor = len;
-    }
-    let clauseLens = [];
-    let clauseAttrs = [];
-    if (clauses) {
-      let remainingLength = len;
-      for (let i = 0; i < clauses.length; i++) {
-        if (clauses[i]) {
-          let clauseLength = clauses[i].length || 0;
-          // Make sure the total clauses length is not bigger than that of the
-          // composition string.
-          if (clauseLength > remainingLength) {
-            clauseLength = remainingLength;
-          }
-          remainingLength -= clauseLength;
-          clauseLens.push(clauseLength);
-          clauseAttrs.push(this._clauseAttrMap[clauses[i].selectionType] ||
-                           Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE);
-        }
-      }
-      // If the total clauses length is less than that of the composition
-      // string, extend the last clause to the end of the composition string.
-      if (remainingLength > 0) {
-        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) {
-      return;
-    }
-    // Update the composing text.
-    tip.setPendingCompositionString(text);
-    for (var i = 0; i < clauseLens.length; i++) {
-      if (!clauseLens[i]) {
-        continue;
-      }
-      tip.appendClauseToPendingComposition(clauseLens[i], clauseAttrs[i]);
-    }
-    if (cursor >= 0) {
-      tip.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;
-    }
-  },
-
-  endComposition: function cm_endComposition(text, dict) {
-    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._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;
-  }
-};
deleted file mode 100644
--- a/dom/inputmethod/jar.mn
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-
-toolkit.jar:
- content/global/forms.js                      (forms.js)
deleted file mode 100644
--- a/dom/inputmethod/mochitest/bug1110030_helper.js
+++ /dev/null
@@ -1,267 +0,0 @@
-// ***********************************
-// * Global variables
-// ***********************************
-const kIsWin = navigator.platform.indexOf("Win") == 0;
-
-// Bit value for the keyboard events
-const kKeyDown  = 0x01;
-const kKeyPress = 0x02;
-const kKeyUp    = 0x04;
-
-// Pair the event name to its bit value
-const kEventCode = {
-  'keydown'   : kKeyDown,
-  'keypress'  : kKeyPress,
-  'keyup'     : kKeyUp
-};
-
-// Holding the current test case's infomation:
-var gCurrentTest;
-
-// The current used input method of this test
-var gInputMethod;
-
-// ***********************************
-// * Utilities
-// ***********************************
-function addKeyEventListeners(eventTarget, handler)
-{
-  Object.keys(kEventCode).forEach(function(type) {
-    eventTarget.addEventListener(type, handler);
-  });
-}
-
-function eventToCode(type)
-{
-  return kEventCode[type];
-}
-
-// To test key events that will be generated by input method here,
-// we need to convert alphabets to native key code.
-// (Our input method for testing will handle alphabets)
-// On the other hand, to test key events that will not be generated by IME,
-// we use 0-9 for such case in our testing.
-function guessNativeKeyCode(key)
-{
-  let nativeCodeName = (kIsWin)? 'WIN_VK_' : 'MAC_VK_ANSI_';
-  if (/^[A-Z]$/.test(key)) {
-    nativeCodeName += key;
-  } else if (/^[a-z]$/.test(key)) {
-    nativeCodeName += key.toUpperCase();
-  } else if (/^[0-9]$/.test(key)) {
-    nativeCodeName += key.toString();
-  } else {
-    return 0;
-  }
-
-  return eval(nativeCodeName);
-}
-
-// ***********************************
-// * Frame loader and frame scripts
-// ***********************************
-function frameScript()
-{
-  function handler(e) {
-    sendAsyncMessage("forwardevent", { type: e.type, key: e.key });
-  }
-  function notifyFinish(e) {
-    if (e.type != 'keyup') return;
-    sendAsyncMessage("finish");
-  }
-  let input = content.document.getElementById('test-input');
-  input.addEventListener('keydown', handler);
-  input.addEventListener('keypress', handler);
-  input.addEventListener('keyup', handler);
-  input.addEventListener('keyup', notifyFinish);
-}
-
-function loadTestFrame(goNext) {
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_empty_app.html';
-  iframe.setAttribute('mozbrowser', true);
-
-  iframe.addEventListener("mozbrowserloadend", function onloadend() {
-    iframe.removeEventListener("mozbrowserloadend", onloadend);
-    iframe.focus();
-    var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-    mm.addMessageListener("forwardevent", function(msg) {
-      inputtextEventReceiver(msg.json);
-    });
-    mm.addMessageListener("finish", function(msg) {
-      if(goNext) {
-        goNext();
-      }
-    });
-    mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
-    return;
-  });
-
-  document.body.appendChild(iframe);
-}
-
-// ***********************************
-// * Event firer and listeners
-// ***********************************
-function fireEvent(callback)
-{
-  let key = gCurrentTest.key;
-  synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, guessNativeKeyCode(key), {},
-                      key, key, (callback) ? callback : null);
-}
-
-function hardwareEventReceiver(evt)
-{
-  if (!gCurrentTest) {
-    return;
-  }
-  gCurrentTest.hardwareinput.receivedEvents |= eventToCode(evt.type);
-  gCurrentTest.hardwareinput.receivedKeys += evt.key;
-}
-
-function inputtextEventReceiver(evt)
-{
-  if (!gCurrentTest) {
-    return;
-  }
-  gCurrentTest.inputtext.receivedEvents |= eventToCode(evt.type);
-  gCurrentTest.inputtext.receivedKeys += evt.key;
-}
-
-// ***********************************
-// * Event verifier
-// ***********************************
-function verifyResults(test)
-{
-  // Verify results received from inputcontent.hardwareinput
-  is(test.hardwareinput.receivedEvents,
-     test.hardwareinput.expectedEvents,
-     "received events from inputcontent.hardwareinput are wrong");
-
-  is(test.hardwareinput.receivedKeys,
-     test.hardwareinput.expectedKeys,
-     "received keys from inputcontent.hardwareinput are wrong");
-
-  // Verify results received from actual input text
-  is(test.inputtext.receivedEvents,
-     test.inputtext.expectedEvents,
-     "received events from input text are wrong");
-
-  is(test.inputtext.receivedKeys,
-     test.inputtext.expectedKeys,
-     "received keys from input text are wrong");
-}
-
-function areEventsSame(test)
-{
-  return (test.hardwareinput.receivedEvents ==
-          test.hardwareinput.expectedEvents) &&
-         (test.inputtext.receivedEvents ==
-          test.inputtext.expectedEvents);
-}
-
-// ***********************************
-// * Input Method
-// ***********************************
-// The method input used in this test
-// only handles alphabets
-function InputMethod(inputContext)
-{
-  this._inputContext = inputContext;
-  this.init();
-}
-
-InputMethod.prototype = {
-  init: function im_init() {
-    this._setKepMap();
-  },
-
-  handler: function im_handler(evt) {
-    // Ignore the key if the event is defaultPrevented
-    if (evt.defaultPrevented) {
-      return;
-    }
-
-    // Finish if there is no _inputContext
-    if (!this._inputContext) {
-      return;
-    }
-
-    // Generate the keyDict for inputcontext.keydown/keyup
-    let keyDict = this._generateKeyDict(evt);
-
-    // Ignore the key if IME doesn't want to handle it
-    if (!keyDict) {
-      return;
-    }
-
-    // Call preventDefault if the key will be handled.
-    evt.preventDefault();
-
-    // Call inputcontext.keydown/keyup
-    this._inputContext[evt.type](keyDict);
-  },
-
-  mapKey: function im_keymapping(key) {
-    if (!this._mappingTable) {
-      return;
-    }
-    return this._mappingTable[key];
-  },
-
-  _setKepMap: function im_setKeyMap() {
-    // A table to map characters:
-    // {
-    //   'A': 'B'
-    //   'a': 'b'
-    //   'B': 'C'
-    //   'b': 'c'
-    //   ..
-    //   ..
-    //   'Z': 'A',
-    //   'z': 'a',
-    // }
-    this._mappingTable = {};
-
-    let rotation = 1;
-
-    for (let i = 0 ; i < 26 ; i++) {
-      // Convert 'A' to 'B', 'B' to 'C', ..., 'Z' to 'A'
-      this._mappingTable[String.fromCharCode(i + 'A'.charCodeAt(0))] =
-        String.fromCharCode((i+rotation)%26 + 'A'.charCodeAt(0));
-
-      // Convert 'a' to 'b', 'b' to 'c', ..., 'z' to 'a'
-      this._mappingTable[String.fromCharCode(i + 'a'.charCodeAt(0))] =
-        String.fromCharCode((i+rotation)%26 + 'a'.charCodeAt(0));
-    }
-  },
-
-  _generateKeyDict: function im_generateKeyDict(evt) {
-
-    let mappedKey = this.mapKey(evt.key);
-
-    if (!mappedKey) {
-      return;
-    }
-
-    let keyDict = {
-      key: mappedKey,
-      code: this._guessCodeFromKey(mappedKey),
-      repeat: evt.repeat,
-    };
-
-    return keyDict;
-  },
-
-  _guessCodeFromKey: function im_guessCodeFromKey(key) {
-    if (/^[A-Z]$/.test(key)) {
-      return "Key" + key;
-    } else if (/^[a-z]$/.test(key)) {
-      return "Key" + key.toUpperCase();
-    } else if (/^[0-9]$/.test(key)) {
-      return "Digit" + key.toString();
-    } else {
-      return 0;
-    }
-  },
-};
deleted file mode 100644
--- a/dom/inputmethod/mochitest/chrome.ini
+++ /dev/null
@@ -1,52 +0,0 @@
-[DEFAULT]
-# dom/inputmethod only made sense on B2G
-skip-if = true
-support-files =
-  bug1110030_helper.js
-  inputmethod_common.js
-  file_inputmethod.html
-  file_blank.html
-  file_test_app.html
-  file_test_bug1066515.html
-  file_test_bug1137557.html
-  file_test_bug1175399.html
-  file_test_empty_app.html
-  file_test_focus_blur_manage_events.html
-  file_test_sendkey_cancel.html
-  file_test_setSupportsSwitching.html
-  file_test_simple_manage_events.html
-  file_test_sms_app.html
-  file_test_sms_app_1066515.html
-  file_test_sync_edit.html
-  file_test_two_inputs.html
-  file_test_two_selects.html
-  file_test_unload.html
-  file_test_unload_action.html
-
-[test_basic.html]
-[test_bug944397.html]
-[test_bug949059.html]
-[test_bug953044.html]
-[test_bug960946.html]
-[test_bug978918.html]
-[test_bug1026997.html]
-[test_bug1043828.html]
-[test_bug1059163.html]
-disabled = fails because receiving bad values
-[test_bug1066515.html]
-[test_bug1137557.html]
-[test_bug1175399.html]
-[test_focus_blur_manage_events.html]
-disabled = fails because receiving bad events # also depends on bug 1254823
-[test_forward_hardware_key_to_ime.html]
-skip-if = true # Test only ran on Mulet
-[test_input_registry_events.html]
-disabled = timeout on pine
-[test_sendkey_cancel.html]
-[test_setSupportsSwitching.html]
-[test_simple_manage_events.html]
-disabled = fails because receiving bad events
-[test_sync_edit.html]
-[test_two_inputs.html]
-[test_two_selects.html]
-[test_unload.html]
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_blank.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_inputmethod.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
-<body>
-<script>
-  var im = navigator.mozInputMethod;
-  if (im) {
-    im.oninputcontextchange = onIcc;
-
-    if (im.inputcontext) {
-      onIcc();
-    }
-  }
-
-  function onIcc() {
-    var ctx = im.inputcontext;
-    if (ctx) {
-      ctx.replaceSurroundingText(location.hash).then(function() {
-        /* Happy flow */
-      }, function(err) {
-        dump('ReplaceSurroundingText failed ' + err + '\n');
-      });
-    }
-  }
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_app.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<input id="test-input" type="text" value="Yuan" x-inputmode="verbatim" lang="zh"/>
-<script type="application/javascript;version=1.7">
-  let input = document.getElementById('test-input');
-  input.focus();
-  dump('file_test_app.html was loaded.');
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_bug1066515.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<div id="text" contenteditable>Jan Jongboom</div>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_bug1137557.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<textarea rows=30 cols=30></textarea>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_bug1175399.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><input value="First" readonly></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_empty_app.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<input id="test-input" type="text" value=""/>
-<script type="application/javascript;version=1.7">
-  let input = document.getElementById('test-input');
-  input.focus();
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_focus_blur_manage_events.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html><body>
-<input type="text">
-<input type="search">
-<textarea></textarea>
-<p contenteditable></p>
-<input type="number">
-<input type="tel">
-<input type="url">
-<input type="email">
-<input type="password">
-<input type="datetime">
-<input type="date" value="2015-08-03" min="1990-01-01" max="2020-01-01">
-<input type="month">
-<input type="week">
-<input type="time">
-<input type="datetime-local">
-<input type="color">
-<select><option selected>foo</option><option disabled>bar</option>
-<optgroup label="group"><option>baz</option></optgroup></select>
-<select multiple><option selected>foo</option><option disabled>bar</option>
-<optgroup label="group"><option>baz</option></optgroup></select>
-</body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_sendkey_cancel.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<input id="test-input" type="text" value="Yolo"/>
-<script type="application/javascript;version=1.7">
-  let input = document.getElementById('test-input');
-  input.focus();
-  
-  input.addEventListener('keydown', function(e) {
-    e.preventDefault();
-  });
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_setSupportsSwitching.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html><body>
-<input type="text">
-<input type="number">
-<input type="password">
-</body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_simple_manage_events.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><input type="text"></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_sms_app.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-  <div id="messages-input" x-inputmode="-moz-sms" contenteditable="true"
-    autofocus="autofocus">Httvb<br></div>
-  <script type="application/javascript;version=1.7">
-    let input = document.getElementById('messages-input');
-    input.focus();
-  </script>
-</body>
-</html>
- </div>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_sms_app_1066515.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-  <div id="messages-input" x-inputmode="-moz-sms" contenteditable="true"
-    autofocus="autofocus">fxos<br>hello <b>world</b></div>
-  <script type="application/javascript;version=1.7">
-    let input = document.getElementById('messages-input');
-    input.focus();
-  </script>
-</body>
-</html>
- </div>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_sync_edit.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><input value="First"></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_two_inputs.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><input value="First"><input value="Second"></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_two_selects.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><select><option>First</option></select><select><option>Second</option></select></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_unload.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><form id="form"><input value="First"><input type="submit"></form></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/file_test_unload_action.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body><input value="Second"></body></html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/inputmethod_common.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function inputmethod_setup(callback) {
-  SimpleTest.waitForExplicitFinish();
-  SimpleTest.requestCompleteLog();
-  let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1']
-                .getService(SpecialPowers.Ci.nsIXULAppInfo);
-  if (appInfo.name != 'B2G') {
-    SpecialPowers.Cu.import("resource://gre/modules/Keyboard.jsm", this);
-  }
-
-  let prefs = [
-    ['dom.mozBrowserFramesEnabled', true],
-    ['network.disable.ipc.security', true],
-    // Enable navigator.mozInputMethod.
-    ['dom.mozInputMethod.enabled', true]
-  ];
-  SpecialPowers.pushPrefEnv({set: prefs}, function() {
-    SimpleTest.waitForFocus(callback);
-  });
-}
-
-function inputmethod_cleanup() {
-  SpecialPowers.wrap(navigator.mozInputMethod).setActive(false);
-  SimpleTest.finish();
-}
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_basic.html
+++ /dev/null
@@ -1,212 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=932145
--->
-<head>
-  <title>Basic test for InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=932145">Mozilla Bug 932145</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-SimpleTest.requestFlakyTimeout("untriaged");
-
-// The input context.
-var gContext = null;
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    is(gContext.type, 'input', 'The input context type should match.');
-    is(gContext.inputType, 'text', 'The inputType should match.');
-    is(gContext.inputMode, 'verbatim', 'The inputMode should match.');
-    is(gContext.lang, 'zh', 'The language should match.');
-    is(gContext.text, 'Yuan', 'Should get the text.');
-    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Yuan',
-       'Should get the text around the cursor.');
-
-    test_setSelectionRange();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_app.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-}
-
-function test_setSelectionRange() {
-  // Move cursor position to 2.
-  gContext.setSelectionRange(2, 0).then(function() {
-    is(gContext.selectionStart, 2, 'selectionStart was set successfully.');
-    is(gContext.selectionEnd, 2, 'selectionEnd was set successfully.');
-    test_sendKey();
-  }, function(e) {
-    ok(false, 'setSelectionRange failed:' + e.name);
-    console.error(e);
-    inputmethod_cleanup();
-  });
-}
-
-function test_sendKey() {
-  // Add '-' to current cursor posistion and move the cursor position to 3.
-  gContext.sendKey(0, '-'.charCodeAt(0), 0).then(function() {
-    is(gContext.text, 'Yu-an',
-       'sendKey should changed the input field correctly.');
-    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Yu-an',
-       'sendKey should changed the input field correctly.');
-    test_deleteSurroundingText();
-  }, function(e) {
-    ok(false, 'sendKey failed:' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_deleteSurroundingText() {
-  // Remove one character before current cursor position and move the cursor
-  // position back to 2.
-  gContext.deleteSurroundingText(-1, 1).then(function() {
-    ok(true, 'deleteSurroundingText finished');
-    is(gContext.text, 'Yuan',
-       'deleteSurroundingText should changed the input field correctly.');
-    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Yuan',
-       'deleteSurroundingText should changed the input field correctly.');
-    test_replaceSurroundingText();
-  }, function(e) {
-    ok(false, 'deleteSurroundingText failed:' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_replaceSurroundingText() {
-  // Replace 'Yuan' with 'Xulei'.
-  gContext.replaceSurroundingText('Xulei', -2, 4).then(function() {
-    ok(true, 'replaceSurroundingText finished');
-    is(gContext.text, 'Xulei',
-       'replaceSurroundingText changed the input field correctly.');
-    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Xulei',
-       'replaceSurroundingText changed the input field correctly.');
-    test_setComposition();
-  }, function(e) {
-    ok(false, 'replaceSurroundingText failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_setComposition() {
-  gContext.setComposition('XXX').then(function() {
-    ok(true, 'setComposition finished');
-    test_endComposition();
-  }, function(e) {
-    ok(false, 'setComposition failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_endComposition() {
-  gContext.endComposition('2013').then(function() {
-    is(gContext.text, 'Xulei2013',
-       'endComposition changed the input field correctly.');
-    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Xulei2013',
-       'endComposition changed the input field correctly.');
-    test_onSelectionChange();
-  }, function (e) {
-    ok(false, 'endComposition failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_onSelectionChange() {
-  var sccTimeout = setTimeout(function() {
-    ok(false, 'selectionchange event not fired');
-    cleanup(true);
-  }, 3000);
-
-  function cleanup(failed) {
-    gContext.onselectionchange = null;
-    clearTimeout(sccTimeout);
-    if (failed) {
-      inputmethod_cleanup();
-    }
-    else {
-      test_onSurroundingTextChange();
-    }
-  }
-
-  gContext.onselectionchange = function(evt) {
-    ok(true, 'onselectionchange fired');
-    is(evt.detail.selectionStart, 10);
-    is(evt.detail.selectionEnd, 10);
-    ok(evt.detail.ownAction);
-  };
-
-  gContext.sendKey(0, 'j'.charCodeAt(0), 0).then(function() {
-    cleanup();
-  }, function(e) {
-    ok(false, 'sendKey failed: ' + e.name);
-    cleanup(true);
-  });
-}
-
-function test_onSurroundingTextChange() {
-  var sccTimeout = setTimeout(function() {
-    ok(false, 'surroundingtextchange event not fired');
-    cleanup(true);
-  }, 3000);
-
-  function cleanup(failed) {
-    gContext.onsurroundingtextchange = null;
-    clearTimeout(sccTimeout);
-    if (failed) {
-      inputmethod_cleanup();
-    }
-    else {
-      // in case we want more tests leave this
-      inputmethod_cleanup();
-    }
-  }
-
-  gContext.onsurroundingtextchange = function(evt) {
-    ok(true, 'onsurroundingtextchange fired');
-    is(evt.detail.text, 'Xulei2013jj');
-    is(evt.detail.textBeforeCursor, 'Xulei2013jj');
-    is(evt.detail.textAfterCursor, '');
-    ok(evt.detail.ownAction);
-  };
-
-  gContext.sendKey(0, 'j'.charCodeAt(0), 0).then(function() {
-    cleanup();
-  }, function(e) {
-    ok(false, 'sendKey failed: ' + e.name);
-    cleanup(true);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1026997.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1026997
--->
-<head>
-  <title>SelectionChange on InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1026997">Mozilla Bug 1026997</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-// The frame script running in file_test_app.html.
-function appFrameScript() {
-  let input = content.document.getElementById('test-input');
-
-  input.focus();
-
-  function next(start, end) {
-    input.setSelectionRange(start, end);
-  }
-
-  addMessageListener("test:KeyBoard:nextSelection", function(event) {
-    let json = event.json;
-    next(json[0], json[1]);
-  });
-}
-
-function runTest() {
-  let actions = [
-    [0, 4],
-    [1, 1],
-    [3, 3],
-    [2, 3]
-  ];
-
-  let counter = 0;
-  let mm = null;
-  let ic = null;
-
-  let im = navigator.mozInputMethod;
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    ic = im.inputcontext;
-    if (!ic) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    ic.onselectionchange = function() {
-      is(ic.selectionStart, actions[counter][0], "start");
-      is(ic.selectionEnd, actions[counter][1], "end");
-
-      if (++counter === actions.length) {
-        inputmethod_cleanup();
-        return;
-      }
-
-      next();
-    };
-
-    next();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  // Create an app frame to recieve keyboard inputs.
-  let app = document.createElement('iframe');
-  app.src = 'file_test_app.html';
-  app.setAttribute('mozbrowser', true);
-  document.body.appendChild(app);
-  app.addEventListener('mozbrowserloadend', function() {
-    mm = SpecialPowers.getBrowserFrameMessageManager(app);
-    mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
-    next();
-  });
-
-  function next() {
-    if (ic && mm) {
-      mm.sendAsyncMessage('test:KeyBoard:nextSelection', actions[counter]);
-    }
-  }
-}
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1043828.html
+++ /dev/null
@@ -1,183 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1043828
--->
-<head>
-  <title>Basic test for Switching Keyboards.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1043828">Mozilla Bug 1043828</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-SimpleTest.requestFlakyTimeout("untriaged");
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-// The KB frame script running in Keyboard B.
-function kbFrameScript() {
-  function tryGetText() {
-    var ctx = content.navigator.mozInputMethod.inputcontext;
-    if (ctx) {
-      var p = ctx.getText();
-      p.then(function(){
-        sendAsyncMessage('test:InputMethod:getText:Resolve');
-      }, function(e){
-        sendAsyncMessage('test:InputMethod:getText:Reject');
-      });
-    } else {
-      dump("Could not get inputcontext") ;
-    }
-  }
-
-  addMessageListener('test:InputMethod:getText:Do', function(){
-    tryGetText();
-  });
-}
-
-function runTest() {
-  let app, keyboardA, keyboardB;
-  let getTextPromise;
-  let mmKeyboardA, mmKeyboardB;
-
-  /**
-   * Test flow:
-   * 1. Create two keyboard iframes & a mozbrowser iframe with a text field in it & focus the text
-   *    field.
-   * 2. Set keyboard frame A as active input. Wait 200ms.
-   * 3. Set keyboard frame B as active input. Wait 200ms.
-   * 4. Set keyboard frame A as inactive. Wait 200ms.
-   * 5. Allow frame b to use getText() with inputcontext to get the content from the text field
-   *    iframe. Wait 200ms.
-   * [Test would succeed if the Promise returned by getText() resolves correctly.
-   *  Test would fail if otherwise]
-   */
-
-  let path = location.pathname;
-  let basePath = location.protocol + '//' + location.host +
-               path.substring(0, path.lastIndexOf('/'));
-
-  const WAIT_TIME = 200;
-
-  // STEP 1: Create the frames.
-  function step1() {
-    // app
-    app = document.createElement('iframe');
-    app.src = basePath + '/file_test_app.html';
-    app.setAttribute('mozbrowser', true);
-    document.body.appendChild(app);
-
-    // keyboards
-    keyboardA = document.createElement('iframe');
-    keyboardA.setAttribute('mozbrowser', true);
-    document.body.appendChild(keyboardA);
-
-    keyboardB = document.createElement('iframe');
-    keyboardB.setAttribute('mozbrowser', true);
-    document.body.appendChild(keyboardB);
-
-    // simulate two different keyboard apps
-    let imeUrl = basePath + '/file_blank.html';
-
-    keyboardA.src = imeUrl;
-    keyboardB.src = imeUrl;
-
-    var handler = {
-      handleEvent: function(){
-        keyboardB.removeEventListener('mozbrowserloadend', this);
-
-        mmKeyboardB = SpecialPowers.getBrowserFrameMessageManager(keyboardB);
-
-        mmKeyboardB.loadFrameScript('data:,(' + kbFrameScript.toString() + ')();', false);
-
-        mmKeyboardB.addMessageListener('test:InputMethod:getText:Resolve', function() {
-          info('getText() was resolved');
-          inputmethod_cleanup();
-        });
-
-        mmKeyboardB.addMessageListener('test:InputMethod:getText:Reject', function() {
-          ok(false, 'getText() was rejected');
-          inputmethod_cleanup();
-        });
-
-        setTimeout(function(){
-          step2();
-        }, WAIT_TIME);
-      }
-    };
-
-    keyboardB.addEventListener('mozbrowserloadend', handler);
-  }
-
-  // STEP 2: Set keyboard A active
-  function step2() {
-    info('step2');
-    let req = keyboardA.setInputMethodActive(true);
-
-    req.onsuccess = function(){
-      setTimeout(function(){
-        step3();
-      }, WAIT_TIME);
-    };
-
-    req.onerror = function(){
-      ok(false, 'setInputMethodActive failed: ' + this.error.name);
-      inputmethod_cleanup();
-    };
-  }
-
-  // STEP 3: Set keyboard B active
-  function step3() {
-    info('step3');
-    let req = keyboardB.setInputMethodActive(true);
-
-    req.onsuccess = function(){
-      setTimeout(function(){
-        step4();
-      }, WAIT_TIME);
-    };
-
-    req.onerror = function(){
-      ok(false, 'setInputMethodActive failed: ' + this.error.name);
-      inputmethod_cleanup();
-    };
-  }
-
-  // STEP 4: Set keyboard A inactive
-  function step4() {
-    info('step4');
-    let req = keyboardA.setInputMethodActive(false);
-
-    req.onsuccess = function(){
-      setTimeout(function(){
-        step5();
-      }, WAIT_TIME);
-    };
-
-    req.onerror = function(){
-      ok(false, 'setInputMethodActive failed: ' + this.error.name);
-      inputmethod_cleanup();
-    };
-  }
-
-  // STEP 5: getText
-  function step5() {
-    info('step5');
-    mmKeyboardB.sendAsyncMessage('test:InputMethod:getText:Do');
-  }
-
-  step1();
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1059163.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1059163
--->
-<head>
-  <title>Basic test for repeat sendKey events</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1059163">Mozilla Bug 1059163</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-inputmethod_setup(function() {
-  runTest();
-});
-
-// The frame script running in the file
-function appFrameScript() {
-  let document = content.document;
-  let window = content.document.defaultView;
-
-  let t = document.getElementById('text');
-  t.focus();
-
-  let range = document.createRange();
-  range.selectNodeContents(t);
-  range.collapse(false);
-  let selection = window.getSelection();
-  selection.removeAllRanges();
-  selection.addRange(range);
-
-  addMessageListener('test:InputMethod:clear', function() {
-    t.innerHTML = '';
-  });
-}
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  // Create an app frame to recieve keyboard inputs.
-  let app = document.createElement('iframe');
-  app.src = 'file_test_bug1066515.html';
-  app.setAttribute('mozbrowser', true);
-  document.body.appendChild(app);
-
-  app.addEventListener('mozbrowserloadend', function() {
-    let mm = SpecialPowers.getBrowserFrameMessageManager(app);
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-
-    im.oninputcontextchange = function() {
-      is(im.inputcontext.type, 'contenteditable', 'type');
-      is(im.inputcontext.inputType, 'textarea', 'inputType');
-
-      if (im.inputcontext) {
-        im.oninputcontextchange = null;
-        register();
-      }
-    };
-
-    function register() {
-      im.inputcontext.onselectionchange = function() {
-        im.inputcontext.onselectionchange = null;
-
-        is(im.inputcontext.textBeforeCursor, '', 'textBeforeCursor');
-        is(im.inputcontext.textAfterCursor, '', 'textAfterCursor');
-        is(im.inputcontext.selectionStart, 0, 'selectionStart');
-        is(im.inputcontext.selectionEnd, 0, 'selectionEnd');
-
-        inputmethod_cleanup();
-      };
-
-      mm.sendAsyncMessage('test:InputMethod:clear');
-    }
-  });
-}
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1066515.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1066515
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1066515</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1066515">Mozilla Bug 1066515</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-// The input context.
-var gContext = null;
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    test_replaceSurroundingTextWithinTextNode();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_sms_app_1066515.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-}
-
-function test_replaceSurroundingTextWithinTextNode() {
-  // Set cursor position after 'f'.
-  gContext.setSelectionRange(1, 0);
-
-  // Replace 'fxos' to 'Hitooo' which the range is within current text node.
-  gContext.replaceSurroundingText('Hitooo', -1, 4).then(function() {
-    gContext.getText().then(function(text) {
-      is(text, 'Hitooo\nhello world', 'replaceSurroundingText successfully.');
-      test_replaceSurroundingTextSpanMultipleNodes();
-    }, function(e) {
-      ok(false, 'getText failed: ' + e.name);
-      inputmethod_cleanup();
-    });
-  }, function(e) {
-    ok(false, 'replaceSurroundingText failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_replaceSurroundingTextSpanMultipleNodes() {
-  // Set cursor position to the beginning.
-  gContext.setSelectionRange(0, 0);
-
-  // Replace whole content editable element to 'abc'.
-  gContext.replaceSurroundingText('abc', 0, 100).then(function() {
-    gContext.getText().then(function(text) {
-      is(text, 'abc', 'replaceSurroundingText successfully.');
-      inputmethod_cleanup();
-    }, function(e) {
-      ok(false, 'getText failed: ' + e.name);
-      inputmethod_cleanup();
-    });
-  }, function(e) {
-    ok(false, 'replaceSurroundingText failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1137557.html
+++ /dev/null
@@ -1,1799 +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="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/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: expectedValues.location ? expectedValues.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: expectedValues.location ? expectedValues.location : 0,
-          repeat: expectedValues.repeat || false,
-          value: gCurrentValue,
-          shift: false,
-          capsLock: false,
-          control: false,
-          alt: false
-        });
-      }
-
-      if (testdata.expectedInput) {
-        switch (testdata.expectedInput) {
-          case 'Enter':
-            gCurrentValue += '\n';
-            break;
-          case 'Backspace':
-            gCurrentValue =
-              gCurrentValue.substr(0, gCurrentValue.length - 1);
-            break;
-          default:
-            gCurrentValue += testdata.expectedInput;
-            break;
-        }
-
-        expectedEventDetail.push({
-          type: 'input',
-          value: gCurrentValue
-        });
-      }
-
-      if (!testdata.expectedRepeat) {
-        expectedEventDetail.push({
-          type: 'keyup',
-          key: expectedValues.key,
-          charCode: 0,
-          code: expectedValues.code || '',
-          keyCode: expectedValues.keyCode || 0,
-          location: expectedValues.location ? expectedValues.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 runSendKeyNumpadTests() {
-  gTestDescription = 'runSendKeyNumpadTests(): ';
-  var promiseQueue = Promise.resolve();
-
-  var tests = [];
-  ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
-    .forEach(function(key) {
-      let charCode = key.charCodeAt(0);
-
-      tests.push({
-        dict: {
-          key: key,
-          code: 'Numpad' + key
-        },
-        expectedKeypress: true,
-        expectedInput: key,
-        expectedValues: {
-          key: key, code: 'Numpad' + key,
-          keyCode: charCode, charCode: charCode,
-          location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
-        }
-      });
-    });
-
-  [['+', 'NumpadAdd'],
-   [',', 'NumpadComma'],
-   ['.', 'NumpadDecimal'],
-   ['.', 'NumpadComma'],  // Locale-specific NumpadComma
-   [',', 'NumpadDecimal'],  // Locale-specific NumpadDecimal
-   ['/', 'NumpadDivide'],
-   ['=', 'NumpadEqual'],
-   // ['#', 'NumpadHash'], // Not supported yet.
-   ['*', 'NumpadMultiply'],
-   ['(', 'NumpadParenLeft'],
-   [')', 'NumpadParenRight'],
-   // ['*', 'NumpadStar'], // Not supported yet.
-   ['-', 'NumpadSubtract']].forEach(function([key, code]) {
-    tests.push({
-      dict: {
-        key: key,
-        code: code
-      },
-      expectedKeypress: true,
-      expectedInput: key,
-      expectedValues: {
-        key: key, code: code, keyCode: 0, charCode: key.charCodeAt(0),
-        location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
-      }
-    });
-  });
-
-  [
-    'NumpadComma', // Locale-specific NumpadComma -- outputs nothing
-    'NumpadClear',
-    'NumpadClearEntry',
-    'NumpadMemoryAdd',
-    'NumpadMemoryClear',
-    'NumpadMemoryRecall',
-    'NumpadMemoryStore',
-    'NumpadMemorySubtract'
-  ].forEach(function(code) {
-    tests.push({
-      dict: {
-        key: 'Unidentified',
-        code: code
-      },
-      expectedKeypress: true,
-      expectedValues: {
-        key: 'Unidentified', code: code, keyCode: 0, charCode: 0,
-        location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
-      }
-    });
-  });
-
-  tests.push({
-    dict: {
-      key: 'Enter',
-      code: 'NumpadEnter'
-    },
-    expectedKeypress: true,
-    expectedInput: '\n',
-    expectedValues: {
-      key: 'Enter', code: 'NumpadEnter',
-      keyCode: KeyboardEvent.DOM_VK_RETURN, charCode: 0,
-      location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
-    }
-  });
-
-  tests.push({
-    dict: {
-      key: 'Backspace',
-      code: 'NumpadBackspace'
-    },
-    expectedKeypress: true,
-    expectedInput: 'Backspace', // Special value
-    expectedValues: {
-      key: 'Backspace', code: 'NumpadBackspace',
-      keyCode: KeyboardEvent.DOM_VK_BACK_SPACE, charCode: 0,
-      location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
-    }
-  });
-
-  tests.forEach((test) => {
-    promiseQueue = promiseQueue.then(() => {
-      return sendKeyAndAssertResult(test);
-    });
-  });
-
-  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 = 'file_test_bug1137557.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(() => runSendKeyNumpadTests())
-    .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>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug1175399.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1175399
--->
-<head>
-  <title>Test focus when page unloads</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175399">Mozilla Bug 1175399</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let input = content.document.body.firstElementChild;
-  input.focus();
-
-  content.setTimeout(function() {
-    sendAsyncMessage('test:step');
-  });
-};
-
-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 = 'file_test_bug1175399.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-  im.oninputcontextchange = function() {
-    is(false, 'should not receive inputcontextchange event');
-  };
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.addMessageListener('test:step', function() {
-      let inputcontext = navigator.mozInputMethod.inputcontext;
-      is(inputcontext, null, 'inputcontext is null');
-
-      inputmethod_cleanup();
-    });
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug944397.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=944397
--->
-<head>
-  <title>Basic test for InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=944397">Mozilla Bug 944397</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-SimpleTest.requestFlakyTimeout("untriaged");
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-// The frame script running in file_test_app.html.
-function appFrameScript() {
-  let input = content.document.getElementById('test-input');
-  input.oninput = function() {
-    sendAsyncMessage('test:InputMethod:oninput', {
-      value: input.value
-    });
-  };
-}
-
-function runTest() {
-  let app, keyboard;
-
-  /**
-   * So this test does the following:
-   * 1. Create a mozbrowser iframe with a text field in it, and focus the text field
-   * 2. 100ms. after loading we create new keyboard iframe, that will try to execute
-   *    replaceSurroundingText on the current active inputcontext
-   * 3. That should trigger 'input' event on the said text field
-   * 4. And if that happens we know everything is OK
-   */
-
-  let path = location.pathname;
-  let basePath = location.protocol + '//' + location.host +
-               path.substring(0, path.lastIndexOf('/'));
-
-  // STEP 1: Create an app frame to recieve keyboard inputs.
-  function step1() {
-    app = document.createElement('iframe');
-    app.src = basePath + '/file_test_app.html';
-    app.setAttribute('mozbrowser', true);
-    document.body.appendChild(app);
-    app.addEventListener('mozbrowserloadend', function() {
-      let mm = SpecialPowers.getBrowserFrameMessageManager(app);
-      mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
-      mm.addMessageListener("test:InputMethod:oninput", function(ev) {
-        step4(SpecialPowers.wrap(ev).json.value);
-      });
-
-      step2();
-    });
-  }
-
-  function step2() {
-    // STEP 2a: Create a browser frame to load the input method app.
-    keyboard = document.createElement('iframe');
-    keyboard.setAttribute('mozbrowser', true);
-    document.body.appendChild(keyboard);
-
-    // STEP 2b: Grant input privileges to the keyboard iframe
-    let imeUrl = basePath + '/file_inputmethod.html#data';
-
-    // STEP 2c: Tell Gecko to use this iframe as its keyboard app
-    let req = keyboard.setInputMethodActive(true);
-
-    req.onsuccess = function() {
-      ok(true, 'setInputMethodActive succeeded.');
-    };
-
-    req.onerror = function() {
-      ok(false, 'setInputMethodActive failed: ' + this.error.name);
-      inputmethod_cleanup();
-    };
-
-    // STEP 3: Loads the input method app to the browser frame after a delay.
-    setTimeout(function() {
-      keyboard.src = imeUrl;
-    }, 100);
-  }
-
-  function step4(val) {
-    ok(true, 'Keyboard input was received.');
-    is(val, '#dataYuan', 'Input value');
-    inputmethod_cleanup();
-  }
-
-  step1();
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug949059.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=949059
--->
-<head>
-  <title>Test "mgmt" property of MozInputMethod.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=949059">Mozilla Bug 949059</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  // Treat current page as an input method and activate it.
-  SpecialPowers.wrap(im).setActive(true);
-  ok(im.mgmt, 'The mgmt property should not be null.');
-
-  // Deactivate current page.
-  SpecialPowers.wrap(im).setActive(false);
-  ok(im.mgmt, 'The mgmt property should not be null.');
-
-  inputmethod_cleanup();
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug953044.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=953044
--->
-<head>
-  <title>Basic test for InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=953044">Mozilla Bug 953044</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  // Create an app frame to recieve keyboard inputs.
-  let app = document.createElement('iframe');
-  app.src = 'file_test_app.html';
-  app.setAttribute('mozbrowser', true);
-  document.body.appendChild(app);
-
-  // Create a browser frame to load the input method app.
-  let keyboard = document.createElement('iframe');
-  keyboard.setAttribute('mozbrowser', true);
-  document.body.appendChild(keyboard);
-
-  // Bug 953044 setInputMethodActive(false) before input method app loads should
-  // always succeed.
-  let req = keyboard.setInputMethodActive(false);
-  req.onsuccess = function() {
-    ok(true, 'setInputMethodActive before loading succeeded.');
-    inputmethod_cleanup();
-  };
-
-  req.onerror = function() {
-    ok(false, 'setInputMethodActive before loading failed: ' + this.error.name);
-    inputmethod_cleanup();
-  };
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug960946.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=960946
--->
-<head>
-  <title>Basic test for repeat sendKey events</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=960946">Mozilla Bug 960946</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-// The input context.
-var gContext = null;
-var gCounter = 0;
-var gBackSpaceCounter = 0;
-var result = ["keydown", "keypress", "keydown","keypress",
-              "keydown", "keypress", "keyup"
-             ];
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-var input;
-// The frame script running in file_test_backspace_event.html.
-function appFrameScript() {
-  let input = content.document.getElementById('test-input');
-  input.onkeydown = input.onkeypress = input.onkeyup = function(event) {
-    dump('key event was fired in file_test_backspace_event.html: ' + event.type +'\n');
-    sendAsyncMessage('test:KeyBoard:keyEvent', {'type':event.type});
-  };
-}
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    test_sendKey();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  // Create an app frame to recieve keyboard inputs.
-  let app = document.createElement('iframe');
-  app.src = 'file_test_app.html';
-  app.setAttribute('mozbrowser', true);
-  document.body.appendChild(app);
-  app.addEventListener('mozbrowserloadend', function() {
-    let mm = SpecialPowers.getBrowserFrameMessageManager(app);
-    mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
-    mm.addMessageListener("test:KeyBoard:keyEvent", function(event) {
-      ok(true, 'Keyboard input was received.');
-      is(SpecialPowers.wrap(event).json.type, result[gCounter], "expected event");
-      gCounter++;
-    });
-  });
-}
-
-function test_sendKey() {
-  // Move cursor position to 4.
-  gContext.setSelectionRange(4, 0).then(function() {
-    is(gContext.selectionStart, 4, 'selectionStart was set successfully.');
-    is(gContext.selectionEnd, 4, 'selectionEnd was set successfully.');
-    for(let i = 0; i < 2; i++) {
-      test_sendBackspace(true);
-    }
-    test_sendBackspace(false);
-  }, function(e) {
-    ok(false, 'setSelectionRange failed:' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_sendBackspace(repeat) {
-  // Send backspace
-  gContext.sendKey(KeyEvent.DOM_VK_BACK_SPACE, 0, 0, repeat).then(function() {
-    ok(true, 'sendKey success');
-    gBackSpaceCounter++;
-    if (gBackSpaceCounter == 3) {
-      inputmethod_cleanup();
-    }
-  }, function(e) {
-    ok(false, 'sendKey failed:' + e.name);
-    inputmethod_cleanup();
-  });
-}
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_bug978918.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=978918
--->
-<head>
-  <title>Basic test for InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=978918">Mozilla Bug 978918</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-// The input context.
-var gContext = null;
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    test_setSelectionRange();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_sms_app.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-}
-
-function test_setSelectionRange() {
-  gContext.setSelectionRange(0, 100).then(function() {
-    is(gContext.selectionStart, 0, 'selectionStart was set successfully.');
-    is(gContext.selectionEnd, 5, 'selectionEnd was set successfully.');
-    test_replaceSurroundingText();
-  }, function(e) {
-    ok(false, 'setSelectionRange failed:' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-function test_replaceSurroundingText() {
-  // Replace 'Httvb' with 'Hito'.
-  gContext.replaceSurroundingText('Hito', 0, 100).then(function() {
-    ok(true, 'replaceSurroundingText finished');
-    inputmethod_cleanup();
-  }, function(e) {
-    ok(false, 'replaceSurroundingText failed: ' + e.name);
-    inputmethod_cleanup();
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_focus_blur_manage_events.html
+++ /dev/null
@@ -1,199 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
--->
-<head>
-  <title>Test inputcontextfocus and inputcontextblur event</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-let contentFrameMM;
-
-function setupTestRunner() {
-  info('setupTestRunner');
-  let im = navigator.mozInputMethod;
-
-  let expectedEventDetails = [
-    { type: 'input', inputType: 'text' },
-    { type: 'input', inputType: 'search' },
-    { type: 'textarea', inputType: 'textarea' },
-    { type: 'contenteditable', inputType: 'textarea' },
-    { type: 'input', inputType: 'number' },
-    { type: 'input', inputType: 'tel' },
-    { type: 'input', inputType: 'url' },
-    { type: 'input', inputType: 'email' },
-    { type: 'input', inputType: 'password' },
-    { type: 'input', inputType: 'datetime' },
-    { type: 'input', inputType: 'date',
-      value: '2015-08-03', min: '1990-01-01', max: '2020-01-01' },
-    { type: 'input', inputType: 'month' },
-    { type: 'input', inputType: 'week' },
-    { type: 'input', inputType: 'time' },
-    { type: 'input', inputType: 'datetime-local' },
-    { type: 'input', inputType: 'color' },
-    { type: 'select', inputType: 'select-one',
-      choices: {
-        multiple: false,
-        choices: [
-          { group: false, inGroup: false, text: 'foo',
-            disabled: false, selected: true, optionIndex: 0 },
-          { group: false, inGroup: false, text: 'bar',
-            disabled: true, selected: false, optionIndex: 1 },
-          { group: true, text: 'group', disabled: false },
-          { group: false, inGroup: true, text: 'baz',
-            disabled: false, selected: false, optionIndex: 2 } ] }
-    },
-    { type: 'select', inputType: 'select-multiple',
-      choices: {
-        multiple: true,
-        choices: [
-          { group: false, inGroup: false, text: 'foo',
-            disabled: false, selected: true, optionIndex: 0 },
-          { group: false, inGroup: false, text: 'bar',
-            disabled: true, selected: false, optionIndex: 1 },
-          { group: true, text: 'group', disabled: false },
-          { group: false, inGroup: true, text: 'baz',
-            disabled: false, selected: false, optionIndex: 2 } ] }
-    }
-  ];
-
-  let expectBlur = false;
-
-  function deepAssertObject(obj, expectedObj, desc) {
-    for (let prop in expectedObj) {
-      if (typeof expectedObj[prop] === 'object') {
-        deepAssertObject(obj[prop], expectedObj[prop], desc + '.' + prop);
-      } else {
-        is(obj[prop], expectedObj[prop], desc + '.' + prop);
-      }
-    }
-  }
-
-  im.mgmt.oninputcontextfocus =
-  im.mgmt.oninputcontextblur = function(evt) {
-    if (expectBlur) {
-      is(evt.type, 'inputcontextblur', 'evt.type');
-      evt.preventDefault();
-      expectBlur = false;
-
-      return;
-    }
-
-    let expectedEventDetail = expectedEventDetails.shift();
-
-    if (!expectedEventDetail) {
-        ok(false, 'Receving extra events');
-        inputmethod_cleanup();
-
-      return;
-    }
-
-    is(evt.type, 'inputcontextfocus', 'evt.type');
-    evt.preventDefault();
-    expectBlur = true;
-
-    let detail = evt.detail;
-    deepAssertObject(detail, expectedEventDetail, 'detail');
-
-    if (expectedEventDetails.length) {
-      contentFrameMM.sendAsyncMessage('test:next');
-    } else {
-      im.mgmt.oninputcontextfocus = im.mgmt.oninputcontextblur = null;
-      inputmethod_cleanup();
-    }
-  };
-}
-
-function setupInputAppFrame() {
-  info('setupInputAppFrame');
-  return new Promise((resolve, reject) => {
-    let appFrameScript = function appFrameScript() {
-      let im = content.navigator.mozInputMethod;
-
-      im.mgmt.oninputcontextfocus =
-      im.mgmt.oninputcontextblur = function(evt) {
-        sendAsyncMessage('text:appEvent', { type: evt.type });
-      };
-
-      content.document.body.textContent = 'I am a input app';
-    };
-
-    let path = location.pathname;
-    let basePath = location.protocol + '//' + location.host +
-                 path.substring(0, path.lastIndexOf('/'));
-    let imeUrl = basePath + '/file_blank.html';
-
-    let inputAppFrame = document.createElement('iframe');
-    inputAppFrame.setAttribute('mozbrowser', true);
-    inputAppFrame.src = imeUrl;
-    document.body.appendChild(inputAppFrame);
-
-    let mm = SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
-    inputAppFrame.addEventListener('mozbrowserloadend', function() {
-      mm.addMessageListener('text:appEvent', function(msg) {
-        ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
-      });
-      mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-
-      // Set the input app frame to be active
-      let req = inputAppFrame.setInputMethodActive(true);
-      resolve(req);
-    });
-  });
-}
-
-function setupContentFrame() {
-  info('setupContentFrame');
-  return new Promise((resolve, reject) => {
-    let contentFrameScript = function contentFrameScript() {
-      let input = content.document.body.firstElementChild;
-
-      let i = 0;
-
-      input.focus();
-
-      addMessageListener('test:next', function() {
-        content.document.body.children[++i].focus();
-      });
-    };
-
-    let iframe = document.createElement('iframe');
-    iframe.src = 'file_test_focus_blur_manage_events.html';
-    iframe.setAttribute('mozbrowser', true);
-    document.body.appendChild(iframe);
-
-    let mm = contentFrameMM =
-      SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-    iframe.addEventListener('mozbrowserloadend', function() {
-      mm.loadFrameScript('data:,(' + encodeURIComponent(contentFrameScript.toString()) + ')();', false);
-
-      resolve();
-    });
-  });
-}
-
-inputmethod_setup(function() {
-  Promise.resolve()
-    .then(() => setupTestRunner())
-    .then(() => setupContentFrame())
-    .then(() => setupInputAppFrame())
-    .catch((e) => {
-      ok(false, 'Error' + e.toString());
-      console.error(e);
-    });
-});
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_forward_hardware_key_to_ime.html
+++ /dev/null
@@ -1,149 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1110030
--->
-<head>
-  <title>Forwarding Hardware Key to InputMethod</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/NativeKeyCodes.js"></script>
-  <script type="text/javascript" src="bug1110030_helper.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1110030">Mozilla Bug 1110030</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-// The input context.
-var gContext = null;
-
-// The test cases.
-var gTests;
-
-inputmethod_setup(function() {
-  setInputContext();
-});
-
-function setInputContext() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext || !gContext.hardwareinput) {
-      ok(false, 'Should have a non-null inputcontext.hardwareinput');
-      inputmethod_cleanup();
-      return;
-    }
-
-    prepareTest();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  // verifyResultsAndMoveNext will be called after input#text-input
-  // receives all expected key events and it will verify results
-  // and start next test.
-  loadTestFrame(verifyResultsAndMoveNext);
-}
-
-function prepareTest()
-{
-  // Set the used input method of this test
-  gInputMethod = new InputMethod(gContext);
-
-  // Add listenr to hardwareinput
-  addKeyEventListeners(gContext.hardwareinput, function (evt) {
-    hardwareEventReceiver(evt);
-    gInputMethod.handler(evt);
-  });
-
-  // Set the test cases
-  gTests = [
-    // Case 1: IME handle the key input
-    {
-      key: 'z',
-      hardwareinput: {
-        expectedEvents: kKeyDown | kKeyUp,
-        receivedEvents: 0,
-        expectedKeys: 'zz', // One for keydown, the other for keyup
-        receivedKeys: '',
-      },
-      inputtext: {
-        expectedEvents: kKeyDown | kKeyPress | kKeyUp,
-        receivedEvents: 0,
-        expectedKeys: gInputMethod.mapKey('z') +  // for keydown
-                      gInputMethod.mapKey('z') +  // for keypress
-                      gInputMethod.mapKey('z'),   // for keyup
-        receivedKeys: '',
-      }
-    },
-    // case 2: IME doesn't handle the key input
-    {
-      key: '7',
-      hardwareinput: {
-        expectedEvents: kKeyDown | kKeyUp,
-        receivedEvents: 0,
-        expectedKeys: '77', // One for keydown, the other for keyup
-        receivedKeys: '',
-      },
-      inputtext: {
-        expectedEvents: kKeyDown | kKeyPress | kKeyUp,
-        receivedEvents: 0,
-        expectedKeys: '777', // keydown, keypress, keyup all will receive key
-        receivedKeys: '',
-      }
-    },
-    // case 3: IME is disable
-    // This case is same as
-    // dom/events/test/test_dom_before_after_keyboard_event*.html
-  ];
-
-  startTesting();
-}
-
-function startTesting()
-{
-  if (gTests.length <= 0) {
-    finish();
-    return;
-  }
-
-  gCurrentTest = gTests.shift();
-
-  fireEvent();
-}
-
-function verifyResultsAndMoveNext()
-{
-  verifyResults(gCurrentTest);
-  startTesting();
-}
-
-function finish()
-{
-  inputmethod_cleanup();
-}
-
-function errorHandler(msg)
-{
-  // Clear the test cases
-  if (gTests) {
-    gTests = [];
-  }
-
-  ok(false, msg);
-
-  inputmethod_cleanup();
-}
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_input_registry_events.html
+++ /dev/null
@@ -1,251 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
--->
-<head>
-  <title>Test addinputrequest and removeinputrequest event</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-let appFrameMM;
-let nextStep;
-
-function setupInputAppFrame() {
-  info('setupInputAppFrame');
-  return new Promise((resolve, reject) => {
-    let appFrameScript = function appFrameScript() {
-      let im = content.navigator.mozInputMethod;
-
-      addMessageListener('test:callAddInput', function() {
-        im.addInput('foo', {
-            launch_path: 'bar.html',
-            name: 'Foo',
-            description: 'foobar',
-            types: ['text', 'password']
-          })
-          .then((r) => {
-              sendAsyncMessage('test:resolved', { resolved: true, result: r });
-            }, (e) => {
-              sendAsyncMessage('test:rejected', { rejected: true, error: e });
-            });
-      });
-
-      addMessageListener('test:callRemoveInput', function() {
-        im.removeInput('foo')
-          .then((r) => {
-              sendAsyncMessage('test:resolved', { resolved: true, result: r });
-            }, (e) => {
-              sendAsyncMessage('test:rejected', { rejected: true, error: e });
-            });
-      });
-
-      im.mgmt.onaddinputrequest =
-      im.mgmt.onremoveinputrequest = function(evt) {
-        sendAsyncMessage('test:appEvent', { type: evt.type });
-      };
-
-      content.document.body.textContent = 'I am a input app';
-    };
-
-    let path = location.pathname;
-    let basePath = location.protocol + '//' + location.host +
-                 path.substring(0, path.lastIndexOf('/'));
-    let imeUrl = basePath + '/file_blank.html';
-
-    let inputAppFrame = document.createElement('iframe');
-    inputAppFrame.setAttribute('mozbrowser', true);
-    // FIXME: Bug 1270790
-    inputAppFrame.setAttribute('remote', true);
-    inputAppFrame.src = imeUrl;
-    document.body.appendChild(inputAppFrame);
-
-    let mm = appFrameMM =
-      SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
-
-    inputAppFrame.addEventListener('mozbrowserloadend', function() {
-      mm.addMessageListener('test:appEvent', function(msg) {
-        ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
-      });
-      mm.addMessageListener('test:resolved', function(msg) {
-        nextStep && nextStep(msg.data);
-      });
-      mm.addMessageListener('test:rejected', function(msg) {
-        nextStep && nextStep(msg.data);
-      });
-      mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-
-      resolve();
-    });
-  });
-}
-
-function Deferred() {
-  this.promise = new Promise((res, rej) => {
-    this.resolve = res;
-    this.reject = rej;
-  });
-  return this;
-}
-
-function deepAssertObject(obj, expectedObj, desc) {
-  for (let prop in expectedObj) {
-    if (typeof expectedObj[prop] === 'object') {
-      deepAssertObject(obj[prop], expectedObj[prop], desc + '.' + prop);
-    } else {
-      is(obj[prop], expectedObj[prop], desc + '.' + prop);
-    }
-  }
-}
-
-function setupTestRunner() {
-  let im = navigator.mozInputMethod;
-  let d;
-
-  let i = -1;
-  nextStep = function next(evt) {
-    i++;
-    info('Step ' + i);
-
-    switch (i) {
-      case 0:
-        appFrameMM.sendAsyncMessage('test:callAddInput');
-
-        break;
-
-      case 1:
-        is(evt.type, 'addinputrequest', 'evt.type');
-        deepAssertObject(evt.detail, {
-          inputId: 'foo',
-          manifestURL: null, // todo
-          inputManifest: {
-            launch_path: 'bar.html',
-            name: 'Foo',
-            description: 'foobar',
-            types: ['text', 'password']
-          }
-        }, 'detail');
-
-        d = new Deferred();
-        evt.detail.waitUntil(d.promise);
-        evt.preventDefault();
-
-        Promise.resolve().then(next);
-        break;
-
-      case 2:
-        d.resolve();
-        d = null;
-        break;
-
-      case 3:
-        ok(evt.resolved, 'resolved');
-        appFrameMM.sendAsyncMessage('test:callAddInput');
-
-        break;
-
-      case 4:
-        is(evt.type, 'addinputrequest', 'evt.type');
-
-        d = new Deferred();
-        evt.detail.waitUntil(d.promise);
-        evt.preventDefault();
-
-        Promise.resolve().then(next);
-        break;
-
-      case 5:
-        d.reject('Foo Error');
-        d = null;
-        break;
-
-      case 6:
-        ok(evt.rejected, 'rejected');
-        is(evt.error, 'Foo Error', 'rejected');
-
-
-        appFrameMM.sendAsyncMessage('test:callRemoveInput');
-
-        break;
-
-      case 7:
-        is(evt.type, 'removeinputrequest', 'evt.type');
-        deepAssertObject(evt.detail, {
-          inputId: 'foo',
-          manifestURL: null // todo
-        }, 'detail');
-
-        d = new Deferred();
-        evt.detail.waitUntil(d.promise);
-        evt.preventDefault();
-
-        Promise.resolve().then(next);
-        break;
-
-      case 8:
-        d.resolve();
-        d = null;
-        break;
-
-      case 9:
-        ok(evt.resolved, 'resolved');
-        appFrameMM.sendAsyncMessage('test:callRemoveInput');
-
-        break;
-
-      case 10:
-        is(evt.type, 'removeinputrequest', 'evt.type');
-
-        d = new Deferred();
-        evt.detail.waitUntil(d.promise);
-        evt.preventDefault();
-
-        Promise.resolve().then(next);
-        break;
-
-      case 11:
-        d.reject('Foo Error');
-        d = null;
-        break;
-
-      case 12:
-        ok(evt.rejected, 'rejected');
-        is(evt.error, 'Foo Error', 'rejected');
-        inputmethod_cleanup();
-
-        break;
-
-      default:
-        ok(false, 'received extra call.');
-        inputmethod_cleanup();
-
-        break;
-    }
-  }
-
-  im.mgmt.onaddinputrequest =
-  im.mgmt.onremoveinputrequest = nextStep;
-}
-
-inputmethod_setup(function() {
-  Promise.resolve()
-    .then(() => setupTestRunner())
-    .then(() => setupInputAppFrame())
-    .then(() => nextStep())
-    .catch((e) => {
-      ok(false, 'Error' + e.toString());
-      console.error(e);
-    });
-});
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_sendkey_cancel.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=952080
--->
-<head>
-  <title>SendKey with canceled keydown test for InputMethod API.</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952080">Mozilla Bug 952080</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-// The input context.
-var gContext = null;
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  im.oninputcontextchange = function() {
-    ok(true, 'inputcontextchange event was fired.');
-    im.oninputcontextchange = null;
-
-    gContext = im.inputcontext;
-    if (!gContext) {
-      ok(false, 'Should have a non-null inputcontext.');
-      inputmethod_cleanup();
-      return;
-    }
-
-    test();
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_sendkey_cancel.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-}
-
-function test() {
-  gContext.sendKey(0, 'j', 0).then(function() {
-    ok(false, 'sendKey was incorrectly resolved');
-
-    inputmethod_cleanup();
-  }, function(e) {
-    ok(true, 'sendKey was rejected');
-
-    inputmethod_cleanup();
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_setSupportsSwitching.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1197682
--->
-<head>
-  <title>Test inputcontext#inputType and MozInputMethodManager#supportsSwitching()</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1197682">Mozilla Bug 1197682</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let input = content.document.body.firstElementChild;
-
-  let i = 1;
-
-  input.focus();
-
-  addMessageListener('test:next', function() {
-    i++;
-    switch (i) {
-      case 2:
-        content.document.body.children[1].focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 4:
-        content.document.body.lastElementChild.focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 6:
-        content.document.body.lastElementChild.blur();
-
-        break;
-    }
-  });
-};
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  im.oninputcontextchange = function(evt) {
-    var inputcontext = navigator.mozInputMethod.inputcontext;
-
-    i++;
-    switch (i) {
-      case 1:
-        ok(!!inputcontext, '1) Receving the input context');
-        is(inputcontext.inputType, 'text', '1) input type');
-        is(im.mgmt.supportsSwitching(), true, '1) supports switching');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      case 2:
-        is(inputcontext, null, '2) Receving null inputcontext');
-
-        break;
-
-      case 3:
-        ok(!!inputcontext, '3) Receving the input context');
-        is(inputcontext.inputType, 'number', '3) input type');
-        is(im.mgmt.supportsSwitching(), false, '3) supports switching');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      case 4:
-        is(inputcontext, null, '4) Receving null inputcontext');
-
-        break;
-
-      case 5:
-        ok(!!inputcontext, '5) Receving the input context');
-        is(inputcontext.inputType, 'password', '5) input type');
-        is(im.mgmt.supportsSwitching(), true, '5) supports switching');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      case 6:
-        is(inputcontext, null, '6) Receving null inputcontext');
-        is(im.mgmt.supportsSwitching(), false, '6) supports switching');
-
-        inputmethod_cleanup();
-        break;
-
-      default:
-        ok(false, 'Receving extra inputcontextchange calls');
-        inputmethod_cleanup();
-
-        break;
-    }
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-  // Set text and password inputs as supports switching (and not supported for number type)
-  im.mgmt.setSupportsSwitchingTypes(['text', 'password']);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_setSupportsSwitching.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_simple_manage_events.html
+++ /dev/null
@@ -1,154 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1201407
--->
-<head>
-  <title>Test simple manage notification events on MozInputMethodManager</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-let appFrameMM;
-let nextStep;
-
-function setupTestRunner() {
-  info('setupTestRunner');
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  im.mgmt.onshowallrequest =
-  im.mgmt.onnextrequest = nextStep = function(evt) {
-    i++;
-    switch (i) {
-      case 1:
-        is(evt.type, 'inputcontextchange', '1) inputcontextchange event');
-        appFrameMM.sendAsyncMessage('test:callShowAll');
-
-        break;
-
-      case 2:
-        is(evt.type, 'showallrequest', '2) showallrequest event');
-        ok(evt.target, im.mgmt, '2) evt.target');
-        evt.preventDefault();
-
-        appFrameMM.sendAsyncMessage('test:callNext');
-
-        break;
-
-      case 3:
-        is(evt.type, 'nextrequest', '3) nextrequest event');
-        ok(evt.target, im.mgmt, '3) evt.target');
-        evt.preventDefault();
-
-        im.mgmt.onshowallrequest =
-        im.mgmt.onnextrequest = nextStep = null;
-
-        inputmethod_cleanup();
-        break;
-
-      default:
-        ok(false, 'Receving extra events');
-        inputmethod_cleanup();
-
-        break;
-    }
-  };
-}
-
-function setupInputAppFrame() {
-  info('setupInputAppFrame');
-  return new Promise((resolve, reject) => {
-    let appFrameScript = function appFrameScript() {
-      let im = content.navigator.mozInputMethod;
-
-      addMessageListener('test:callShowAll', function() {
-        im.mgmt.showAll();
-      });
-
-      addMessageListener('test:callNext', function() {
-        im.mgmt.next();
-      });
-
-      im.mgmt.onshowallrequest =
-      im.mgmt.onnextrequest = function(evt) {
-        sendAsyncMessage('test:appEvent', { type: evt.type });
-      };
-
-      im.oninputcontextchange = function(evt) {
-        sendAsyncMessage('test:inputcontextchange', {});
-      };
-
-      content.document.body.textContent = 'I am a input app';
-    };
-
-    let path = location.pathname;
-    let basePath = location.protocol + '//' + location.host +
-                 path.substring(0, path.lastIndexOf('/'));
-    let imeUrl = basePath + '/file_blank.html';
-
-    let inputAppFrame = document.createElement('iframe');
-    inputAppFrame.setAttribute('mozbrowser', true);
-    inputAppFrame.src = imeUrl;
-    document.body.appendChild(inputAppFrame);
-
-    let mm = appFrameMM =
-      SpecialPowers.getBrowserFrameMessageManager(inputAppFrame);
-
-    inputAppFrame.addEventListener('mozbrowserloadend', function() {
-      mm.addMessageListener('test:appEvent', function(msg) {
-        ok(false, 'Input app should not receive ' + msg.data.type + ' event.');
-      });
-      mm.addMessageListener('test:inputcontextchange', function(msg) {
-        nextStep && nextStep({ type: 'inputcontextchange' });
-      });
-      mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-
-      // Set the input app frame to be active
-      let req = inputAppFrame.setInputMethodActive(true);
-      resolve(req);
-    });
-  });
-}
-
-function setupContentFrame() {
-  let contentFrameScript = function contentFrameScript() {
-    let input = content.document.body.firstElementChild;
-
-    input.focus();
-  };
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_simple_manage_events.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.loadFrameScript('data:,(' + encodeURIComponent(contentFrameScript.toString()) + ')();', false);
-  });
-}
-
-inputmethod_setup(function() {
-  Promise.resolve()
-    .then(() => setupTestRunner())
-    .then(() => setupContentFrame())
-    .then(() => setupInputAppFrame())
-    .catch((e) => {
-      ok(false, 'Error' + e.toString());
-      console.error(e);
-    });
-});
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_sync_edit.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1079455
--->
-<head>
-  <title>Sync edit of an input</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1079455">Mozilla Bug 1079455</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let input = content.document.body.firstElementChild;
-
-  input.focus();
-  input.value = 'First1';
-  input.blur();
-};
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  im.oninputcontextchange = function() {
-    let inputcontext = im.inputcontext;
-    i++;
-    switch (i) {
-      case 1:
-        ok(!!inputcontext, 'Should receive inputcontext from focus().');
-        is(inputcontext.textAfterCursor, 'First');
-
-        break;
-
-      case 2:
-        ok(!!inputcontext, 'Should receive inputcontext from value change.');
-        is(inputcontext.textBeforeCursor, 'First1');
-
-        break;
-
-      case 3:
-        ok(!inputcontext, 'Should lost inputcontext from blur().');
-
-        inputmethod_cleanup();
-        break;
-
-      default:
-        ok(false, 'Unknown event count.');
-
-        inputmethod_cleanup();
-    }
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_sync_edit.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_two_inputs.html
+++ /dev/null
@@ -1,184 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1057898
-https://bugzilla.mozilla.org/show_bug.cgi?id=952741
--->
-<head>
-  <title>Test switching between two inputs</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1057898">Mozilla Bug 1057898</a>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952741">Mozilla Bug 952741</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let input1 = content.document.body.firstElementChild;
-  let input2 = content.document.body.children[1];
-
-  let i = 1;
-
-  input1.focus();
-
-  addMessageListener('test:next', function() {
-    i++;
-    switch (i) {
-      case 2:
-        input2.focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 4:
-        input2.blur();
-
-        break;
-
-      case 5:
-        input2.focus();
-
-        break;
-
-      case 6:
-        input1.focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 8:
-        content.document.body.removeChild(input1);
-
-        break;
-
-      case 9:
-        input2.focus();
-
-        break;
-
-      case 10:
-        content.document.body.removeChild(input2);
-
-        break;
-    }
-  });
-};
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  im.oninputcontextchange = function(evt) {
-    var inputcontext = navigator.mozInputMethod.inputcontext;
-
-    i++;
-    switch (i) {
-      // focus on the first input receives the first input context.
-      case 1:
-        ok(!!inputcontext, '1) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input should implicitly blur the first input
-      case 2:
-        is(inputcontext, null, '2) Receving null inputcontext');
-
-        break;
-
-      // ... and results the second input context.
-      case 3:
-        ok(!!inputcontext, '3) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // blur on the second input results null input context
-      case 4:
-        is(inputcontext, null, '4) Receving null inputcontext');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input receives the second input context.
-      case 5:
-        ok(!!inputcontext, '5) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input should implicitly blur the first input
-      case 6:
-        is(inputcontext, null, '6) Receving null inputcontext');
-
-        break;
-
-      // ... and results the second input context.
-      case 7:
-        ok(!!inputcontext, '7) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // remove on the first focused input results null input context
-      case 8:
-        is(inputcontext, null, '8) Receving null inputcontext');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // input context for the second input.
-      case 9:
-        ok(!!inputcontext, '9) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // remove on the second focused input results null input context
-      case 10:
-        is(inputcontext, null, '10) Receving null inputcontext');
-
-        inputmethod_cleanup();
-        break;
-
-      default:
-        ok(false, 'Receving extra inputcontextchange calls');
-        inputmethod_cleanup();
-
-        break;
-    }
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_two_inputs.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_two_selects.html
+++ /dev/null
@@ -1,182 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1079728
--->
-<head>
-  <title>Test switching between two inputs</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1079728">Mozilla Bug 1079728</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let select1 = content.document.body.firstElementChild;
-  let select2 = content.document.body.children[1];
-
-  let i = 1;
-
-  select1.focus();
-
-  addMessageListener('test:next', function() {
-    i++;
-    switch (i) {
-      case 2:
-        select2.focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 4:
-        select2.blur();
-
-        break;
-
-      case 5:
-        select2.focus();
-
-        break;
-
-      case 6:
-        select1.focus();
-        i++; // keep the same count with the parent frame.
-
-        break;
-
-      case 8:
-        content.document.body.removeChild(select1);
-
-        break;
-
-      case 9:
-        select2.focus();
-
-        break;
-
-      case 10:
-        content.document.body.removeChild(select2);
-
-        break;
-    }
-  });
-};
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  im.oninputcontextchange = function(evt) {
-    var inputcontext = navigator.mozInputMethod.inputcontext;
-
-    i++;
-    switch (i) {
-      // focus on the first input receives the first input context.
-      case 1:
-        ok(!!inputcontext, '1) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input should implicitly blur the first input
-      case 2:
-        is(inputcontext, null, '2) Receving null inputcontext');
-
-        break;
-
-      // ... and results the second input context.
-      case 3:
-        ok(!!inputcontext, '3) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // blur on the second input results null input context
-      case 4:
-        is(inputcontext, null, '4) Receving null inputcontext');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input receives the second input context.
-      case 5:
-        ok(!!inputcontext, '5) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // focus on the second input should implicitly blur the first input
-      case 6:
-        is(inputcontext, null, '6) Receving null inputcontext');
-
-        break;
-
-      // ... and results the second input context.
-      case 7:
-        ok(!!inputcontext, '7) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // remove on the first focused input results null input context
-      case 8:
-        is(inputcontext, null, '8) Receving null inputcontext');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // input context for the second input.
-      case 9:
-        ok(!!inputcontext, '9) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // remove on the second focused input results null input context
-      case 10:
-        is(inputcontext, null, '10) Receving null inputcontext');
-
-        inputmethod_cleanup();
-        break;
-
-      default:
-        ok(false, 'Receving extra inputcontextchange calls');
-        inputmethod_cleanup();
-
-        break;
-    }
-  };
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_two_selects.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-
-  iframe.addEventListener('mozbrowserloadend', function() {
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/mochitest/test_unload.html
+++ /dev/null
@@ -1,167 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1122463
-https://bugzilla.mozilla.org/show_bug.cgi?id=820057
--->
-<head>
-  <title>Test focus when page unloads</title>
-  <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1122463">Mozilla Bug 1122463</a>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=820057">Mozilla Bug 820057</a>
-<p id="display"></p>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-inputmethod_setup(function() {
-  runTest();
-});
-
-let appFrameScript = function appFrameScript() {
-  let form1 = content.document.body.firstElementChild;
-  let input1 = form1.firstElementChild;
-  let submit1 = form1.lastElementChild;
-  let input2;
-
-  let cancelSubmit = function(evt) {
-    evt.preventDefault();
-  };
-
-  // Content of the second page.
-  form1.action = 'file_test_unload_action.html';
-
-  let i = 1;
-
-  input1.focus();
-
-  addMessageListener('test:next', function() {
-    i++;
-    switch (i) {
-      case 2:
-        // Click the submit button, trigger the submit event and make our
-        // installed event listener preventing the submission.
-        form1.addEventListener('submit', cancelSubmit);
-        submit1.click();
-
-        sendAsyncMessage('test:step');
-
-        break;
-
-      case 3:
-        // Actually submit the form.
-        form1.removeEventListener('submit', cancelSubmit);
-        submit1.click();
-
-        break;
-
-      case 4:
-        if (!content.document.body) {
-          content.onload = function() {
-            content.onload = null;
-
-            let input2 = content.document.body.firstElementChild;
-            input2.focus();
-          };
-
-          return;
-        }
-
-        input2 = content.document.body.firstElementChild;
-        input2.focus();
-
-        break;
-
-      case 5:
-        content.location.href = 'data:text/html,Hello!';
-
-        break;
-    }
-  });
-};
-
-function runTest() {
-  let im = navigator.mozInputMethod;
-
-  let i = 0;
-  function nextStep() {
-    let inputcontext = navigator.mozInputMethod.inputcontext;
-
-    i++;
-    switch (i) {
-      // focus on the first input receives the first input context.
-      case 1:
-        ok(!!inputcontext, '1) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // Cancelled submission should not cause us lost focus.
-      case 2:
-        ok(!!inputcontext, '2) Receving the first input context');
-        is(inputcontext.textAfterCursor, 'First');
-
-        mm.sendAsyncMessage('test:next');
-        break;
-
-      // Real submit and page transition should cause us lost focus.
-      // XXX: Unless we could delay the page transition, we does not know if
-      // the inputcontext is lost because of the submit or the pagehide/beforeload
-      // event.
-      case 3:
-        is(inputcontext, null, '3) Receving null inputcontext');
-
-        mm.sendAsyncMessage('test:next');
-
-        break;
-
-      // Regaining focus of input in the second page.
-      case 4:
-        ok(!!inputcontext, '4) Receving the second input context');
-        is(inputcontext.textAfterCursor, 'Second');
-
-        mm.sendAsyncMessage('test:next');
-
-        break;
-
-      // Page transition should cause us lost focus
-      case 5:
-        is(inputcontext, null, '5) Receving null inputcontext');
-
-        inputmethod_cleanup();
-
-        break;
-    }
-  }
-
-  // Set current page as an input method.
-  SpecialPowers.wrap(im).setActive(true);
-
-  let iframe = document.createElement('iframe');
-  iframe.src = 'file_test_unload.html';
-  iframe.setAttribute('mozbrowser', true);
-  document.body.appendChild(iframe);
-
-  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-  im.oninputcontextchange = nextStep;
-
-  let frameScriptLoaded = false;
-  iframe.addEventListener('mozbrowserloadend', function() {
-    if (frameScriptLoaded)
-      return;
-
-    frameScriptLoaded = true;
-    mm.addMessageListener('test:step', nextStep);
-    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
-  });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/inputmethod/moz.build
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-if CONFIG['MOZ_B2G']:
-    XPIDL_SOURCES += [
-        'nsIHardwareKeyHandler.idl',
-    ]
-
-    XPIDL_MODULE = 'inputmethod'
-
-    EXPORTS.mozilla += [
-        'HardwareKeyHandler.h',
-    ]
-
-    SOURCES += [
-        'HardwareKeyHandler.cpp'
-    ]
-
-    include('/ipc/chromium/chromium-config.mozbuild')
-
-    FINAL_LIBRARY = 'xul'
-    LOCAL_INCLUDES += [
-        '/dom/base',
-        '/layout/base',
-    ]
-
-EXTRA_COMPONENTS += [
-    'InputMethod.manifest',
-    'MozKeyboard.js',
-]
-
-EXTRA_PP_JS_MODULES += [
-    'Keyboard.jsm',
-]
-
-JAR_MANIFESTS += ['jar.mn']
-
-MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
deleted file mode 100644
--- a/dom/inputmethod/nsIHardwareKeyHandler.idl
+++ /dev/null
@@ -1,142 +0,0 @@
-/* -*- 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 "nsISupports.idl"
-
-interface nsIDOMKeyEvent;
-
-%{C++
-#define NS_HARDWARE_KEY_HANDLER_CID \
-  { 0xfb45921b, 0xe0a5, 0x45c6, \
-    { 0x90, 0xd0, 0xa6, 0x97, 0xa7, 0x72, 0xc4, 0x2a } }
-#define NS_HARDWARE_KEY_HANDLER_CONTRACTID \
-  "@mozilla.org/HardwareKeyHandler;1"
-
-#include "mozilla/EventForwards.h" /* For nsEventStatus */
-
-namespace mozilla {
-class WidgetKeyboardEvent;
-}
-
-using mozilla::WidgetKeyboardEvent;
-
-class nsINode;
-%}
-
-/**
- * This interface is used to be registered to the nsIHardwareKeyHandler through
- * |nsIHardwareKeyHandler.registerListener|.
- */
-[scriptable, function, uuid(cd5aeee3-b4b9-459d-85e7-c0671c7a8a2e)]
-interface nsIHardwareKeyEventListener : nsISupports
-{
-  /**
-   * This method will be invoked by nsIHardwareKeyHandler to forward the native
-   * keyboard event to the active input method
-   */
-  bool onHardwareKey(in nsIDOMKeyEvent aEvent);
-};
-
-/**
- * This interface has two main roles. One is to send a hardware keyboard event
- * to the active input method app and the other is to receive its reply result.
- * If a keyboard event is triggered from a hardware keyboard when an editor has
- * focus, the event target should be the editor. However, the text input
- * processor algorithm is implemented in an input method app and it should
- * handle the event earlier than the real event target to do the mapping such
- * as character conversion according to the language setting or the type of a
- * hardware keyboard.
- */
-[scriptable, builtinclass, uuid(25b34270-caad-4d18-a910-860351690639)]
-interface nsIHardwareKeyHandler : nsISupports
-{
-  /**
-   * Flags used to set the defaultPrevented's result. The default result
-   * from input-method-app should be set to NO_DEFAULT_PREVENTED.
-   * (It means the forwarded event isn't consumed by input-method-app.)
-   * If the input-method-app consumes the forwarded event,
-   * then the result should be set by DEFAULT_PREVENTED* before reply.
-   */
-  const unsigned short NO_DEFAULT_PREVENTED           = 0x0000;
-  const unsigned short DEFAULT_PREVENTED              = 0x0001;
-  const unsigned short DEFAULT_PREVENTED_BY_CHROME    = 0x0002;
-  const unsigned short DEFAULT_PREVENTED_BY_CONTENT   = 0x0004;
-
-  /**
-   * Registers a listener in input-method-app to receive
-   * the forwarded hardware keyboard events
-   *
-   * @param aListener             Listener object to be notified for receiving
-   *                              the keyboard event fired from hardware
-   * @note                        A listener object must implement
-   *                              nsIHardwareKeyEventListener and
-   *                              nsSupportsWeakReference
-   * @see nsIHardwareKeyEventListener
-   * @see nsSupportsWeakReference
-   */
-  void registerListener(in nsIHardwareKeyEventListener aListener);
-
-  /**
-   * Unregisters the current listener from input-method-app
-   */
-  void unregisterListener();
-
-  /**
-   * Notifies nsIHardwareKeyHandler that input-method-app is active.
-   */
-  void onInputMethodAppConnected();
-
-  /**
-   * Notifies nsIHardwareKeyHandler that input-method-app is disabled.
-   */
-  void onInputMethodAppDisconnected();
-
-  /**
-   * Input-method-app will pass the processing result that the forwarded
-   * event is handled or not through this method, and the nsIHardwareKeyHandler
-   * can use this to receive the reply of |forwardKeyToInputMethodApp|
-   * from the active input method.
-   *
-   * The result should contain the original event type and the info whether
-   * the default is prevented, also, it is prevented by chrome or content.
-   *
-   * @param aEventType            The type of an original event.
-   * @param aDefaultPrevented     State that |evt.preventDefault|
-   *                              is called by content, chrome or not.
-   */
-  void onHandledByInputMethodApp(in DOMString aType,
-                                 in unsigned short aDefaultPrevented);
-
-  /**
-   * Sends the native keyboard events triggered from hardware to the
-   * active input method before dispatching to its event target.
-   * This method only forwards keydown and keyup events.
-   * If the event isn't allowed to be forwarded, we should continue the
-   * normal event processing. For those forwarded keydown and keyup events
-   * We will pause the further event processing to wait for the completion
-   * of the event handling in the active input method app.
-   * Once |onHandledByInputMethodApp| is called by the input method app,
-   * the pending event processing can be resumed according to its reply.
-   * On the other hand, the keypress will never be sent to the input-method-app.
-   * Depending on whether the keydown's reply arrives before the keypress event
-   * comes, the keypress event will be handled directly or pushed into
-   * the event queue to wait for its heading keydown's reply.
-   *
-   * This implementation will call |nsIHardwareKeyEventListener.onHardwareKey|,
-   * which is registered through |nsIHardwareKeyEventListener.registerListener|,
-   * to forward the events.
-   *
-   * Returns true, if the event is handled in this module.
-   * Returns false, otherwise.
-   *
-   * If it returns false, we should continue the normal event processing.
-   */
-  %{C++
-  virtual bool ForwardKeyToInputMethodApp(nsINode* aTarget,
-                                          WidgetKeyboardEvent* aEvent,
-                                          nsEventStatus* aEventStatus) = 0;
-  %}
-};
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -703,21 +703,18 @@ ContentParent::GetInitialProcessPriority
 {
   // Frames with mozapptype == critical which are expecting a system message
   // get FOREGROUND_HIGH priority.
 
   if (!aFrameElement) {
     return PROCESS_PRIORITY_FOREGROUND;
   }
 
-  if (aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
-                                 NS_LITERAL_STRING("inputmethod"), eCaseMatters)) {
-    return PROCESS_PRIORITY_FOREGROUND_KEYBOARD;
-  } else if (!aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
-                                        NS_LITERAL_STRING("critical"), eCaseMatters)) {
+  if (!aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
+                                  NS_LITERAL_STRING("critical"), eCaseMatters)) {
     return PROCESS_PRIORITY_FOREGROUND;
   }
 
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aFrameElement);
   if (!browserFrame) {
     return PROCESS_PRIORITY_FOREGROUND;
   }
 
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -1053,19 +1053,17 @@ ParticularProcessPriorityManager::Comput
   for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
     if (TabParent::GetFrom(iter.Get()->GetKey())->IsVisible()) {
       isVisible = true;
       break;
     }
   }
 
   if (isVisible) {
-    return HasAppType("inputmethod") ?
-      PROCESS_PRIORITY_FOREGROUND_KEYBOARD :
-      PROCESS_PRIORITY_FOREGROUND;
+    return PROCESS_PRIORITY_FOREGROUND;
   }
 
   if ((mHoldsCPUWakeLock || mHoldsHighPriorityWakeLock) &&
       IsExpectingSystemMessage()) {
     return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -81,17 +81,16 @@ DIRS += [
     'ipc',
     'workers',
     'audiochannel',
     'broadcastchannel',
     'messagechannel',
     'promise',
     'smil',
     'url',
-    'inputmethod',
     'webidl',
     'xbl',
     'xml',
     'xslt',
     'xul',
     'manifest',
     'vr',
     'u2f',
--- a/dom/webidl/BrowserElement.webidl
+++ b/dom/webidl/BrowserElement.webidl
@@ -142,21 +142,16 @@ interface BrowserElementPrivileged {
   [Throws,
    Pref="dom.mozBrowserFramesEnabled",
    ChromeOnly]
   DOMRequest getContentDimensions();
 
   [Throws,
    Pref="dom.mozBrowserFramesEnabled",
    ChromeOnly]
-  DOMRequest setInputMethodActive(boolean isActive);
-
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
   void findAll(DOMString searchString, BrowserFindCaseSensitivity caseSensitivity);
 
   [Throws,
    Pref="dom.mozBrowserFramesEnabled",
    ChromeOnly]
   void findNext(BrowserFindDirection direction);
 
   [Throws,
deleted file mode 100644
--- a/dom/webidl/InputMethod.webidl
+++ /dev/null
@@ -1,738 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-/**
- * InputMethod API implements a bridge between the web content hosting an input
- * element and the input content (a.k.a. input app, virtual keyboard app,
- * or IME). This API is input content facing in order for it to interact with
- * the remote input element.
- * The API also contains a few Gaia System app only methods
- * (marked with "input-manage" permission) for Gaia System app to interact with
- * some types of inputs and to regulate the input apps.
- */
-[JSImplementation="@mozilla.org/b2g-inputmethod;1",
- NavigatorProperty="mozInputMethod",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputMethod : EventTarget {
-  /**
-   * Activate or decactive current API instance.
-   * Gaia System app call this method via BrowserElement#setInputMethodActive.
-   */
-  [ChromeOnly]
-  void setActive(boolean isActive);
-
-  /**
-   * InputMethodManager contain a few global methods expose to input apps.
-   */
-  readonly attribute MozInputMethodManager mgmt;
-
-  /**
-   * Fired when the input context changes, include changes from and to null.
-   * The new InputContext instance will be available in the event
-   * object under |inputcontext| property.  When it changes to null it
-   * means the app (the user of this API) no longer has the control of
-   * the original focused input field.
-   * Note that if the app saves the original context, it might get
-   * void; implementation decides when to void the input context.
-   */
-  attribute EventHandler oninputcontextchange;
-
-  /**
-   * An "input context" is mapped to a text field that the app is
-   * allow to mutate. This attribute should be null when there is no
-   * text field currently focused.
-   */
-  readonly attribute MozInputContext? inputcontext;
-
-  /**
-   * Add a dynamically declared input.
-   *
-   * The id must not be the same with any statically declared input in the app
-   * manifest. If an input of the same id is already declared, the info of that
-   * input will be updated.
-   */
-  Promise<void> addInput(DOMString inputId,
-                         MozInputMethodInputManifest inputManifest);
-
-  /**
-   * Remove a dynamically declared input.
-   *
-   * The id must not be the same with any statically declared input in the app
-   * manifest. Silently resolves if the input is not previously declared;
-   * rejects if attempt to remove a statically declared input.
-   */
-  Promise<void> removeInput(DOMString id);
-
-  /**
-   * Remove focus from the current input, usable by Gaia System app, globally,
-   * regardless of the current focus state.
-   */
-  void removeFocus();
-
-  /**
-   * The following are internal methods for Firefox OS System app only,
-   * for handling the "option" group inputs.
-   */
-
-  /**
-   * Set the value on the currently focused element. This has to be used
-   * for special situations where the value had to be chosen amongst a
-   * list (type=month) or a widget (type=date, time, etc.).
-   * If the value passed in parameter isn't valid (in the term of HTML5
-   * Forms Validation), the value will simply be ignored by the element.
-   */
-  void setValue(DOMString value);
-
-  /**
-   * Select the <select> option specified by index.
-   * If this method is called on a <select> that support multiple
-   * selection, then the option specified by index will be added to
-   * the selection.
-   * If this method is called for a select that does not support multiple
-   * selection the previous element will be unselected.
-   */
-  void setSelectedOption(long index);
-
-  /**
-   * Select the <select> options specified by indexes. All other options
-   * will be deselected.
-   * If this method is called for a <select> that does not support multiple
-   * selection, then the last index specified in indexes will be selected.
-   */
-  void setSelectedOptions(sequence<long> indexes);
-};
-
-/**
- * InputMethodManager contains a few of the global methods for the input app.
- */
-[JSImplementation="@mozilla.org/b2g-imm;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputMethodManager : EventTarget {
-  /**
-   * Ask the OS to show a list of available inputs for users to switch from.
-   * OS should sliently ignore this request if the app is currently not the
-   * active one.
-   */
-  void showAll();
-
-  /**
-   * Ask the OS to switch away from the current active input app.
-   * OS should sliently ignore this request if the app is currently not the
-   * active one.
-   */
-  void next();
-
-  /**
-   * If this method returns true, it is recommended that the input app provides
-   * a shortcut that would invoke the next() method above, for easy switching
-   * between inputs -- i.e. show a "global" button on screen if the input app
-   * implements an on-screen virtual keyboard.
-   *
-   * The returning value is depend on the inputType of the current input context.
-   */
-  boolean supportsSwitching();
-
-  /**
-   * Ask the OS to remove the input focus, will cause the lost of input context.
-   * OS should sliently ignore this request if the app is currently not the
-   * active one.
-   */
-  void hide();
-
-  /**
-   * Update Gecko with information on the input types which supportsSwitching()
-   * should return ture.
-   *
-   * @param types Array of input types in which supportsSwitching() should
-   *              return true.
-   */
-  void setSupportsSwitchingTypes(sequence<MozInputMethodInputContextInputTypes> types);
-
-  /**
-   * CustomEvent dispatches to System when there is an input to handle.
-   * If the API consumer failed to handle and call preventDefault(),
-   * there will be a message printed on the console.
-   *
-   * evt.detail is defined by MozInputContextFocusEventDetail.
-   */
-  attribute EventHandler oninputcontextfocus;
-
-  /**
-   * Event dispatches to System when there is no longer an input to handle.
-   * If the API consumer failed to handle and call preventDefault(),
-   * there will be a message printed on the console.
-   */
-  attribute EventHandler oninputcontextblur;
-
-  /**
-   * Event dispatches to System when there is a showAll() call.
-   * If the API consumer failed to handle and call preventDefault(),
-   * there will be a message printed on the console.
-   */
-  attribute EventHandler onshowallrequest;
-
-  /**
-   * Event dispatches to System when there is a next() call.
-   * If the API consumer failed to handle and call preventDefault(),
-   * there will be a message printed on the console.
-   */
-  attribute EventHandler onnextrequest;
-
-  /**
-   * Event dispatches to System when there is a addInput() call.
-   * The API consumer must call preventDefault() to indicate the event is
-   * consumed, otherwise the request is not considered handled even if
-   * waitUntil() was called.
-   *
-   * evt.detail is defined by MozInputRegistryEventDetail.
-   */
-  attribute EventHandler onaddinputrequest;
-
-  /**
-   * Event dispatches to System when there is a removeInput() call.
-   * The API consumer must call preventDefault() to indicate the event is
-   * consumed, otherwise the request is not considered handled even if
-   * waitUntil() was called.
-   *
-   * evt.detail is defined by MozInputRegistryEventDetail.
-   */
-  attribute EventHandler onremoveinputrequest;
-};
-
-/**
- * Detail of the inputcontextfocus event.
- */
-[JSImplementation="@mozilla.org/b2g-imm-focus;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputContextFocusEventDetail {
-  /**
-   * The type of the focused input.
-   */
-  readonly attribute MozInputMethodInputContextTypes type;
-  /**
-   * The input type of the focused input.
-   */
-  readonly attribute MozInputMethodInputContextInputTypes inputType;
-
-  /**
-   * The following is only needed for rendering and handling "option" input types,
-   * in System app.
-   */
-
-  /**
-   * Current value of the input.
-   */
-  readonly attribute DOMString? value;
-  /**
-   * An object representing all the <optgroup> and <option> elements
-   * in the <select> element.
-   */
-  [Pure, Cached, Frozen]
-  readonly attribute MozInputContextChoicesInfo? choices;
-  /**
-   * Max/min value of <input>
-   */
-  readonly attribute DOMString? min;
-  readonly attribute DOMString? max;
-};
-
-/**
- * Information about the options within the <select> element.
- */
-dictionary MozInputContextChoicesInfo {
-  boolean multiple;
-  sequence<MozInputMethodChoiceDict> choices;
-};
-
-/**
- * Content of the option header (<optgroup>) or an option (<option>).
- */
-dictionary MozInputMethodChoiceDict {
-  boolean group;
-  DOMString text;
-  boolean disabled;
-  boolean? inGroup;
-  boolean? selected;
-  long? optionIndex;
-};
-
-/**
- * detail of addinputrequest or removeinputrequest event.
- */
-[JSImplementation="@mozilla.org/b2g-imm-input-registry;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputRegistryEventDetail {
-  /**
-   * Manifest URL of the requesting app.
-   */
-  readonly attribute DOMString manifestURL;
-  /**
-   * ID of the input
-   */
-  readonly attribute DOMString inputId;
-  /**
-   * Input manifest of the input to add.
-   * Null for removeinputrequest event.
-   */
-  [Pure, Cached, Frozen]
-  readonly attribute MozInputMethodInputManifest? inputManifest;
-  /**
-   * Resolve or Reject the addInput() or removeInput() call when the passed
-   * promises are resolved.
-   */
-  [Throws]
-  void waitUntil(Promise<any> p);
-};
-
-/**
- * The input context, which consists of attributes and information of current
- * input field. It also hosts the methods available to the keyboard app to
- * mutate the input field represented. An "input context" gets void when the
- * app is no longer allowed to interact with the text field,
- * e.g., the text field does no longer exist, the app is being switched to
- * background, and etc.
- */
-[JSImplementation="@mozilla.org/b2g-inputcontext;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputContext: EventTarget {
-  /**
-   * Type of the InputContext. See MozInputMethodInputContextTypes
-   */
-  readonly attribute MozInputMethodInputContextTypes? type;
-
-  /**
-   * InputType of the InputContext. See MozInputMethodInputContextInputTypes.
-   */
-  readonly attribute MozInputMethodInputContextInputTypes? inputType;
-
-  /**
-   * The inputmode string, representing the inputmode of the input.
-   * See http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#input-modalities:-the-inputmode-attribute
-   */
-  readonly attribute DOMString? inputMode;
-
-  /**
-   * The primary language for the input field.
-   * It is the value of HTMLElement.lang.
-   * See http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#htmlelement
-   */
-  readonly attribute DOMString? lang;
-
-  /**
-   * Get the whole text content of the input field.
-   * @return DOMString
-   */
-  Promise<DOMString> getText(optional long offset, optional long length);
-
-  /**
-   * The start and stop position of the current selection.
-   */
-  readonly attribute long selectionStart;
-  readonly attribute long selectionEnd;
-
-  /**
-   * The text in the current input.
-   */
-  readonly attribute DOMString? text;
-
-  /**
-   * The text before and after the begining of the selected text.
-   *
-   * You should use the text property instead because these properties are
-   * truncated at 100 characters.
-   */
-  readonly attribute DOMString? textBeforeCursor;
-  readonly attribute DOMString? textAfterCursor;
-
-  /**
-   * Set the selection range of the the editable text.
-   * Note: This method cannot be used to move the cursor during composition. Calling this
-   * method will cancel composition.
-   * @param start The beginning of the selected text.
-   * @param length The length of the selected text.
-   *
-   * Note that the start position should be less or equal to the end position.
-   * To move the cursor, set the start and end position to the same value.
-   *
-   * @return boolean
-   */
-  Promise<boolean> setSelectionRange(long start, long length);
-
-  /* User moves the cursor, or changes the selection with other means. If the text around
-   * cursor has changed, but the cursor has not been moved, the IME won't get notification.
-   *
-   * evt.detail is defined by MozInputContextSelectionChangeEventDetail.
-   */
-  attribute EventHandler onselectionchange;
-
-  /**
-   * Commit text to current input field and replace text around
-   * cursor position. It will clear the current composition.
-   *
-   * @param text The string to be replaced with.
-   * @param offset The offset from the cursor position where replacing starts. Defaults to 0.
-   * @param length The length of text to replace. Defaults to 0.
-   * @return boolean
-   */
-  Promise<boolean> replaceSurroundingText(DOMString text, optional long offset, optional long length);
-
-  /**
-   * Delete text around the cursor.
-   * @param offset The offset from the cursor position where deletion starts.
-   * @param length The length of text to delete.
-   * TODO: maybe updateSurroundingText(DOMString beforeText, DOMString afterText); ?
-   * @return boolean
-   */
-  Promise<boolean> deleteSurroundingText(long offset, long length);
-
-  /**
-   * Notifies when the text around the cursor is changed, due to either text
-   * editing or cursor movement. If the cursor has been moved, but the text around has not
-   * changed, the IME won't get notification.
-   *
-   * evt.detail is defined by MozInputContextSurroundingTextChangeEventDetail.
-   */
-  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);
-
-  /**
-   * 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);
-
-  /**
-   * 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);
-
-  /**
-   * The interface used to receive the native events from hardware keyboard
-   */
-  readonly attribute MozHardwareInput? hardwareinput;
-};
-
-/*
- * This interface will be added into inputcontext and used to receive the
- * events from the hardware keyboard.
- * Example:
- *   mozInputMethod.inputcontext.hardwareinput.addEventListener('keyup', this);
- *   mozInputMethod.inputcontext.hardwareinput.removeEventListener('keyup', this);
- */
-[JSImplementation="@mozilla.org/b2g-hardwareinput;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozHardwareInput: EventTarget {
-};
-
-/**
- * Detail of the selectionchange event.
- */
-[JSImplementation="@mozilla.org/b2g-imm-selectionchange;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputContextSelectionChangeEventDetail {
-  /**
-   * Indicate whether or not the change is due to our own action from,
-   * for example, sendKey() call.
-   *
-   * Note: this property is untrustworthy because it would still be true even
-   * if script in the page changed the text synchronously upon responding to
-   * events trigger by the call.
-   */
-  readonly attribute boolean ownAction;
-
-  /**
-   * The start and stop position of the current selection.
-   */
-  readonly attribute long selectionStart;
-  readonly attribute long selectionEnd;
-};
-
-/**
- * Detail of the surroundingtextchange event.
- */
-[JSImplementation="@mozilla.org/b2g-imm-surroundingtextchange;1",
- Pref="dom.mozInputMethod.enabled",
- ChromeOnly]
-interface MozInputContextSurroundingTextChangeEventDetail {
-  /**
-   * Indicate whether or not the change is due to our own action from,
-   * for example, sendKey() call.
-   *
-   * Note: this property is untrustworthy because it would still be true even
-   * if script in the page changed the text synchronously upon responding to
-   * events trigger by the call.
-   */
-  readonly attribute boolean ownAction;
-
-  /**
-   * The text in the current input.
-   */
-  readonly attribute DOMString? text;
-
-  /**
-   * The text before and after the begining of the selected text.
-   *
-   * You should use the text property instead because these properties are
-   * truncated at 100 characters.
-   */
-  readonly attribute DOMString? textBeforeCursor;
-  readonly attribute DOMString? textAfterCursor;
-};
-
-enum CompositionClauseSelectionType {
-  "raw-input",
-  "selected-raw-text",
-  "converted-text",
-  "selected-converted-text"
-};
-
-dictionary CompositionClauseParameters {
-  CompositionClauseSelectionType selectionType = "raw-input";
-  long length;
-};
-
-/**
- * Types are HTML tag names of the inputs that is explosed with InputContext,
- * *and* the special keyword "contenteditable" for contenteditable element.
- */
-enum MozInputMethodInputContextTypes {
-  "input", "textarea", "contenteditable",
-  /**
-   * <select> is managed by the API but it is handled by the System app only,
-   * so this value is only accessible by System app from inputcontextfocus event.
-   */
-  "select"
-};
-
-/**
- * InputTypes of the input that InputContext is representing. The value
- * is inferred from the type attribute of element.
- *
- * See https://html.spec.whatwg.org/multipage/forms.html#states-of-the-type-attribute
- * for types of HTMLInputElement.
- *
- * They are divided into groups -- an layout/input capable of handling one type
- * in the group is considered as capable of handling all of the types in the
- * same group.
- * The layout/input that could handle type "text" is considered as the fallback
- * if none of layout/input installed can handle a specific type.
- *
- * Groups and fallbacks is enforced in Gaia System app currently.
- *
- * Noted that the actual virtual keyboard to show, for example in the case of
- * Gaia Keyboard app, will also depend on the inputMode of the input element.
- */
-enum MozInputMethodInputContextInputTypes {
-  /**
-   * Group "text". Be reminded that contenteditable element is assigned with
-   * an input type of "textarea".
-   */
-  "text", "search", "textarea",
-  /**
-   * Group "number"
-   */
-  "number", "tel",
-  /**
-   * Group "url"
-   */
-  "url",
-  /**
-   * Group "email"
-   */
-  "email",
-  /**
-   * Group "password".
-   * An non-Latin alphabet layout/input should not be able to handle this type.
-   */
-  "password",
-  /**
-   * Group "option". These types are handled by System app itself currently, so
-   * no input app will be set to active for these input types.
-   * System app access these types from inputcontextfocus event.
-   * ("select-one" and "select-multiple" are valid HTMLSelectElement#type.)
-   */
-  "datetime", "date", "month", "week", "time", "datetime-local", "color",
-  "select-one", "select-multiple"
-  /**
-   * These types are ignored by the API even though they are valid
-   * HTMLInputElement#type.
-   */
-  //"checkbox", "radio", "file", "submit", "image", "range", "reset", "button"
-};
-
-/**
- * An input app can host multiple inputs (a.k.a. layouts) and the capability of
- * the input is described by the input manifest.
- */
-dictionary MozInputMethodInputManifest {
-  required DOMString launch_path;
-  required DOMString name;
-  DOMString? description;
-  sequence<MozInputMethodInputContextInputTypes> types;
-};
-
-/**
- * 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/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -267,17 +267,16 @@ WEBIDL_FILES = [
     'IdleDeadline.webidl',
     'IIRFilterNode.webidl',
     'ImageBitmap.webidl',
     'ImageBitmapRenderingContext.webidl',
     'ImageCapture.webidl',
     'ImageData.webidl',
     'ImageDocument.webidl',
     'InputEvent.webidl',
-    'InputMethod.webidl',
     'InspectorUtils.webidl',
     'IntersectionObserver.webidl',
     'IterableIterator.webidl',
     'KeyAlgorithm.webidl',
     'KeyboardEvent.webidl',
     'KeyEvent.webidl',
     'KeyframeAnimationOptions.webidl',
     'KeyframeEffect.webidl',
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -762,22 +762,16 @@ PresShell::AccessibleCaretEnabled(nsIDoc
   // on the specific device running), then enable it.
   if (sAccessibleCaretOnTouch && dom::TouchEvent::PrefEnabled(aDocShell)) {
     return true;
   }
   // Otherwise, disabled.
   return false;
 }
 
-/* static */ bool
-PresShell::IsTargetIframe(nsINode* aTarget)
-{
-  return aTarget && aTarget->IsHTMLElement(nsGkAtoms::iframe);
-}
-
 PresShell::PresShell()
   : mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
 {
 #ifdef MOZ_REFLOW_PERF
   mReflowCountMgr = new ReflowCountMgr();
   mReflowCountMgr->SetPresContext(mPresContext);
   mReflowCountMgr->SetPresShell(this);
 #endif
@@ -7035,108 +7029,16 @@ PresShell::CanDispatchEvent(const Widget
   bool rv =
     mPresContext && !mHaveShutDown && nsContentUtils::IsSafeToRunScript();
   if (aEvent) {
     rv &= (aEvent && aEvent->mWidget && !aEvent->mWidget->Destroyed());
   }
   return rv;
 }
 
-void
-PresShell::HandleKeyboardEvent(nsINode* aTarget,
-                               WidgetKeyboardEvent& aEvent,
-                               bool aEmbeddedCancelled,
-                               nsEventStatus* aStatus,
-                               EventDispatchingCallback* aEventCB)
-{
-  MOZ_ASSERT(aTarget);
-  
-  // return true if the event target is in its child process
-  bool targetIsIframe = IsTargetIframe(aTarget);
-
-  ForwardKeyToInputMethodAppOrDispatch(targetIsIframe, aTarget, aEvent,
-                                       aStatus, aEventCB);
-}
-
-#ifdef MOZ_B2G
-bool
-PresShell::ForwardKeyToInputMethodApp(nsINode* aTarget,
-                                      WidgetKeyboardEvent& aEvent,
-                                      nsEventStatus* aStatus)
-{
-  if (!XRE_IsParentProcess() || aEvent.mIsSynthesizedByTIP ||
-      aEvent.IsKeyEventOnPlugin()) {
-    return false;
-  }
-
-  if (!mHardwareKeyHandler) {
-    nsresult rv;
-    mHardwareKeyHandler =
-      do_GetService("@mozilla.org/HardwareKeyHandler;1", &rv);
-    if (!NS_SUCCEEDED(rv) || !mHardwareKeyHandler) {
-      return false;
-    }
-  }
-
-  if (mHardwareKeyHandler->ForwardKeyToInputMethodApp(aTarget,
-                                                      aEvent.AsKeyboardEvent(),
-                                                      aStatus)) {
-    // No need to dispatch the forwarded keyboard event to it's child process
-    aEvent.mFlags.mNoCrossProcessBoundaryForwarding = true;
-    return true;
-  }
-
-  return false;
-}
-#endif // MOZ_B2G
-
-bool
-PresShell::ForwardKeyToInputMethodAppOrDispatch(bool aIsTargetRemote,
-                                                nsINode* aTarget,
-                                                WidgetKeyboardEvent& aEvent,
-                                                nsEventStatus* aStatus,
-                                                EventDispatchingCallback* aEventCB)
-{
-#ifndef MOZ_B2G
-  // No need to forward to input-method-app if the platform isn't run on B2G.
-  EventDispatcher::Dispatch(aTarget, mPresContext,
-                            &aEvent, nullptr, aStatus, aEventCB);
-  return false;
-#else
-  // In-process case: the event target is in the current process
-  if (!aIsTargetRemote) {
-    if(ForwardKeyToInputMethodApp(aTarget, aEvent, aStatus)) {
-      return true;
-    }
-
-    // If the keyboard event isn't forwarded to the input-method-app,
-    // then it should be dispatched to its event target directly.
-    EventDispatcher::Dispatch(aTarget, mPresContext,
-                              &aEvent, nullptr, aStatus, aEventCB);
-
-    return false;
-  }
-
-  // OOP case: the event target is in its child process.
-  // Dispatch the keyboard event to the iframe that embeds the remote
-  // event target first.
-  EventDispatcher::Dispatch(aTarget, mPresContext,
-                            &aEvent, nullptr, aStatus, aEventCB);
-
-  // If the event is defaultPrevented, then there is no need to forward it
-  // to the input-method-app.
-  if (aEvent.mFlags.mDefaultPrevented) {
-    return false;
-  }
-
-  // Try forwarding to the input-method-app.
-  return ForwardKeyToInputMethodApp(aTarget, aEvent, aStatus);
-#endif // MOZ_B2G
-}
-
 nsresult
 PresShell::HandleEvent(nsIFrame* aFrame,
                        WidgetGUIEvent* aEvent,
                        bool aDontRetargetEvents,
                        nsEventStatus* aEventStatus,
                        nsIContent** aTargetContent)
 {
 #ifdef MOZ_TASK_TRACER
@@ -8211,19 +8113,16 @@ PresShell::DispatchEventToDOM(WidgetEven
       eventCBPtr = nullptr;
     }
   }
   if (eventTarget) {
     if (aEvent->mClass == eCompositionEventClass) {
       IMEStateManager::DispatchCompositionEvent(eventTarget, mPresContext,
                                                 aEvent->AsCompositionEvent(),
                                                 aStatus, eventCBPtr);
-    } else if (aEvent->mClass == eKeyboardEventClass) {
-      HandleKeyboardEvent(eventTarget, *(aEvent->AsKeyboardEvent()),
-                          false, aStatus, eventCBPtr);
     } else {
       EventDispatcher::Dispatch(eventTarget, mPresContext,
                                 aEvent, nullptr, aStatus, eventCBPtr);
     }
   }
   return rv;
 }
 
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -86,18 +86,16 @@ public:
 
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
   // nsISupports
   NS_DECL_ISUPPORTS
 
   static bool AccessibleCaretEnabled(nsIDocShell* aDocShell);
 
-  static bool IsTargetIframe(nsINode* aTarget);
-
   void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
             nsViewManager* aViewManager, mozilla::StyleSetHandle aStyleSet);
   virtual void Destroy() override;
 
   virtual void UpdatePreferenceStyles() override;
 
   NS_IMETHOD GetSelection(RawSelectionType aRawSelectionType,
                           nsISelection** aSelection) override;
@@ -774,46 +772,16 @@ protected:
                                   Maybe<OnNonvisible> aNonvisibleAction = Nothing());
 
   nsRevocableEventPtr<nsRunnableMethod<PresShell>> mUpdateApproximateFrameVisibilityEvent;
 
   // A set of frames that were visible or could be visible soon at the time
   // that we last did an approximate frame visibility update.
   VisibleFrames mApproximatelyVisibleFrames;
 
-
-  //////////////////////////////////////////////////////////////////////////////
-  // Methods for dispatching KeyboardEvent.
-  //////////////////////////////////////////////////////////////////////////////
-
-  void HandleKeyboardEvent(nsINode* aTarget,
-                           mozilla::WidgetKeyboardEvent& aEvent,
-                           bool aEmbeddedCancelled,
-                           nsEventStatus* aStatus,
-                           mozilla::EventDispatchingCallback* aEventCB);
-
-#ifdef MOZ_B2G
-  // This method is used to forward the keyboard event to the input-method-app
-  // before the event is dispatched to its event target.
-  // Return true if it's successfully forwarded. Otherwise, return false.
-  bool ForwardKeyToInputMethodApp(nsINode* aTarget,
-                                  mozilla::WidgetKeyboardEvent& aEvent,
-                                  nsEventStatus* aStatus);
-#endif // MOZ_B2G
-
-  // This method tries forwarding key events to the input-method-editor(IME).
-  // If the event isn't be forwarded, then it will be dispathed to its target.
-  // Return true when event is successfully forwarded to the input-method-editor.
-  // Otherwise, return false.
-  bool ForwardKeyToInputMethodAppOrDispatch(bool aIsTargetRemote,
-                                            nsINode* aTarget,
-                                            mozilla::WidgetKeyboardEvent& aEvent,
-                                            nsEventStatus* aStatus,
-                                            mozilla::EventDispatchingCallback* aEventCB);
-
   nsresult SetResolutionImpl(float aResolution, bool aScaleToResolution);
 
 #ifdef DEBUG
   // The reflow root under which we're currently reflowing.  Null when
   // not in reflow.
   nsIFrame*                 mCurrentReflowRoot;
   uint32_t                  mUpdateCount;
 #endif
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1742,21 +1742,16 @@ protected:
 #endif
 
   // At least on Win32 and Mac after interupting a reflow we need to post
   // the resume reflow event off a timer to avoid event starvation because
   // posted messages are processed before other messages when the modal
   // moving/sizing loop is running, see bug 491700 for details.
   nsCOMPtr<nsITimer>        mReflowContinueTimer;
 
-#ifdef MOZ_B2G
-  // Forward hardware key events to the input-method-app
-  nsCOMPtr<nsIHardwareKeyHandler> mHardwareKeyHandler;
-#endif // MOZ_B2G
-
 #ifdef DEBUG
   nsIFrame*                 mDrawEventTargetFrame;
 
   // We track allocated pointers in a debug-only hashtable to assert against
   // missing/double frees.
   nsTHashtable<nsPtrHashKey<void>> mAllocatedPointers;
 #endif
 
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -207,21 +207,16 @@ static void Shutdown();
 
 #include "GMPService.h"
 
 #include "mozilla/dom/PresentationDeviceManager.h"
 #include "mozilla/dom/PresentationTCPSessionTransport.h"
 
 #include "mozilla/TextInputProcessor.h"
 
-#ifdef MOZ_B2G
-#include "nsIHardwareKeyHandler.h"
-#include "mozilla/HardwareKeyHandler.h"
-#endif
-
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::dom::power::PowerManagerService;
 using mozilla::dom::quota::QuotaManagerService;
 using mozilla::dom::workers::ServiceWorkerManager;
 using mozilla::dom::workers::WorkerDebuggerManager;
 using mozilla::dom::UDPSocketChild;
 using mozilla::dom::time::TimeService;
@@ -602,21 +597,16 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNullPrincipal, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(UDPSocketChild)
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(GeckoMediaPluginService, GeckoMediaPluginService::GetGeckoMediaPluginService)
 
-#ifdef MOZ_B2G
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIHardwareKeyHandler,
-                                         HardwareKeyHandler::GetInstance)
-#endif
-
 #ifdef ACCESSIBILITY
 #include "xpcAccessibilityService.h"
 
   MAKE_CTOR(CreateA11yService, nsIAccessibilityService, NS_GetAccessibilityService)
 #endif
 
 static nsresult
 Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
@@ -1057,19 +1047,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_MEDIAMANAGERSERVICE_CID, false, nullptr, nsIMediaManagerServiceConstructor },
 #ifdef ACCESSIBILITY
   { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService },
 #endif
   { &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor },
   { &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor },
   { &kPRESENTATION_TCP_SESSION_TRANSPORT_CID, false, nullptr, PresentationTCPSessionTransportConstructor },
   { &kTEXT_INPUT_PROCESSOR_CID, false, nullptr, TextInputProcessorConstructor },
-#ifdef MOZ_B2G
-  { &kNS_HARDWARE_KEY_HANDLER_CID, false, nullptr, nsIHardwareKeyHandlerConstructor },
-#endif
   { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
   XPCONNECT_CONTRACTS
   { "@mozilla.org/layout/xul-boxobject;1", &kNS_BOXOBJECT_CID },
 #ifdef MOZ_XUL
   { "@mozilla.org/layout/xul-boxobject-listbox;1", &kNS_LISTBOXOBJECT_CID },
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5050,19 +5050,16 @@ pref("captivedetect.pollingTime", 3000);
 pref("captivedetect.maxRetryCount", 5);
 
 #ifdef RELEASE_OR_BETA
 pref("dom.forms.inputmode", false);
 #else
 pref("dom.forms.inputmode", true);
 #endif
 
-// InputMethods for soft keyboards in B2G
-pref("dom.mozInputMethod.enabled", false);
-
 pref("dom.flyweb.enabled", false);
 
 // Enable mapped array buffer by default.
 pref("dom.mapped_arraybuffer.enabled", true);
 
 // The tables used for Safebrowsing phishing and malware checks.
 pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,test-malware-simple,test-unwanted-simple");