Bug 1297013 part.3 Make NativeKey log its behavior r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 21 Sep 2016 13:29:34 +0900
changeset 415841 3e95482c6151a94b8987301240c2faa963aa0d11
parent 415794 7bfc1fdc8bbf2b0429cbb79f460bdbfe17ce1f12
child 531712 aea6c7cdcce7bd802fa8e9549035273f67e23f61
push id29983
push usermasayuki@d-toybox.com
push dateWed, 21 Sep 2016 04:33:58 +0000
reviewersm_kato
bugs1297013
milestone52.0a1
Bug 1297013 part.3 Make NativeKey log its behavior r?m_kato MozReview-Commit-ID: 6ksuMFMxQdM
widget/windows/KeyboardLayout.cpp
widget/windows/KeyboardLayout.h
widget/windows/WinModifierKeyState.h
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -133,16 +133,22 @@ static const char* kVirtualKeyName[] = {
   "VK_OEM_ENLW", "VK_OEM_BACKTAB", "VK_ATTN", "VK_CRSEL",
   "VK_EXSEL", "VK_EREOF", "VK_PLAY", "VK_ZOOM",
   "VK_NONAME", "VK_PA1", "VK_OEM_CLEAR", "0xFF"
 };
 
 static_assert(sizeof(kVirtualKeyName) / sizeof(const char*) == 0x100,
   "The virtual key name must be defined just 256 keys");
 
+static const char*
+GetBoolName(bool aBool)
+{
+  return aBool ? "true" : "false";
+}
+
 static const nsCString
 GetCharacterCodeName(WPARAM aCharCode)
 {
   switch (aCharCode) {
     case 0x0000:
       return NS_LITERAL_CSTRING("NULL (0x0000)");
     case 0x0008:
       return NS_LITERAL_CSTRING("BACKSPACE (0x0008)");
@@ -240,16 +246,33 @@ GetCharacterCodeName(WPARAM aCharCode)
           NS_ConvertUTF16toUTF8(nsAutoString(aCharCode)).get(), aCharCode) :
         nsPrintfCString("'%s' (0x%08X)",
           NS_ConvertUTF16toUTF8(nsAutoString(aCharCode)).get(), aCharCode);
     }
   }
 }
 
 static const nsCString
+GetKeyLocationName(uint32_t aLocation)
+{
+  switch (aLocation) {
+    case nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT:
+      return NS_LITERAL_CSTRING("KEY_LOCATION_LEFT");
+    case nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT:
+      return NS_LITERAL_CSTRING("KEY_LOCATION_RIGHT");
+    case nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD:
+      return NS_LITERAL_CSTRING("KEY_LOCATION_STANDARD");
+    case nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD:
+      return NS_LITERAL_CSTRING("KEY_LOCATION_NUMPAD");
+    default:
+      return nsPrintfCString("Unknown (0x%04X)", aLocation);
+  }
+}
+
+static const nsCString
 GetCharacterCodeName(char16_t* aChars, uint32_t aLength)
 {
   if (!aLength) {
     return NS_LITERAL_CSTRING("");
   }
   nsAutoCString result;
   for (uint32_t i = 0; i < aLength; ++i) {
     if (!result.IsEmpty()) {
@@ -589,16 +612,52 @@ ToString(const MSG& aMSG)
     default:
       result.AppendPrintf("wParam=%u, lParam=%u", aMSG.wParam, aMSG.lParam);
       break;
   }
   result.AppendPrintf(", hwnd=0x%p", aMSG.hwnd);
   return result;
 }
 
+static const nsCString
+ToString(const UniCharsAndModifiers& aUniCharsAndModifiers)
+{
+  if (aUniCharsAndModifiers.IsEmpty()) {
+    return NS_LITERAL_CSTRING("{}");
+  }
+  nsAutoCString result;
+  result.AssignLiteral("{ ");
+  result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[0]));
+  for (uint32_t i = 1; i < aUniCharsAndModifiers.mLength; ++i) {
+    if (aUniCharsAndModifiers.mModifiers[i - 1] !=
+          aUniCharsAndModifiers.mModifiers[i]) {
+      result.AppendLiteral(" [");
+      result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[0]));
+      result.AppendLiteral("]");
+    }
+    result.AppendLiteral(", ");
+    result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[i]));
+  }
+  result.AppendLiteral(" [");
+  uint32_t lastIndex = aUniCharsAndModifiers.mLength - 1;
+  result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[lastIndex]));
+  result.AppendLiteral("] }");
+  return result;
+}
+
+const nsCString
+ToString(const ModifierKeyState& aModifierKeyState)
+{
+  nsAutoCString result;
+  result.AssignLiteral("{ ");
+  result.Append(GetModifiersName(aModifierKeyState.GetModifiers()).get());
+  result.AppendLiteral(" }");
+  return result;
+}
+
 // Unique id counter associated with a keydown / keypress events. Used in
 // identifing keypress events for removal from async event dispatch queue
 // in metrofx after preventDefault is called on keydown events.
 static uint32_t sUniqueKeyEventId = 0;
 
 struct DeadKeyEntry
 {
   char16_t BaseChar;
@@ -1127,16 +1186,18 @@ VirtualKey::FillKbdState(PBYTE aKbdState
 }
 
 /*****************************************************************************
  * mozilla::widget::NativeKey
  *****************************************************************************/
 
 uint8_t NativeKey::sDispatchedKeyOfAppCommand = 0;
 
+LazyLogModule sNativeKeyLogger("NativeKeyWidgets");
+
 NativeKey::NativeKey(nsWindowBase* aWidget,
                      const MSG& aMessage,
                      const ModifierKeyState& aModKeyState,
                      HKL aOverrideKeyboardLayout,
                      nsTArray<FakeCharMsg>* aFakeCharMsgs)
   : mWidget(aWidget)
   , mDispatcher(aWidget->GetTextEventDispatcher())
   , mMsg(aMessage)
@@ -1150,47 +1211,84 @@ NativeKey::NativeKey(nsWindowBase* aWidg
   , mShiftedLatinChar(0)
   , mUnshiftedLatinChar(0)
   , mScanCode(0)
   , mIsExtended(false)
   , mIsDeadKey(false)
   , mFakeCharMsgs(aFakeCharMsgs && aFakeCharMsgs->Length() ?
                     aFakeCharMsgs : nullptr)
 {
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p NativeKey::NativeKey(aWidget=0x%p { GetWindowHandle()=0x%p }, "
+     "aMessage=%s, aModKeyState=%s)",
+     this, aWidget, aWidget->GetWindowHandle(), ToString(aMessage).get(),
+     ToString(aModKeyState).get()));
+
   MOZ_ASSERT(aWidget);
   MOZ_ASSERT(mDispatcher);
   KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
   mKeyboardLayout = keyboardLayout->GetLayout();
   if (aOverrideKeyboardLayout && mKeyboardLayout != aOverrideKeyboardLayout) {
     keyboardLayout->OverrideLayout(aOverrideKeyboardLayout);
     mKeyboardLayout = keyboardLayout->GetLayout();
     MOZ_ASSERT(mKeyboardLayout == aOverrideKeyboardLayout);
     mIsOverridingKeyboardLayout = true;
   } else {
     mIsOverridingKeyboardLayout = false;
   }
 
   if (mMsg.message == WM_APPCOMMAND) {
     InitWithAppCommand();
-    return;
+  } else {
+    InitWithKeyChar();
   }
 
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::NativeKey(), mKeyboardLayout=0x%08X, "
+     "mFocusedWndBeforeDispatch=0x%p, mDOMKeyCode=0x%04X, "
+     "mKeyNameIndex=%s, mCodeNameIndex=%s, mModKeyState=%s, "
+     "mVirtualKeyCode=%s, mOriginalVirtualKeyCode=%s, "
+     "mCommittedCharsAndModifiers=%s, mInputtingStringAndModifiers=%s, "
+     "mShiftedString=%s, mUnshiftedString=%s, mShiftedLatinChar=%s, "
+     "mUnshiftedLatinChar=%s, mScanCode=0x%04X, mIsExtended=%s, "
+     "mIsDeadKey=%s, mIsPrintableKey=%s, mIsOverridingKeyboardLayout=%s",
+     this, mKeyboardLayout, mFocusedWndBeforeDispatch,
+     GetDOMKeyCodeName(mDOMKeyCode).get(), ToString(mKeyNameIndex).get(),
+     ToString(mCodeNameIndex).get(),
+     ToString(mModKeyState).get(),
+     GetVirtualKeyCodeName(mVirtualKeyCode).get(),
+     GetVirtualKeyCodeName(mOriginalVirtualKeyCode).get(),
+     ToString(mCommittedCharsAndModifiers).get(),
+     ToString(mInputtingStringAndModifiers).get(),
+     ToString(mShiftedString).get(), ToString(mUnshiftedString).get(),
+     GetCharacterCodeName(mShiftedLatinChar).get(),
+     GetCharacterCodeName(mUnshiftedLatinChar).get(),
+     mScanCode, GetBoolName(mIsExtended), GetBoolName(mIsDeadKey),
+     GetBoolName(mIsPrintableKey), GetBoolName(mIsOverridingKeyboardLayout)));
+}
+
+void
+NativeKey::InitWithKeyChar()
+{
   mScanCode = WinUtils::GetScanCode(mMsg.lParam);
   mIsExtended = WinUtils::IsExtendedScanCode(mMsg.lParam);
   switch (mMsg.message) {
     case WM_KEYDOWN:
     case WM_SYSKEYDOWN: {
       // If next message is WM_*CHAR message, let's consume it now.
       MSG charMsg;
       while (GetFollowingCharMessage(charMsg)) {
         // Although, got message shouldn't be WM_NULL in desktop apps,
         // we should keep checking this.  FYI: This was added for Metrofox.
         if (charMsg.message == WM_NULL) {
           continue;
         }
+        MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+          ("%p   NativeKey::InitWithKeyChar(), removed char message, %s",
+           this, ToString(charMsg).get()));
         NS_WARN_IF(charMsg.hwnd != mMsg.hwnd);
         mFollowingCharMsgs.AppendElement(charMsg);
       }
       MOZ_FALLTHROUGH;
     }
     case WM_KEYUP:
     case WM_SYSKEYUP:
     case MOZ_WM_KEYDOWN:
@@ -1345,16 +1443,17 @@ NativeKey::NativeKey(nsWindowBase* aWidg
     default:
       MOZ_CRASH("Unsupported message");
   }
 
   if (!mVirtualKeyCode) {
     mVirtualKeyCode = mOriginalVirtualKeyCode;
   }
 
+  KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
   mDOMKeyCode =
     keyboardLayout->ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode);
   // Be aware, keyboard utilities can change non-printable keys to printable
   // keys.  In such case, we should make the key value as a printable key.
   // FYI: IsFollowedByNonControlCharMessage() returns true only when it's
   //      handling a keydown message.
   mKeyNameIndex = IsFollowedByNonControlCharMessage() ?
     KEY_NAME_INDEX_USE_STRING :
@@ -1405,16 +1504,18 @@ NativeKey::NativeKey(nsWindowBase* aWidg
     }
     // Remove odd char messages if there are.
     RemoveFollowingOddCharMessages();
   }
 }
 
 NativeKey::~NativeKey()
 {
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+    ("%p   NativeKey::~NativeKey(), destroyed", this));
   if (mIsOverridingKeyboardLayout) {
     KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
     keyboardLayout->RestoreLayout();
   }
 }
 
 void
 NativeKey::InitWithAppCommand()
@@ -1606,16 +1707,20 @@ NativeKey::RemoveFollowingOddCharMessage
   MSG msg;
   while (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_CHAR, WM_CHAR,
                                PM_REMOVE | PM_NOYIELD)) {
     if (msg.message != WM_CHAR) {
       MOZ_RELEASE_ASSERT(msg.message == WM_NULL,
                          "Unexpected message was removed");
       continue;
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::RemoveFollowingOddCharMessages(), removed odd char "
+       "message, %s",
+       this, ToString(msg).get()));
     mRemovedOddCharMsgs.AppendElement(msg);
   }
 }
 
 UINT
 NativeKey::GetScanCodeWithExtendedFlag() const
 {
   if (!mIsExtended) {
@@ -1806,16 +1911,29 @@ NativeKey::InitKeyEvent(WidgetKeyboardEv
     pluginEvent.event = aMsgSentToPlugin->message;
     pluginEvent.wParam = aMsgSentToPlugin->wParam;
     pluginEvent.lParam = aMsgSentToPlugin->lParam;
     aKeyEvent.mPluginEvent.Copy(pluginEvent);
   }
 
   KeyboardLayout::NotifyIdleServiceOfUserActivity();
 
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::InitKeyEvent(), initialized, aKeyEvent={ "
+     "mMessage=%s, mKeyNameIndex=%s, mKeyValue=\"%s\", mCodeNameIndex=%s, "
+     "mKeyCode=%s, mLocation=%s, mModifiers=%s, DefaultPrevented()=%s }",
+     this, ToChar(aKeyEvent.mMessage),
+     ToString(aKeyEvent.mKeyNameIndex).get(),
+     NS_ConvertUTF16toUTF8(aKeyEvent.mKeyValue).get(),
+     ToString(aKeyEvent.mCodeNameIndex).get(),
+     GetDOMKeyCodeName(aKeyEvent.mKeyCode).get(),
+     GetKeyLocationName(aKeyEvent.mLocation).get(),
+     GetModifiersName(aKeyEvent.mModifiers).get(),
+     GetBoolName(aKeyEvent.DefaultPrevented())));
+
   return aKeyEvent.DefaultPrevented() ? nsEventStatus_eConsumeNoDefault :
                                         nsEventStatus_eIgnore;
 }
 
 bool
 NativeKey::DispatchCommandEvent(uint32_t aEventCommand) const
 {
   nsCOMPtr<nsIAtom> command;
@@ -1879,23 +1997,34 @@ NativeKey::DispatchCommandEvent(uint32_t
       break;
     case APPCOMMAND_MEDIA_STOP:
       command = nsGkAtoms::MediaStop;
       break;
     case APPCOMMAND_MEDIA_PLAY_PAUSE:
       command = nsGkAtoms::PlayPause;
       break;
     default:
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::DispatchCommandEvent(), doesn't dispatch command "
+         "event", this));
       return false;
   }
   WidgetCommandEvent commandEvent(true, nsGkAtoms::onAppCommand,
                                   command, mWidget);
 
   mWidget->InitEvent(commandEvent);
-  return (mWidget->DispatchWindowEvent(&commandEvent) || mWidget->Destroyed());
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::DispatchCommandEvent(), dispatching %s command event...",
+     this, nsAtomCString(command).get()));
+  bool ok = mWidget->DispatchWindowEvent(&commandEvent) || mWidget->Destroyed();
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::DispatchCommandEvent(), dispatched command event, "
+     "result=%s, mWidget->Destroyed()=%s",
+     this, GetBoolName(ok), GetBoolName(mWidget->Destroyed())));
+  return ok;
 }
 
 bool
 NativeKey::HandleAppCommandMessage() const
 {
   // NOTE: Typical behavior of WM_APPCOMMAND caused by key is, WM_APPCOMMAND
   //       message is _sent_ first.  Then, the DefaultWndProc will _post_
   //       WM_KEYDOWN message and WM_KEYUP message if the keycode for the
@@ -1920,31 +2049,50 @@ NativeKey::HandleAppCommandMessage() con
       WinUtils::IsOurProcessWindow(reinterpret_cast<HWND>(mMsg.wParam));
   }
 
   bool consumed = false;
 
   if (dispatchKeyEvent) {
     nsresult rv = mDispatcher->BeginNativeInputTransaction();
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::HandleAppCommandMessage(), FAILED due to "
+         "BeginNativeInputTransaction() failure", this));
       return true;
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), initializing keydown "
+       "event...", this));
     WidgetKeyboardEvent keydownEvent(true, eKeyDown, mWidget);
     nsEventStatus status = InitKeyEvent(keydownEvent, mModKeyState, &mMsg);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), tries to dispatch "
+       "keydown event...", this));
     // NOTE: If the keydown event is consumed by web contents, we shouldn't
     //       continue to handle the command.
     if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, status,
                                             const_cast<NativeKey*>(this))) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), keydown event isn't "
+         "dispatched", this));
       // If keyboard event wasn't fired, there must be composition.
       // So, we don't need to dispatch a command event.
       return true;
     }
     consumed = status == nsEventStatus_eConsumeNoDefault;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), keydown event was "
+       "dispatched, consumed=%s",
+       this, GetBoolName(consumed)));
     sDispatchedKeyOfAppCommand = mVirtualKeyCode;
     if (mWidget->Destroyed()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), keydown event caused "
+         "destroying the widget", this));
       return true;
     }
   }
 
   // Dispatch a command event or a content command event if the command is
   // supported.
   if (!consumed) {
     uint32_t appCommand = GET_APPCOMMAND_LPARAM(mMsg.lParam);
@@ -1993,39 +2141,68 @@ NativeKey::HandleAppCommandMessage() con
       case APPCOMMAND_UNDO:
         contentCommandMessage = eContentCommandUndo;
         break;
     }
 
     if (contentCommandMessage) {
       WidgetContentCommandEvent contentCommandEvent(true, contentCommandMessage,
                                                     mWidget);
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), dispatching %s event...",
+         this, ToChar(contentCommandMessage)));
       mWidget->DispatchWindowEvent(&contentCommandEvent);
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), dispatched %s event",
+         this, ToChar(contentCommandMessage)));
       consumed = true;
-    }
-
-    if (mWidget->Destroyed()) {
-      return true;
+
+      if (mWidget->Destroyed()) {
+        MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+          ("%p   NativeKey::HandleAppCommandMessage(), %s event caused "
+           "destroying the widget",
+           this, ToChar(contentCommandMessage)));
+        return true;
+      }
+    } else {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), doesn't dispatch content "
+         "command event", this));
     }
   }
 
   // Dispatch a keyup event if the command is caused by pressing a key and
   // the key isn't mapped to a virtual keycode.
   if (dispatchKeyEvent && !mVirtualKeyCode) {
     nsresult rv = mDispatcher->BeginNativeInputTransaction();
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::HandleAppCommandMessage(), FAILED due to "
+         "BeginNativeInputTransaction() failure", this));
       return true;
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), initializing keyup "
+       "event...", this));
     WidgetKeyboardEvent keyupEvent(true, eKeyUp, mWidget);
     nsEventStatus status = InitKeyEvent(keyupEvent, mModKeyState, &mMsg);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), dispatching keyup event...",
+       this));
     // NOTE: Ignore if the keyup event is consumed because keyup event
     //       represents just a physical key event state change.
     mDispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status,
                                        const_cast<NativeKey*>(this));
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleAppCommandMessage(), dispatched keyup event",
+       this));
     if (mWidget->Destroyed()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleAppCommandMessage(), %s event caused "
+         "destroying the widget", this));
       return true;
     }
   }
 
   return consumed;
 }
 
 bool
@@ -2037,61 +2214,95 @@ NativeKey::HandleKeyDownMessage(bool* aE
     *aEventDispatched = false;
   }
 
   if (sDispatchedKeyOfAppCommand &&
       sDispatchedKeyOfAppCommand == mOriginalVirtualKeyCode) {
     // The multimedia key event has already been dispatch from
     // HandleAppCommandMessage().
     sDispatchedKeyOfAppCommand = 0;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), doesn't dispatch keydown "
+       "event due to already dispatched from HandleAppCommandMessage(), ",
+       this));
     return true;
   }
 
   bool defaultPrevented = false;
   if (mFakeCharMsgs || IsKeyMessageOnPlugin() ||
       !RedirectedKeyDownMessageManager::IsRedirectedMessage(mMsg)) {
     // Ignore [shift+]alt+space so the OS can handle it.
     if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
         mVirtualKeyCode == VK_SPACE) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), doesn't dispatch keydown "
+         "event due to Alt+Space", this));
       return false;
     }
 
     nsresult rv = mDispatcher->BeginNativeInputTransaction();
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::HandleKeyDownMessage(), FAILED due to "
+         "BeginNativeInputTransaction() failure", this));
       return true;
     }
 
     bool isIMEEnabled = WinUtils::IsIMEEnabled(mWidget->GetInputContext());
+
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+      ("%p   NativeKey::HandleKeyDownMessage(), initializing keydown "
+       "event...", this));
+
     EventMessage keyDownMessage =
       IsKeyMessageOnPlugin() ? eKeyDownOnPlugin : eKeyDown;
     WidgetKeyboardEvent keydownEvent(true, keyDownMessage, mWidget);
     nsEventStatus status = InitKeyEvent(keydownEvent, mModKeyState, &mMsg);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), dispatching keydown event...",
+       this));
     bool dispatched =
       mDispatcher->DispatchKeyboardEvent(keyDownMessage, keydownEvent, status,
                                          const_cast<NativeKey*>(this));
     if (aEventDispatched) {
       *aEventDispatched = dispatched;
     }
     if (!dispatched) {
       // If the keydown event wasn't fired, there must be composition.
       // we don't need to do anything anymore.
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), doesn't dispatch keypress "
+         "event(s) because keydown event isn't dispatched actually", this));
       return false;
     }
     defaultPrevented = status == nsEventStatus_eConsumeNoDefault;
 
     // We don't need to handle key messages on plugin for eKeyPress since
     // eKeyDownOnPlugin is handled as both eKeyDown and eKeyPress.
     if (IsKeyMessageOnPlugin()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), doesn't dispatch keypress "
+         "event(s) because it's a keydown message on windowed plugin, "
+         "defaultPrevented=%s",
+         this, GetBoolName(defaultPrevented)));
       return defaultPrevented;
     }
 
     if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), keydown event caused "
+         "destroying the widget", this));
       return true;
     }
 
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), dispatched keydown event, "
+       "dispatched=%s, defaultPrevented=%s",
+       this, GetBoolName(dispatched), GetBoolName(defaultPrevented)));
+
     // If IMC wasn't associated to the window but is associated it now (i.e.,
     // focus is moved from a non-editable editor to an editor by keydown
     // event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
     // inputting if IME is opened.  But then, we should redirect the native
     // keydown message to IME.
     // However, note that if focus has been already moved to another
     // application, we shouldn't redirect the message to it because the keydown
     // message is processed by us, so, nobody shouldn't process it.
@@ -2109,82 +2320,135 @@ NativeKey::HandleKeyDownMessage(bool* aE
       if (mIsExtended) {
         keyinput.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
       }
       keyinput.ki.time = 0;
       keyinput.ki.dwExtraInfo = 0;
 
       RedirectedKeyDownMessageManager::WillRedirect(mMsg, defaultPrevented);
 
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), redirecting %s...",
+         this, ToString(mMsg).get()));
+
       ::SendInput(1, &keyinput, sizeof(keyinput));
 
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleKeyDownMessage(), redirected %s",
+         this, ToString(mMsg).get()));
+
       // Return here.  We shouldn't dispatch keypress event for this WM_KEYDOWN.
       // If it's needed, it will be dispatched after next (redirected)
       // WM_KEYDOWN.
       return true;
     }
   } else {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), received a redirected %s",
+       this, ToString(mMsg).get()));
+
     defaultPrevented = RedirectedKeyDownMessageManager::DefaultPrevented();
     // If this is redirected keydown message, we have dispatched the keydown
     // event already.
     if (aEventDispatched) {
       *aEventDispatched = true;
     }
   }
 
   RedirectedKeyDownMessageManager::Forget();
 
   // If the key was processed by IME, we shouldn't dispatch keypress event.
   if (mOriginalVirtualKeyCode == VK_PROCESSKEY) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), not dispatching keypress "
+       "event because the key was already handled by IME, defaultPrevented=%s",
+       this, GetBoolName(defaultPrevented)));
     return defaultPrevented;
   }
 
   if (defaultPrevented) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), not dispatching keypress "
+       "event because preceding keydown event was consumed",
+       this));
     MaybeDispatchPluginEventsForRemovedCharMessages();
     return true;
   }
 
   // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a
   // keypress for almost all keys
   if (NeedsToHandleWithoutFollowingCharMessages()) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), tries to be dispatching "
+       "keypress events...", this));
     return (MaybeDispatchPluginEventsForRemovedCharMessages() ||
             DispatchKeyPressEventsWithoutCharMessage());
   }
 
   if (!mFollowingCharMsgs.IsEmpty()) {
     bool consumed = false;
     for (size_t i = 0; i < mFollowingCharMsgs.Length(); ++i) {
+        MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+          ("%p   NativeKey::HandleKeyDownMessage(), stopped dispatching "
+           "keypress events for remaining char messages, consumed=%s, "
+           "mFollowingCharMsgs[%u]=%s, mMsg=%s, "
+           "mFocusedWndBeforeDispatch=0x%p, ::GetFocus()=0x%p",
+           this, GetBoolName(consumed), i,
+           ToString(mFollowingCharMsgs[i]).get(),
+           ToString(mMsg).get(), mFocusedWndBeforeDispatch, ::GetFocus()));
       consumed =
         DispatchKeyPressEventForFollowingCharMessage(mFollowingCharMsgs[i]) ||
         consumed;
       if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+        MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+          ("%p   NativeKey::HandleKeyDownMessage(), %s event caused "
+           "destroying the widget", this));
         return true;
       }
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), handled all following char "
+       "messages, consumed=%s",
+       this, GetBoolName(consumed)));
     return consumed;
   }
 
   // If WM_KEYDOWN of VK_PACKET isn't followed by WM_CHAR, we don't need to
   // dispatch keypress events.
   if (mVirtualKeyCode == VK_PACKET) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+       "because the key is VK_PACKET and there are no char messages",
+       this));
     return false;
   }
 
   if (!mModKeyState.IsControl() && !mModKeyState.IsAlt() &&
       !mModKeyState.IsWin() && mIsPrintableKey) {
     // If this is simple KeyDown event but next message is not WM_CHAR,
     // this event may not input text, so we should ignore this event.
     // See bug 314130.
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+       "because the key event is simple printable key's event but not followed "
+       "by char messages", this));
     return false;
   }
 
   if (mIsDeadKey) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+       "because the key is a dead key and not followed by char messages",
+       this));
     return false;
   }
 
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::HandleKeyDownMessage(), tries to be dispatching "
+     "keypress events due to no following char messages...", this));
   return DispatchKeyPressEventsWithoutCharMessage();
 }
 
 bool
 NativeKey::HandleCharMessage(const MSG& aCharMsg,
                              bool* aEventDispatched) const
 {
   MOZ_ASSERT(IsKeyDownMessage() || IsPrintableCharMessage(mMsg));
@@ -2192,22 +2456,28 @@ NativeKey::HandleCharMessage(const MSG& 
 
   if (aEventDispatched) {
     *aEventDispatched = false;
   }
 
   // Alt+Space key is handled by OS, we shouldn't touch it.
   if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
       mVirtualKeyCode == VK_SPACE) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), doesn't dispatch keypress "
+       "event due to Alt+Space", this));
     return false;
   }
 
   // Bug 818235: Ignore Ctrl+Enter.
   if (!mModKeyState.IsAlt() && mModKeyState.IsControl() &&
       mVirtualKeyCode == VK_RETURN) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), doesn't dispatch keypress "
+       "event due to Ctrl+Enter", this));
     return false;
   }
 
   // XXXmnakao I think that if aNativeKeyDown is null, such lonely WM_CHAR
   //           should cause composition events because they are not caused
   //           by actual keyboard operation.
 
   static const char16_t U_EQUAL = 0x3D;
@@ -2220,131 +2490,226 @@ NativeKey::HandleCharMessage(const MSG& 
     WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
     if (!IsControlChar(static_cast<char16_t>(aCharMsg.wParam))) {
       keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
     } else {
       keypressEvent.mKeyCode = mDOMKeyCode;
     }
     nsresult rv = mDispatcher->BeginNativeInputTransaction();
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::HandleCharMessage(), FAILED due to "
+         "BeginNativeInputTransaction() failure", this));
       return true;
     }
 
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+      ("%p   NativeKey::HandleCharMessage(), initializing keypress "
+       "event...", this));
+
     // When AltGr (Alt+Ctrl) is pressed, that causes normal text input.
     // At this time, if either alt or ctrl flag is set, EditorBase ignores the
     // keypress event.  For avoiding this issue, we should remove ctrl and alt
     // flags.
     ModifierKeyState modKeyState(mModKeyState);
     modKeyState.Unset(MODIFIER_ALT | MODIFIER_CONTROL);
     nsEventStatus status = InitKeyEvent(keypressEvent, modKeyState, &aCharMsg);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), dispatching keypress event...",
+       this));
     bool dispatched =
       mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
                                                const_cast<NativeKey*>(this));
     if (aEventDispatched) {
       *aEventDispatched = dispatched;
     }
-    return status == nsEventStatus_eConsumeNoDefault;
+    if (mWidget->Destroyed()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleCharMessage(), keypress event caused "
+         "destroying the widget", this));
+      return true;
+    }
+    bool consumed = status == nsEventStatus_eConsumeNoDefault;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), dispatched keypress event, "
+       "dispatched=%s, consumed=%s",
+       this, GetBoolName(dispatched), GetBoolName(consumed)));
+    return consumed;
   }
 
   // XXX It seems that following code was implemented for shortcut key
   //     handling.  However, it's now handled in WM_KEYDOWN message handler.
   //     So, this actually runs only when WM_CHAR is sent/posted without
   //     WM_KEYDOWN.  I think that we don't need to keypress event in such
   //     case especially for shortcut keys.
 
   char16_t uniChar;
   // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
   if (mModKeyState.IsControl() &&
       IsControlChar(static_cast<char16_t>(aCharMsg.wParam))) {
     // Bug 16486: Need to account for shift here.
     uniChar = aCharMsg.wParam - 1 + (mModKeyState.IsShift() ? 'A' : 'a');
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), computing charCode for ASCII "
+       "control characters which are inputted with Ctrl key, uniChar=%s",
+       this, GetCharacterCodeName(uniChar).get()));
   } else if (mModKeyState.IsControl() && aCharMsg.wParam <= 0x1F) {
+    // XXX Looks like that this block won't run since the condition is
+    //     included in the first |if|'s condition.
     // Bug 50255: <ctrl><[> and <ctrl><]> are not being processed.
     // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
     // for some reason the keypress handler need to have the uniChar code set
     // with the addition of a upper case A not the lower case.
     uniChar = aCharMsg.wParam - 1 + 'A';
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), computing charCode for ASCII "
+       "control characters which are inputted with Ctrl key, uniChar=%s",
+       this, GetCharacterCodeName(uniChar).get()));
   } else if (IsControlChar(static_cast<char16_t>(aCharMsg.wParam)) ||
              (aCharMsg.wParam == U_EQUAL && mModKeyState.IsControl())) {
     uniChar = 0;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), setting charCode to 0 because "
+       "the character is a control character without Ctrl key or Ctrl+=",
+       this));
   } else {
     uniChar = aCharMsg.wParam;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), deciding to use given charCode, "
+       "uniChar=%s",
+       this, GetCharacterCodeName(uniChar).get()));
   }
 
   // Bug 50255 and Bug 351310: Keep the characters unshifted for shortcuts and
   // accesskeys and make sure that numbers are always passed as such.
   if (uniChar && (mModKeyState.IsControl() || mModKeyState.IsAlt())) {
     char16_t unshiftedCharCode =
       (mVirtualKeyCode >= '0' && mVirtualKeyCode <= '9') ?
         mVirtualKeyCode :  mModKeyState.IsShift() ?
                              ComputeUnicharFromScanCode() : 0;
     // Ignore diacritics (top bit set) and key mapping errors (char code 0)
-    if (static_cast<int32_t>(unshiftedCharCode) > 0) {
+    if (uniChar != unshiftedCharCode &&
+        static_cast<int32_t>(unshiftedCharCode) > 0) {
       uniChar = unshiftedCharCode;
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::HandleCharMessage(), adjusting computed charCode "
+         "because unshifted charCode is better, uniChar=%s, mModKeyState=%s",
+         this, GetCharacterCodeName(uniChar).get(),
+         ToString(mModKeyState).get()));
     }
   }
 
   // Bug 285161 and Bug 295095: They were caused by the initial fix for
   // bug 178110.  When pressing (alt|ctrl)+char, the char must be lowercase
   // unless shift is pressed too.
   if (!mModKeyState.IsShift() &&
-      (mModKeyState.IsAlt() || mModKeyState.IsControl())) {
+      (mModKeyState.IsAlt() || mModKeyState.IsControl()) &&
+      uniChar != towlower(uniChar)) {
     uniChar = towlower(uniChar);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), making computed charCode "
+       "lower case character because Shift isn't pressed but Ctrl or Alt is "
+       "pressed, uniChar=%s, mModKeyState=%s",
+       this, GetCharacterCodeName(uniChar).get(),
+       ToString(mModKeyState).get()));
   }
 
   nsresult rv = mDispatcher->BeginNativeInputTransaction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+      ("%p   NativeKey::HandleCharMessage(), FAILED due to "
+       "BeginNativeInputTransaction() failure", this));
     return true;
   }
 
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+    ("%p   NativeKey::HandleCharMessage(), initializing keypress "
+     "event after some hacks...", this));
   WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
   keypressEvent.mCharCode = uniChar;
   if (!keypressEvent.mCharCode) {
     keypressEvent.mKeyCode = mDOMKeyCode;
   }
   nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState, &aCharMsg);
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::HandleCharMessage(), dispatching keypress event with "
+     "some hacks...", this));
   bool dispatched =
     mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
                                              const_cast<NativeKey*>(this));
   if (aEventDispatched) {
     *aEventDispatched = dispatched;
   }
-  return status == nsEventStatus_eConsumeNoDefault;
+  if (mWidget->Destroyed()) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleCharMessage(), keypress event caused "
+       "destroying the widget", this));
+    return true;
+  }
+  bool consumed = status == nsEventStatus_eConsumeNoDefault;
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::HandleCharMessage(), dispatched keypress event with "
+     "some hacks, dispatched=%s, consumed=%s",
+     this, GetBoolName(dispatched), GetBoolName(consumed)));
+  return consumed;
 }
 
 bool
 NativeKey::HandleKeyUpMessage(bool* aEventDispatched) const
 {
   MOZ_ASSERT(IsKeyUpMessage());
 
   if (aEventDispatched) {
     *aEventDispatched = false;
   }
 
   // Ignore [shift+]alt+space so the OS can handle it.
   if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
       mVirtualKeyCode == VK_SPACE) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyUpMessage(), doesn't dispatch keyup "
+       "event due to Alt+Space", this));
     return false;
   }
 
   nsresult rv = mDispatcher->BeginNativeInputTransaction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+      ("%p   NativeKey::HandleKeyUpMessage(), FAILED due to "
+       "BeginNativeInputTransaction() failure", this));
     return true;
   }
 
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+    ("%p   NativeKey::HandleKeyUpMessage(), initializing keyup event...",
+     this));
   EventMessage keyUpMessage = IsKeyMessageOnPlugin() ? eKeyUpOnPlugin : eKeyUp;
   WidgetKeyboardEvent keyupEvent(true, keyUpMessage, mWidget);
   nsEventStatus status = InitKeyEvent(keyupEvent, mModKeyState, &mMsg);
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::HandleKeyUpMessage(), dispatching keyup event...",
+     this));
   bool dispatched =
     mDispatcher->DispatchKeyboardEvent(keyUpMessage, keyupEvent, status,
                                        const_cast<NativeKey*>(this));
   if (aEventDispatched) {
     *aEventDispatched = dispatched;
   }
-  return status == nsEventStatus_eConsumeNoDefault;
+  if (mWidget->Destroyed()) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::HandleKeyUpMessage(), keyup event caused "
+       "destroying the widget", this));
+    return true;
+  }
+  bool consumed = status == nsEventStatus_eConsumeNoDefault;
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::HandleKeyUpMessage(), dispatched keyup event, "
+     "dispatched=%s, consumed=%s",
+     this, GetBoolName(dispatched), GetBoolName(consumed)));
+  return consumed;
 }
 
 bool
 NativeKey::NeedsToHandleWithoutFollowingCharMessages() const
 {
   MOZ_ASSERT(IsKeyDownMessage());
 
   // We cannot know following char messages of key messages in a plugin
@@ -2476,16 +2841,19 @@ NativeKey::GetFollowingCharMessage(MSG& 
   // related char message for the handling keydown event for now.
   // Note that it's possible other applications may send other key message
   // after we call TranslateMessage(). That may cause PeekMessage() failing
   // to get char message for the handling keydown message.
   MSG nextKeyMsg;
   if (!WinUtils::PeekMessage(&nextKeyMsg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
                              PM_NOREMOVE | PM_NOYIELD) ||
       !IsCharMessage(nextKeyMsg)) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Verbose,
+      ("%p   NativeKey::GetFollowingCharMessage(), there are no char messages",
+       this));
     return false;
   }
 
   // On Metrofox, PeekMessage() sometimes returns WM_NULL even if we specify
   // the message range.  So, if it returns WM_NULL, we should retry to get
   // the following char message it was found above.
   for (uint32_t i = 0; i < 5; i++) {
     MSG removedMsg, nextKeyMsgInAllWindows;
@@ -2496,35 +2864,54 @@ NativeKey::GetFollowingCharMessage(MSG& 
       // We meets unexpected case.  We should collect the message queue state
       // and crash for reporting the bug.
       doCrash = true;
       // The char message is redirected to different thread's window by focus
       // move or something or just cancelled by external application.
       if (!WinUtils::PeekMessage(&nextKeyMsgInAllWindows, 0,
                                  WM_KEYFIRST, WM_KEYLAST,
                                  PM_NOREMOVE | PM_NOYIELD)) {
+        MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+          ("%p   NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+           "remove a char message, but it's already gone from all message "
+           "queues, nextKeyMsg=%s",
+           this, ToString(nextKeyMsg).get()));
         return true;
       }
       if (MayBeSameCharMessage(nextKeyMsgInAllWindows, nextKeyMsg)) {
         // The char message is redirected to different window created by our
         // thread.
         if (nextKeyMsgInAllWindows.hwnd != mMsg.hwnd) {
           aCharMsg = nextKeyMsgInAllWindows;
+          MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+            ("%p   NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+             "remove a char message, but found in another message queue, "
+             "nextKeyMsgInAllWindows=%s",
+             this, ToString(nextKeyMsgInAllWindows).get()));
           return true;
         }
         // The found char message still in the queue, but PeekMessage() failed
         // to remove it only with PM_REMOVE.  Although, we don't know why this
         // occurs.  However, this occurs acctually.
         // Try to remove the char message with GetMessage() again.
         if (WinUtils::GetMessage(&removedMsg, mMsg.hwnd,
                                  nextKeyMsg.message, nextKeyMsg.message)) {
+          MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+            ("%p   NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+             "remove a char message, but succeeded with GetMessage(), "
+             "removedMsg=%s",
+             this, ToString(removedMsg).get()));
           // Cancel to crash, but we need to check the removed message value.
           doCrash = false;
         }
       }
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::GetFollowingCharMessage(), FAILED, lost target "
+         "message to remove, nextKeyMsg=%s",
+         this, ToString(nextKeyMsg).get()));
     }
 
     if (doCrash) {
 #ifdef MOZ_CRASHREPORTER
       nsPrintfCString info("\nPeekMessage() failed to remove char message! "
                            "\nHandling message: %s, InSendMessageEx()=%s, "
                            "\nFound message: %s, "
                            "\nWM_NULL has been removed: %d, "
@@ -2547,30 +2934,45 @@ NativeKey::GetFollowingCharMessage(MSG& 
           NS_LITERAL_CSTRING("\nThere is no message in any window"));
       }
 #endif // #ifdef MOZ_CRASHREPORTER
       MOZ_CRASH("We lost the following char message");
     }
 
     // Retry for the strange case.
     if (removedMsg.message == WM_NULL) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+        ("%p   NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+         "remove a char message, instead, removed WM_NULL message, ",
+         "removedMsg=%s",
+         this, ToString(removedMsg).get()));
       continue;
     }
 
     // Typically, this case occurs with WM_DEADCHAR.  If the removed message's
     // wParam becomes 0, that means that the key event shouldn't cause text
     // input.  So, let's ignore the strange char message.
     if (removedMsg.message == nextKeyMsg.message && !removedMsg.wParam) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+        ("%p   NativeKey::GetFollowingCharMessage(), WARNING, succeeded to "
+         "remove a char message, but the removed message's wParam is 0, "
+         "removedMsg=%s",
+         this, ToString(removedMsg).get()));
       return false;
     }
 
     // NOTE: Although, we don't know when this case occurs, the scan code value
     //       in lParam may be changed from 0 to something.  The changed value
     //       is different from the scan code of handling keydown message.
     if (!MayBeSameCharMessage(removedMsg, nextKeyMsg)) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+        ("%p   NativeKey::GetFollowingCharMessage(), FAILED, removed message "
+         "is really different from what we have already found, removedMsg=%s, "
+         "nextKeyMsg=%s",
+         this, ToString(removedMsg).get(), ToString(nextKeyMsg).get()));
 #ifdef MOZ_CRASHREPORTER
       nsPrintfCString info("\nPeekMessage() removed unexpcted char message! "
                            "\nHandling message: %s, InSendMessageEx()=%s, "
                            "\nFound message: %s, "
                            "\nRemoved message: %s, ",
                            ToString(mMsg).get(),
                            GetResultOfInSendMessageEx().get(),
                            ToString(nextKeyMsg).get(),
@@ -2602,18 +3004,26 @@ NativeKey::GetFollowingCharMessage(MSG& 
         CrashReporter::AppendAppNotesToCrashReport(
           NS_LITERAL_CSTRING("\nThere is no key message in any windows."));
       }
 #endif // #ifdef MOZ_CRASHREPORTER
       MOZ_CRASH("PeekMessage() removed unexpected message");
     }
 
     aCharMsg = removedMsg;
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Verbose,
+      ("%p   NativeKey::GetFollowingCharMessage(), succeeded to retrieve next "
+       "char message, aCharMsg=%s",
+       this, ToString(aCharMsg).get()));
     return true;
   }
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+    ("%p   NativeKey::GetFollowingCharMessage(), FAILED, removed messages "
+     "are all WM_NULL, nextKeyMsg=%s",
+     this, ToString(nextKeyMsg).get()));
 #ifdef MOZ_CRASHREPORTER
   nsPrintfCString info("\nWe lost following char message! "
                        "\nHandling message: %s, InSendMessageEx()=%s, \n"
                        "Found message: %s, removed a lot of WM_NULL",
                        ToString(mMsg).get(),
                        GetResultOfInSendMessageEx().get(),
                        ToString(nextKeyMsg).get());
   CrashReporter::AppendAppNotesToCrashReport(info);
@@ -2626,35 +3036,61 @@ bool
 NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages() const
 {
   MOZ_ASSERT(IsKeyDownMessage());
   MOZ_ASSERT(!IsKeyMessageOnPlugin());
 
   for (size_t i = 0;
        i < mFollowingCharMsgs.Length() && mWidget->ShouldDispatchPluginEvent();
        ++i) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+       "dispatching %uth plugin event for %s...",
+       this, i + 1, ToString(mFollowingCharMsgs[i]).get()));
     MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
       "NativeKey tries to dispatch a plugin event on destroyed widget");
     mWidget->DispatchPluginEvent(mFollowingCharMsgs[i]);
     if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+         "%uth plugin event caused %s",
+         this, i + 1, mWidget->Destroyed() ? "destroying the widget" :
+                                             "focus change"));
       return true;
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+       "dispatched %uth plugin event",
+       this, i + 1));
   }
 
   // Dispatch odd char messages which are caused by ATOK or WXG (both of them
   // are Japanese IME) and removed by RemoveFollowingOddCharMessages().
   for (size_t i = 0;
        i < mRemovedOddCharMsgs.Length() && mWidget->ShouldDispatchPluginEvent();
        ++i) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+       "dispatching %uth plugin event for odd char message, %s...",
+       this, i + 1, ToString(mFollowingCharMsgs[i]).get()));
     MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
       "NativeKey tries to dispatch a plugin event on destroyed widget");
     mWidget->DispatchPluginEvent(mRemovedOddCharMsgs[i]);
     if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+         "%uth plugin event for odd char message caused %s",
+         this, i + 1, mWidget->Destroyed() ? "destroying the widget" :
+                                             "focus change"));
       return true;
     }
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+       "dispatched %uth plugin event for odd char message",
+       this, i + 1));
   }
 
   return false;
 }
 
 void
 NativeKey::ComputeInputtingStringWithKeyboardLayout()
 {
@@ -2740,41 +3176,66 @@ NativeKey::ComputeInputtingStringWithKey
 bool
 NativeKey::DispatchKeyPressEventsWithoutCharMessage() const
 {
   MOZ_ASSERT(IsKeyDownMessage());
   MOZ_ASSERT(!mIsDeadKey || !mCommittedCharsAndModifiers.IsEmpty());
 
   nsresult rv = mDispatcher->BeginNativeInputTransaction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+      ("%p   NativeKey::DispatchKeyPressEventsWithoutCharMessage(), FAILED due "
+       "to BeginNativeInputTransaction() failure", this));
     return true;
   }
 
   WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
   if (mInputtingStringAndModifiers.IsEmpty() &&
       mShiftedString.IsEmpty() && mUnshiftedString.IsEmpty()) {
     keypressEvent.mKeyCode = mDOMKeyCode;
   }
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+    ("%p   NativeKey::DispatchKeyPressEventsWithoutCharMessage(), initializing "
+     "keypress event...", this));
   nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState);
-  mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
-                                           const_cast<NativeKey*>(this));
-  return status == nsEventStatus_eConsumeNoDefault;
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::DispatchKeyPressEventsWithoutCharMessage(), dispatching "
+     "keypress event(s)...", this));
+  bool dispatched =
+    mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
+                                             const_cast<NativeKey*>(this));
+  if (mWidget->Destroyed()) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::DispatchKeyPressEventsWithoutCharMessage(), "
+       "keypress event(s) caused destroying the widget", this));
+    return true;
+  }
+  bool consumed = status == nsEventStatus_eConsumeNoDefault;
+  MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+    ("%p   NativeKey::DispatchKeyPressEventsWithoutCharMessage(), dispatched "
+     "keypress event(s), dispatched=%s, consumed=%s",
+     this, GetBoolName(dispatched), GetBoolName(consumed)));
+  return consumed;
 }
 
 void
 NativeKey::WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyboardEvent,
                                      uint32_t aIndex)
 {
   uint32_t longestLength =
     std::max(mInputtingStringAndModifiers.mLength,
              std::max(mShiftedString.mLength, mUnshiftedString.mLength));
   uint32_t skipUniChars = longestLength - mInputtingStringAndModifiers.mLength;
   uint32_t skipShiftedChars = longestLength - mShiftedString.mLength;
   uint32_t skipUnshiftedChars = longestLength - mUnshiftedString.mLength;
   if (aIndex >= longestLength) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::WillDispatchKeyboardEvent(), does nothing for %uth "
+       "%s event",
+       this, aIndex + 1, ToChar(aKeyboardEvent.mMessage)));
     return;
   }
 
   // Check if aKeyboardEvent is the last event for a key press.
   // So, if it's not an eKeyPress event, it's always the last event.
   // Otherwise, check if the index is the last character of
   // mCommittedCharsAndModifiers.
   bool isLastIndex =
@@ -2802,25 +3263,33 @@ NativeKey::WillDispatchKeyboardEvent(Wid
       // and base character does not produce a valid composite character
       // then both produced dead-key character and following base
       // character may have different modifier flags, too.
       modKeyState.Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
                         MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
       modKeyState.Set(
         mInputtingStringAndModifiers.mModifiers[aIndex - skipUniChars]);
       modKeyState.InitInputEvent(aKeyboardEvent);
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::WillDispatchKeyboardEvent(), "
+         "setting %uth modifier state to %s",
+         this, aIndex + 1, ToString(modKeyState).get()));
     }
     uint16_t uniChar =
       mInputtingStringAndModifiers.mChars[aIndex - skipUniChars];
 
     // The mCharCode was set from mKeyValue. However, for example, when Ctrl key
     // is pressed, its value should indicate an ASCII character for backward
     // compatibility rather than inputting character without the modifiers.
     // Therefore, we need to modify mCharCode value here.
     aKeyboardEvent.SetCharCode(uniChar);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::WillDispatchKeyboardEvent(), "
+       "setting %uth charCode to %s",
+       this, aIndex + 1, GetCharacterCodeName(uniChar).get()));
   }
 
   // We need to append alterntaive charCode values:
   //   - if the event is eKeyPress, we need to append for the index because
   //     eKeyPress event is dispatched for every character inputted by a
   //     key press.
   //   - if the event is not eKeyPress, we need to append for all characters
   //     inputted by the key press because the other keyboard events (e.g.,
@@ -2918,27 +3387,45 @@ NativeKey::DispatchKeyPressEventForFollo
       }
     }
 #endif // #ifdef DEBUG
     return HandleCharMessage(aCharMsg);
   }
 
   if (IsDeadCharMessage(aCharMsg)) {
     if (!mWidget->PluginHasFocus()) {
+      MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+        ("%p   NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+         "plugin doesn't have focus", this));
       return false;
     }
-    return (mWidget->DispatchPluginEvent(aCharMsg) || mWidget->Destroyed());
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+       "dispatching plugin event...", this));
+    bool ok = mWidget->DispatchPluginEvent(aCharMsg) || mWidget->Destroyed();
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+       "dispatched plugin event, result=%s, mWidget->Destroyed()=%s",
+       this, GetBoolName(ok), GetBoolName(mWidget->Destroyed())));
   }
 
   bool defaultPrevented = HandleCharMessage(aCharMsg);
   // If a syschar keypress wasn't processed, Windows may want to
   // handle it to activate a native menu.
   if (!defaultPrevented && IsSysCharMessage(aCharMsg)) {
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+       "calling DefWindowProcW(aCharMsg=%s)...",
+       this, ToString(aCharMsg).get()));
     ::DefWindowProcW(aCharMsg.hwnd, aCharMsg.message,
                      aCharMsg.wParam, aCharMsg.lParam);
+    MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+      ("%p   NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+       "called DefWindowProcW(aCharMsg=%s)",
+       this, ToString(aCharMsg).get()));
   }
   return defaultPrevented;
 }
 
 /*****************************************************************************
  * mozilla::widget::KeyboardLayout
  *****************************************************************************/
 
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -335,16 +335,17 @@ private:
   static uint8_t sDispatchedKeyOfAppCommand;
 
   NativeKey()
   {
     MOZ_CRASH("The default constructor of NativeKey isn't available");
   }
 
   void InitWithAppCommand();
+  void InitWithKeyChar();
 
   /**
    * Returns true if the key event is caused by auto repeat.
    */
   bool IsRepeat() const
   {
     switch (mMsg.message) {
       case WM_KEYDOWN:
--- a/widget/windows/WinModifierKeyState.h
+++ b/widget/windows/WinModifierKeyState.h
@@ -5,16 +5,18 @@
 
 #ifndef mozilla_widget_WinModifierKeyState_h_
 #define mozilla_widget_WinModifierKeyState_h_
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/EventForwards.h"
 #include <windows.h>
 
+class nsCString;
+
 namespace mozilla {
 namespace widget {
 
 class MOZ_STACK_CLASS ModifierKeyState final
 {
 public:
   ModifierKeyState();
   ModifierKeyState(bool aIsShiftDown, bool aIsControlDown, bool aIsAltDown);
@@ -47,12 +49,14 @@ public:
 private:
   Modifiers mModifiers;
 
   MOZ_ALWAYS_INLINE void EnsureAltGr();
 
   void InitMouseEvent(WidgetInputEvent& aMouseEvent) const;
 };
 
+const nsCString ToString(const ModifierKeyState& aModifierKeyState);
+
 } // namespace widget
 } // namespace mozilla
 
 #endif // #ifndef mozilla_widget_WinModifierKeyState_h_