diff --git a/widget/TextEvents.h b/widget/TextEvents.h
index aa0e40ed1a0c..a0bb6c85acc1 100644
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -107,6 +107,8 @@ public:
   bool mIsRepeat;
   // DOM KeyboardEvent.key
   KeyNameIndex mKeyNameIndex;
+  // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
+  nsString mKeyValue;
   // OS-specific native event can optionally be preserved
   void* mNativeKeyEvent;
   // Unique id associated with a keydown / keypress event. Used in identifing
@@ -117,6 +119,10 @@ public:
 
   void GetDOMKeyName(nsAString& aKeyName)
   {
+    if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
+      aKeyName = mKeyValue;
+      return;
+    }
     GetDOMKeyName(mKeyNameIndex, aKeyName);
   }
 
@@ -147,6 +153,7 @@ public:
     isChar = aEvent.isChar;
     mIsRepeat = aEvent.mIsRepeat;
     mKeyNameIndex = aEvent.mKeyNameIndex;
+    mKeyValue = aEvent.mKeyValue;
     // Don't copy mNativeKeyEvent because it may be referred after its instance
     // is destroyed.
     mNativeKeyEvent = nullptr;
diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h
index e219d618705a..55980a74e046 100644
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -297,6 +297,7 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetInputEvent>(aParam));
     WriteParam(aMsg, static_cast<uint32_t>(aParam.mKeyNameIndex));
+    WriteParam(aMsg, aParam.mKeyValue);
     WriteParam(aMsg, aParam.keyCode);
     WriteParam(aMsg, aParam.charCode);
     WriteParam(aMsg, aParam.isChar);
@@ -313,6 +314,7 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
     if (ReadParam(aMsg, aIter,
                   static_cast<mozilla::WidgetInputEvent*>(aResult)) &&
         ReadParam(aMsg, aIter, &keyNameIndex) &&
+        ReadParam(aMsg, aIter, &aResult->mKeyValue) &&
         ReadParam(aMsg, aIter, &aResult->keyCode) &&
         ReadParam(aMsg, aIter, &aResult->charCode) &&
         ReadParam(aMsg, aIter, &aResult->isChar) &&