Bug 1452536 - Don't gesture activate documents for blacklisted keys. r?masayuki draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 11 Apr 2018 16:23:54 +1200
changeset 780903 831c26533c21671e138120451da5917c642e8644
parent 779997 0528a414c2a86dad0623779abde5301d37337934
child 780904 a6c8b0c33482091677cddc76879df4f1c7ba91f0
push id106158
push userbmo:cpearce@mozilla.com
push dateThu, 12 Apr 2018 07:09:26 +0000
reviewersmasayuki
bugs1452536
milestone61.0a1
Bug 1452536 - Don't gesture activate documents for blacklisted keys. r?masayuki We plan to only allow autoplay audible video in documents which have had user interaction. So when a document has a mouse or key event dispatched to it, we want to mark the document as gesture-activated. However we don't want interactions which are probably not interaction with the web page to gesture activate the document. So keypresses like scrolling with keys, or keyboard shortcuts, should not gesture activate. So add a blacklist of keys to EventStateManager.cpp of keys we think should not gesture activate a document, and don't activate on key events for those keys. MozReview-Commit-ID: AHvW3nynkrn
dom/events/EventStateManager.cpp
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -891,16 +891,96 @@ EventStateManager::PreHandleEvent(nsPres
     NotifyTargetUserActivation(aEvent, aTargetContent);
     break;
   default:
     break;
   }
   return NS_OK;
 }
 
+static bool
+IsInGestureActivationKeyBlackList(WidgetKeyboardEvent* aKeyEvent)
+{
+  // If a modifier key is pressed, this key event may be a keyboard shortcut
+  // for the browser or OS, so don't activate.
+  const uint32_t mask = (MODIFIER_ALT |
+                         MODIFIER_CONTROL |
+                         MODIFIER_SHIFT |
+                         MODIFIER_META |
+                         MODIFIER_OS |
+                         MODIFIER_FN);
+  if (aKeyEvent->mModifiers & mask) {
+    return true;
+  }
+
+  // If this key is in the list below, it's considered as not
+  // interaction with web page, and so blacklisted.
+  switch (aKeyEvent->mKeyNameIndex) {
+    // Tab changes focus, so not considered interaction with content.
+    case KEY_NAME_INDEX_Tab: MOZ_FALLTHROUGH;
+
+    // Lock keys, interaction with keyboard, not content.
+    case KEY_NAME_INDEX_CapsLock: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_NumLock: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_ScrollLock: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_FnLock: MOZ_FALLTHROUGH;
+
+    // OS/"Windows" keys, probably interaction with window manager.
+    case KEY_NAME_INDEX_Meta: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_OS: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Hyper: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Super: MOZ_FALLTHROUGH;
+
+    // Context menu is probably interaction with browser.
+    case KEY_NAME_INDEX_ContextMenu: MOZ_FALLTHROUGH;
+
+    // Navigation/scrolling keys; user shouldn't activate a document
+    // if they choose to scroll content via keyboard shortcuts.
+    case KEY_NAME_INDEX_ArrowUp: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_ArrowDown: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_ArrowLeft: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_ArrowRight: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_PageUp: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_PageDown: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Home: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_End: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Backspace: MOZ_FALLTHROUGH;
+
+    // Modifier keys; interaction with keyboard, or in preparation
+    // for a shortcut.
+    case KEY_NAME_INDEX_Fn: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Alt: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_AltGraph: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Control: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_Shift: MOZ_FALLTHROUGH;
+
+    // Escape is used to close dialogs, exit fullscreen and "get out",
+    // of annoying situations, so shouldn't activate.
+    case KEY_NAME_INDEX_Escape: MOZ_FALLTHROUGH;
+
+    // Many of the F* keys map to browser shortcuts,
+    // so blacklist all of them.
+    case KEY_NAME_INDEX_F1: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F2: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F3: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F4: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F5: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F6: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F7: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F8: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F9: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F10: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F11: MOZ_FALLTHROUGH;
+    case KEY_NAME_INDEX_F12:
+      return true;
+    default:
+      return false;
+  }
+}
+
 void
 EventStateManager::NotifyTargetUserActivation(WidgetEvent* aEvent,
                                               nsIContent* aTargetContent)
 {
   if (!aEvent->IsTrusted()) {
     return;
   }
 
@@ -914,16 +994,23 @@ EventStateManager::NotifyTargetUserActiv
     return;
   }
 
   nsIDocument* doc = node->OwnerDoc();
   if (!doc || doc->HasBeenUserActivated()) {
     return;
   }
 
+  // Don't gesutre activate for key events for keys which are likely
+  // to be interaction with the browser, OS, or likely to be scrolling.
+  WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
+  if (keyEvent && IsInGestureActivationKeyBlackList(keyEvent)) {
+    return;
+  }
+
   MOZ_ASSERT(aEvent->mMessage == eKeyUp   ||
              aEvent->mMessage == eMouseUp ||
              aEvent->mMessage == eTouchEnd);
   doc->NotifyUserActivation();
 }
 
 already_AddRefed<EventStateManager>
 EventStateManager::ESMFromContentOrThis(nsIContent* aContent)