Bug 1301306 - Stop focus events from anon. content when moving inside input=time element. r=smaug
authorJessica Jong <jjong@mozilla.com>
Fri, 04 Nov 2016 00:47:00 -0400
changeset 351323 8d27bc400b98b035c5ee7614b732fb1001a21308
parent 351322 3eee70f71e8573c621bd5e05e838f552531e46c0
child 351324 b03f99accc585b2c850307398cc2500028e6bd8e
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1301306
milestone52.0a1
Bug 1301306 - Stop focus events from anon. content when moving inside input=time element. r=smaug
dom/html/HTMLInputElement.cpp
dom/html/test/forms/mochitest.ini
dom/html/test/forms/test_input_time_focus_blur_events.html
editor/libeditor/EditorEventListener.cpp
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4082,16 +4082,36 @@ HTMLInputElement::PreHandleEvent(EventCh
         // value changes than our anon text control does, so in some cases
         // (if our text control's value doesn't parse as a number) we don't
         // want to fire a 'change' event at all.
         aVisitor.mCanHandle = false;
       }
     }
   }
 
+  // Stop the event if the related target's first non-native ancestor is the
+  // same as the original target's first non-native ancestor (we are moving
+  // inside of the same element).
+  if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType) &&
+      (aVisitor.mEvent->mMessage == eFocus ||
+       aVisitor.mEvent->mMessage == eFocusIn ||
+       aVisitor.mEvent->mMessage == eFocusOut ||
+       aVisitor.mEvent->mMessage == eBlur)) {
+    nsCOMPtr<nsIContent> originalTarget =
+      do_QueryInterface(aVisitor.mEvent->AsFocusEvent()->mRelatedTarget);
+    nsCOMPtr<nsIContent> relatedTarget =
+      do_QueryInterface(aVisitor.mEvent->AsFocusEvent()->mRelatedTarget);
+
+    if (originalTarget && relatedTarget &&
+        originalTarget->FindFirstNonChromeOnlyAccessContent() ==
+        relatedTarget->FindFirstNonChromeOnlyAccessContent()) {
+      aVisitor.mCanHandle = false;
+    }
+  }
+
   return rv;
 }
 
 void
 HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent)
 {
   mIsDraggingRange = true;
   mRangeThumbDragStartValue = GetValueAsDecimal();
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -65,16 +65,18 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_input_range_mouse_and_touch_events.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure; bug 926546
 [test_input_range_rounding.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_input_sanitization.html]
 [test_input_textarea_set_value_no_scroll.html]
 [test_input_time_key_events.html]
 skip-if = os == "android" || appname == "b2g"
+[test_input_time_focus_blur_events.html]
+skip-if = os == "android" || appname == "b2g"
 [test_input_types_pref.html]
 [test_input_typing_sanitization.html]
 skip-if = buildapp == 'mulet'
 [test_input_untrusted_key_events.html]
 [test_input_url.html]
 [test_interactive_content_in_label.html]
 [test_label_control_attribute.html]
 [test_label_input_controls.html]
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_input_time_focus_blur_events.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
+-->
+<head>
+<title>Test for Bug 1301306</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="time" id="input_time" onfocus="++focusEvent" onblur="++blurEvent"
+       onfocusin="++focusInEvent" onfocusout="++focusOutEvent">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ * Test for Bug 1301306.
+ * This test checks that when moving inside the time input element, e.g. jumping
+ * through the inner text boxes, does not fire extra focus/blur events.
+ **/
+
+var focusEvent = 0;
+var focusInEvent = 0;
+var focusOutEvent = 0;
+var blurEvent = 0;
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  test();
+  SimpleTest.finish();
+});
+
+function test() {
+  var time = document.getElementById("input_time");
+  time.focus();
+  is(focusEvent, 1, "time input element should have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+  // Move around inside the input element's input box.
+  synthesizeKey("VK_TAB", {});
+  is(focusEvent, 1, "time input element should not have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+  synthesizeKey("VK_RIGHT", {});
+  is(focusEvent, 1, "time input element should not have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+  synthesizeKey("VK_LEFT", {});
+  is(focusEvent, 1, "time input element should not have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+  synthesizeKey("VK_RIGHT", {});
+  is(focusEvent, 1, "time input element should not have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+  time.blur();
+  is(focusEvent, 1, "time input element should not have dispatched focus event.");
+  is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+  is(focusOutEvent, 1, "time input element should not have dispatched focusout event.");
+  is(blurEvent, 1, "time input element should have dispatched blur event.");
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -1083,17 +1083,31 @@ EditorEventListener::Focus(nsIDOMEvent* 
     // make sure that the element is really focused in case an earlier
     // listener in the chain changed the focus.
     if (editableRoot) {
       nsIFocusManager* fm = nsFocusManager::GetFocusManager();
       NS_ENSURE_TRUE(fm, NS_OK);
 
       nsCOMPtr<nsIDOMElement> element;
       fm->GetFocusedElement(getter_AddRefs(element));
-      if (!SameCOMIdentity(element, target)) {
+      if (!element) {
+        return NS_OK;
+      }
+
+      nsCOMPtr<nsIDOMEventTarget> originalTarget;
+      aEvent->GetOriginalTarget(getter_AddRefs(originalTarget));
+
+      nsCOMPtr<nsIContent> originalTargetAsContent =
+        do_QueryInterface(originalTarget);
+      nsCOMPtr<nsIContent> focusedElementAsContent =
+        do_QueryInterface(element);
+
+      if (!SameCOMIdentity(
+            focusedElementAsContent->FindFirstNonChromeOnlyAccessContent(),
+            originalTargetAsContent->FindFirstNonChromeOnlyAccessContent())) {
         return NS_OK;
       }
     }
   }
 
   mEditorBase->OnFocus(target);
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();