Backed out 3 changesets (bug 1327097) for eslint failures toolkit/content/tests/widgets/test_videocontrols.html:228 r=backout on a CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Thu, 16 Nov 2017 14:23:20 +0200
changeset 446459 2fab4b8b8f7c8e56d200d04801c9e015086a541d
parent 446458 f8dfa355526c007b50aeec918ed4c5f56039362d
child 446460 3e99c259e2dc30479063bc52eb6c9c9e351a53e7
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1327097
milestone59.0a1
backs out09c0a4c56c78e66f3584e765e2a5cf816fb423cf
c0c5ee67b3ef8b57e08b4efbfa4a904b38089eed
82a6e4dc5da71071b1d20e30970edb02d1e06a8f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1327097) for eslint failures toolkit/content/tests/widgets/test_videocontrols.html:228 r=backout on a CLOSED TREE Backed out changeset 09c0a4c56c78 (bug 1327097) Backed out changeset c0c5ee67b3ef (bug 1327097) Backed out changeset 82a6e4dc5da7 (bug 1327097)
accessible/tests/mochitest/actions.js
accessible/tests/mochitest/actions/test_media.html
accessible/tests/mochitest/events.js
dom/base/nsGkAtomList.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/html/test/forms/chrome.ini
dom/html/test/forms/mochitest.ini
dom/html/test/forms/test_input_range_mozinputrangeignorepreventdefault.html
dom/html/test/forms/test_input_range_mozinputrangeignorepreventdefault_chrome.html
gfx/layers/apz/test/mochitest/helper_bug1162771.html
toolkit/content/tests/widgets/test_videocontrols.html
toolkit/content/widgets/videocontrols.xml
--- a/accessible/tests/mochitest/actions.js
+++ b/accessible/tests/mochitest/actions.js
@@ -59,26 +59,26 @@ function testActions(aArray) {
     var events = actionObj.events;
     var accOrElmOrIDOfTarget = actionObj.targetID ?
       actionObj.targetID : accOrElmOrID;
 
     var eventSeq = [];
     if (events) {
       var elm = getNode(accOrElmOrIDOfTarget);
       if (events & MOUSEDOWN_EVENT)
-        eventSeq.push(new checkerOfActionInvoker("mousedown", elm, actionObj));
+        eventSeq.push(new checkerOfActionInvoker("mousedown", elm));
 
       if (events & MOUSEUP_EVENT)
-        eventSeq.push(new checkerOfActionInvoker("mouseup", elm, actionObj));
+        eventSeq.push(new checkerOfActionInvoker("mouseup", elm));
 
       if (events & CLICK_EVENT)
         eventSeq.push(new checkerOfActionInvoker("click", elm, actionObj));
 
       if (events & COMMAND_EVENT)
-        eventSeq.push(new checkerOfActionInvoker("command", elm, actionObj));
+        eventSeq.push(new checkerOfActionInvoker("command", elm));
 
       if (events & FOCUS_EVENT)
         eventSeq.push(new focusChecker(elm));
     }
 
     if (actionObj.eventSeq)
       eventSeq = eventSeq.concat(actionObj.eventSeq);
 
@@ -143,28 +143,24 @@ function actionInvoker(aAccOrElmOrId, aA
   };
 }
 
 function checkerOfActionInvoker(aType, aTarget, aActionObj) {
   this.type = aType;
 
   this.target = aTarget;
 
-  if (aActionObj && "eventTarget" in aActionObj) {
-    this.eventTarget = aActionObj.eventTarget;
-  }
-
   this.phase = false;
 
   this.getID = function getID() {
     return aType + " event handling";
   };
 
   this.check = function check(aEvent) {
-    if (aType == "click" && aActionObj && "checkOnClickEvent" in aActionObj)
+    if (aActionObj && "checkOnClickEvent" in aActionObj)
       aActionObj.checkOnClickEvent(aEvent);
   };
 }
 
 var gActionDescrMap =
 {
   jump: "Jump",
   press: "Press",
--- a/accessible/tests/mochitest/actions/test_media.html
+++ b/accessible/tests/mochitest/actions/test_media.html
@@ -59,34 +59,32 @@ https://bugzilla.mozilla.org/show_bug.cg
       var playBtn = audioElm.firstChild;
       // var scrubber = playBtn.nextSibling.nextSibling.nextSibling;
       var muteBtn = audioElm.lastChild.previousSibling;
 
       var actions = [
         {
           ID: muteBtn,
           actionName: "press",
-          eventTarget: "element",
           eventSeq: [
      //       new focusChecker(muteBtn),
             new nameChecker(muteBtn, "Unmute"),
           ]
         },
      //   {
      //     ID: scrubber,
      //     actionName: "activate",
      //     events: null,
      //     eventSeq: [
      //       new focusChecker(scrubber)
      //     ]
      //   },
         {
           ID: playBtn,
           actionName: "press",
-          eventTarget: "element",
           eventSeq: [
      //       new focusChecker(playBtn),
             new nameChecker(playBtn, "Pause"),
           ]
         }
       ];
 
       testActions(actions); // Will call SimpleTest.finish();
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -741,23 +741,23 @@ function eventQueue(aEventType) {
 
           gLogger.logToConsole(msg);
           gLogger.logToDOM(msg, true);
         }
 
         var eventType = eventSeq[idx].type;
         if (typeof eventType == "string") {
           // DOM event
-          var target = eventQueue.getEventTarget(eventSeq[idx]);
+          var target = eventSeq[idx].target;
           if (!target) {
             ok(false, "no target for DOM event!");
             return false;
           }
           var phase = eventQueue.getEventPhase(eventSeq[idx]);
-          target.addEventListener(eventType, this, phase);
+          target.ownerDocument.addEventListener(eventType, this, phase);
 
         } else {
           // A11y event
           addA11yEventListener(eventType, this);
         }
       }
     }
 
@@ -769,19 +769,19 @@ function eventQueue(aEventType) {
       return;
 
     for (var scnIdx = 0; scnIdx < this.mScenarios.length; scnIdx++) {
       var eventSeq = this.mScenarios[scnIdx];
       for (var idx = 0; idx < eventSeq.length; idx++) {
         var eventType = eventSeq[idx].type;
         if (typeof eventType == "string") {
           // DOM event
-          var target = eventQueue.getEventTarget(eventSeq[idx]);
+          var target = eventSeq[idx].target;
           var phase = eventQueue.getEventPhase(eventSeq[idx]);
-          target.removeEventListener(eventType, this, phase);
+          target.ownerDocument.removeEventListener(eventType, this, phase);
 
         } else {
           // A11y event
           removeA11yEventListener(eventType, this);
         }
       }
     }
     this.mScenarios = null;
@@ -848,29 +848,16 @@ eventQueue.getEventTargetDescr =
   var target = ("target" in aEventOrChecker) ? aEventOrChecker.target : null;
   return prettyName(target);
 };
 
 eventQueue.getEventPhase = function eventQueue_getEventPhase(aChecker) {
   return ("phase" in aChecker) ? aChecker.phase : true;
 };
 
-eventQueue.getEventTarget = function eventQueue_getEventTarget(aChecker) {
-  if ("eventTarget" in aChecker) {
-    switch (aChecker.eventTarget) {
-      case "element":
-        return aChecker.target;
-      case "document":
-      default:
-        return aChecker.target.ownerDocument;
-    }
-  }
-  return aChecker.target.ownerDocument;
-};
-
 eventQueue.compareEventTypes =
   function eventQueue_compareEventTypes(aChecker, aEvent) {
   var eventType = (aEvent instanceof nsIDOMEvent) ?
     aEvent.type : aEvent.eventType;
   return aChecker.type == eventType;
 };
 
 eventQueue.compareEvents = function eventQueue_compareEvents(aChecker, aEvent) {
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2061,16 +2061,19 @@ GK_ATOM(onmozorientationchange, "onmozor
 GK_ATOM(onuserproximity, "onuserproximity")
 
 // light sensor support
 GK_ATOM(ondevicelight, "ondevicelight")
 
 // MediaDevices device change event
 GK_ATOM(ondevicechange, "ondevicechange")
 
+// HTML element attributes that only exposed to XBL and chrome content
+GK_ATOM(mozinputrangeignorepreventdefault, "mozinputrangeignorepreventdefault")
+
 // WebExtensions
 GK_ATOM(moz_extension, "moz-extension")
 GK_ATOM(all_urlsPermission, "<all_urls>")
 GK_ATOM(clipboardRead, "clipboardRead")
 GK_ATOM(clipboardWrite, "clipboardWrite")
 GK_ATOM(debugger, "debugger")
 GK_ATOM(tabs, "tabs")
 GK_ATOM(webRequestBlocking, "webRequestBlocking")
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4695,17 +4695,18 @@ HTMLInputElement::PostHandleEvent(EventC
   return MaybeInitPickers(aVisitor);
 }
 
 void
 HTMLInputElement::PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor)
 {
   MOZ_ASSERT(mType == NS_FORM_INPUT_RANGE);
 
-  if (nsEventStatus_eConsumeNoDefault == aVisitor.mEventStatus ||
+  if ((nsEventStatus_eConsumeNoDefault == aVisitor.mEventStatus &&
+       !MozInputRangeIgnorePreventDefault()) ||
       !(aVisitor.mEvent->mClass == eMouseEventClass ||
         aVisitor.mEvent->mClass == eTouchEventClass ||
         aVisitor.mEvent->mClass == eKeyboardEventClass)) {
     return;
   }
 
   nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
   if (!rangeFrame && mIsDraggingRange) {
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -573,22 +573,16 @@ public:
   {
     SetUnsignedIntAttr(nsGkAtoms::height, aValue, 0, aRv);
   }
 
   bool Indeterminate() const
   {
     return mIndeterminate;
   }
-
-  bool IsDraggingRange() const
-  {
-    return mIsDraggingRange;
-  }
-
   // XPCOM SetIndeterminate() is OK
 
   void GetInputMode(nsAString& aValue);
   void SetInputMode(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::inputmode, aValue, aRv);
   }
 
@@ -863,16 +857,22 @@ public:
   int32_t InputTextLength(CallerType aCallerType);
 
   void MozGetFileNameArray(nsTArray<nsString>& aFileNames, ErrorResult& aRv);
 
   void MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv);
   void MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles);
   void MozSetDirectory(const nsAString& aDirectoryPath, ErrorResult& aRv);
 
+  bool MozInputRangeIgnorePreventDefault() const
+  {
+    return (IsInChromeDocument() || IsInNativeAnonymousSubtree()) &&
+      GetBoolAttr(nsGkAtoms::mozinputrangeignorepreventdefault);
+  }
+
   /*
    * The following functions are called from datetime picker to let input box
    * know the current state of the picker or to update the input box on changes.
    */
   void GetDateTimeInputBoxValue(DateTimeValue& aValue);
   void UpdateDateTimeInputBox(const DateTimeValue& aValue);
   void SetDateTimePickerState(bool aOpen);
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -9,17 +9,16 @@
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/MediaEncryptedEvent.h"
 #include "mozilla/EMEUtils.h"
-#include "mozilla/EventDispatcher.h"
 #include "mozilla/Sprintf.h"
 
 #include "base/basictypes.h"
 #include "nsIDOMHTMLMediaElement.h"
 #include "TimeRanges.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsDocShellLoadTypes.h"
@@ -131,17 +130,16 @@ static mozilla::LazyLogModule gMediaElem
 #include "mozilla/Preferences.h"
 #include "mozilla/FloatingPoint.h"
 
 #include "nsIPermissionManager.h"
 #include "nsDocShell.h"
 
 #include "mozilla/EventStateManager.h"
 
-#include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/VideoPlaybackQuality.h"
 #include "HTMLMediaElement.h"
 
 #include "GMPCrashHelper.h"
 
 using namespace mozilla::layers;
 using mozilla::net::nsMediaFragmentURIParser;
@@ -4382,70 +4380,16 @@ HTMLMediaElement::OutputMediaStream::Out
 
 HTMLMediaElement::OutputMediaStream::~OutputMediaStream()
 {
   for (auto pair : mTrackPorts) {
     pair.second()->Destroy();
   }
 }
 
-nsresult
-HTMLMediaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
-{
-  if (!this->Controls() || !aVisitor.mEvent->mFlags.mIsTrusted) {
-    return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
-  }
-
-  HTMLInputElement* el = nullptr;
-  nsCOMPtr<nsINode> node;
-
-  // We will need to trap pointer, touch, and mouse events within the media
-  // element, allowing media control exclusive consumption on these events,
-  // and preventing the content from handling them.
-  switch (aVisitor.mEvent->mMessage) {
-    case ePointerDown:
-    case ePointerUp:
-    case eTouchEnd:
-    // Always prevent touchmove captured in video element from being handled by content,
-    // since we always do that for touchstart.
-    case eTouchMove:
-    case eTouchStart:
-    case eMouseClick:
-    case eMouseDoubleClick:
-    case eMouseDown:
-    case eMouseUp:
-      aVisitor.mCanHandle = false;
-      return NS_OK;
-
-    // The *move events however are only comsumed when the range input is being
-    // dragged.
-    case ePointerMove:
-    case eMouseMove:
-      node = do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
-      if (node->IsInNativeAnonymousSubtree()) {
-        if (node->IsHTMLElement(nsGkAtoms::input)) {
-          // The node is a <input type="range">
-          el = static_cast<HTMLInputElement*>(node.get());
-        } else if (node->GetParentNode() &&
-                   node->GetParentNode()->IsHTMLElement(nsGkAtoms::input)) {
-          // The node is a child of <input type="range">
-          el = static_cast<HTMLInputElement*>(node->GetParentNode());
-        }
-      }
-      if (el && el->IsDraggingRange()) {
-        aVisitor.mCanHandle = false;
-        return NS_OK;
-      }
-      return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
-
-    default:
-      return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
-  }
-}
-
 bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
                                       nsAtom* aAttribute,
                                       const nsAString& aValue,
                                       nsAttrValue& aResult)
 {
   // Mappings from 'preload' attribute strings to an enumeration.
   static const nsAttrValue::EnumTable kPreloadTable[] = {
     { "",         HTMLMediaElement::PRELOAD_ATTR_EMPTY },
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -140,20 +140,16 @@ public:
   // nsIDOMHTMLMediaElement
   NS_DECL_NSIDOMHTMLMEDIAELEMENT
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLMediaElement,
                                            nsGenericHTMLElement)
 
-  // nsIDOMEventTarget
-  virtual nsresult
-  GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
-
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
--- a/dom/html/test/forms/chrome.ini
+++ b/dom/html/test/forms/chrome.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
 support-files =
   submit_invalid_file.sjs
 [test_autocompleteinfo.html]
 [test_submit_invalid_file.html]
+[test_input_range_mozinputrangeignorepreventdefault_chrome.html]
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -56,16 +56,17 @@ skip-if = os == "android"
 skip-if = os == "android"
 [test_input_number_validation.html]
 # We don't build ICU for Firefox for Android:
 skip-if = os == "android"
 [test_input_number_focus.html]
 [test_input_range_attr_order.html]
 [test_input_range_key_events.html]
 [test_input_range_mouse_and_touch_events.html]
+[test_input_range_mozinputrangeignorepreventdefault.html]
 [test_input_range_rounding.html]
 [test_input_sanitization.html]
 skip-if = os == 'android' && debug # Extremely slow on debug android
 [test_input_textarea_set_value_no_scroll.html]
 [test_input_time_key_events.html]
 [test_input_time_sec_millisec_field.html]
 [test_input_types_pref.html]
 [test_input_typing_sanitization.html]
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_mozinputrangeignorepreventdefault.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1338961
+-->
+<head>
+  <title>Test mouse and touch events for range</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <style>
+    /* synthesizeMouse and synthesizeFunc uses getBoundingClientRect. We set
+     * the following properties to avoid fractional values in the rect returned
+     * by getBoundingClientRect in order to avoid rounding that would occur
+     * when event coordinates are internally converted to be relative to the
+     * top-left of the element. (Such rounding would make it difficult to
+     * predict exactly what value the input should take on for events at
+     * certain coordinates.)
+     */
+    input { margin: 0 ! important; width: 200px ! important; }
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338961">Mozilla Bug 1338961</a>
+<p id="display"></p>
+<div id="content">
+  <input id="range" type="range" mozinputrangeignorepreventdefault="true">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 1338961
+ * This test ensures mozinputrangeignorepreventdefault has no effect in
+ * content html.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  test(synthesizeMouse, "click", "mousedown", "mousemove", "mouseup");
+  test(synthesizeTouch, "tap", "touchstart", "touchmove", "touchend");
+  SimpleTest.finish();
+});
+
+function flush() {
+  // Flush style, specifically to flush the 'direction' property so that the
+  // browser uses the new value for thumb positioning.
+  var flush = document.body.clientWidth;
+}
+
+const QUARTER_OF_RANGE = "25";
+
+function test(synthesizeFunc, clickOrTap, startName, moveName, endName) {
+  var elem = document.getElementById("range");
+  elem.focus();
+  flush();
+
+  var width = parseFloat(window.getComputedStyle(elem).width);
+  var height = parseFloat(window.getComputedStyle(elem).height);
+  var borderLeft = parseFloat(window.getComputedStyle(elem).borderLeftWidth);
+  var borderTop = parseFloat(window.getComputedStyle(elem).borderTopWidth);
+  var paddingLeft = parseFloat(window.getComputedStyle(elem).paddingLeft);
+  var paddingTop = parseFloat(window.getComputedStyle(elem).paddingTop);
+
+  // Extrema for mouse/touch events:
+  var midY = height / 2 + borderTop + paddingTop;
+  var minX = borderLeft + paddingLeft;
+  var midX = minX + width / 2;
+  var maxX = minX + width;
+
+  function preventDefault(e) {
+    e.preventDefault();
+  }
+
+  // Test that preventDefault() works:
+  elem.value = QUARTER_OF_RANGE;
+  elem.addEventListener(startName, preventDefault);
+  synthesizeFunc(elem, midX, midY, {});
+  is(elem.value, QUARTER_OF_RANGE, "Test that preventDefault() works");
+  elem.removeEventListener(startName, preventDefault);
+
+  // Test that preventDefault() on the parent node works:
+  elem.value = QUARTER_OF_RANGE;
+  elem.parentNode.addEventListener(startName, preventDefault);
+  synthesizeFunc(elem, midX, midY, {});
+  is(elem.value, QUARTER_OF_RANGE, "Test that preventDefault() on the parent node works");
+  elem.parentNode.removeEventListener(startName, preventDefault);
+}
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_mozinputrangeignorepreventdefault_chrome.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1338961
+-->
+<head>
+  <title>Test mouse and touch events for range</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <style>
+    /* synthesizeMouse and synthesizeFunc uses getBoundingClientRect. We set
+     * the following properties to avoid fractional values in the rect returned
+     * by getBoundingClientRect in order to avoid rounding that would occur
+     * when event coordinates are internally converted to be relative to the
+     * top-left of the element. (Such rounding would make it difficult to
+     * predict exactly what value the input should take on for events at
+     * certain coordinates.)
+     */
+    input { margin: 0 ! important; width: 200px ! important; }
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338961">Mozilla Bug 1338961</a>
+<p id="display"></p>
+<div id="content">
+  <input id="range" type="range" mozinputrangeignorepreventdefault="true">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 1338961
+ * This test ensures mozinputrangeignorepreventdefault has it's desired effect in
+ * chrome html.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  test(synthesizeMouse, "click", "mousedown", "mousemove", "mouseup");
+  test(synthesizeTouch, "tap", "touchstart", "touchmove", "touchend");
+  SimpleTest.finish();
+});
+
+function flush() {
+  // Flush style, specifically to flush the 'direction' property so that the
+  // browser uses the new value for thumb positioning.
+  var flush = document.body.clientWidth;
+}
+
+const MIDDLE_OF_RANGE = "50";
+const QUARTER_OF_RANGE = "25";
+
+function test(synthesizeFunc, clickOrTap, startName, moveName, endName) {
+  var elem = document.getElementById("range");
+  elem.focus();
+  flush();
+
+  var width = parseFloat(window.getComputedStyle(elem).width);
+  var height = parseFloat(window.getComputedStyle(elem).height);
+  var borderLeft = parseFloat(window.getComputedStyle(elem).borderLeftWidth);
+  var borderTop = parseFloat(window.getComputedStyle(elem).borderTopWidth);
+  var paddingLeft = parseFloat(window.getComputedStyle(elem).paddingLeft);
+  var paddingTop = parseFloat(window.getComputedStyle(elem).paddingTop);
+
+  // Extrema for mouse/touch events:
+  var midY = height / 2 + borderTop + paddingTop;
+  var minX = borderLeft + paddingLeft;
+  var midX = minX + width / 2;
+  var maxX = minX + width;
+
+  function preventDefault(e) {
+    e.preventDefault();
+  }
+
+  // Test that preventDefault() is ignored:
+  elem.value = QUARTER_OF_RANGE;
+  elem.addEventListener(startName, preventDefault);
+  synthesizeFunc(elem, midX, midY, {});
+  is(elem.value, MIDDLE_OF_RANGE, "Test that preventDefault() is ignored");
+  elem.removeEventListener(startName, preventDefault);
+
+  // Test that preventDefault() on the parent node works:
+  elem.value = QUARTER_OF_RANGE;
+  elem.parentNode.addEventListener(startName, preventDefault);
+  synthesizeFunc(elem, midX, midY, {});
+  is(elem.value, MIDDLE_OF_RANGE, "Test that preventDefault() on the parent node is ignored");
+  elem.parentNode.removeEventListener(startName, preventDefault);
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/gfx/layers/apz/test/mochitest/helper_bug1162771.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1162771.html
@@ -93,12 +93,12 @@ waitUntilApzStable()
       border:solid black 1px;
       background-color: #88a;
     }
   </style>
 </head>
 <body>
  <p>Tap on the colored boxes to hide them.</p>
  <video id="video"></video>
- <audio id="audio"></audio>
+ <audio id="audio" controls></audio>
  <div id="div"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/test_videocontrols.html
+++ b/toolkit/content/tests/widgets/test_videocontrols.html
@@ -114,26 +114,16 @@ add_task(async function setup() {
 
   video.addEventListener("play", verifyExpectedEvent);
   video.addEventListener("pause", verifyExpectedEvent);
   video.addEventListener("volumechange", verifyExpectedEvent);
   video.addEventListener("seeking", verifyExpectedEvent);
   video.addEventListener("seeked", verifyExpectedEvent);
   document.addEventListener("mozfullscreenchange", verifyExpectedEvent);
 
-  ["mousedown", "mouseup", "dblclick", "click"]
-    .forEach((eventType) => {
-      window.addEventListener(eventType, (evt) => {
-        // Prevent default action of leaked events and make the tests fail.
-        evt.preventDefault();
-        ok(false, "Event " + eventType + " in videocontrol should not leak to content;" +
-          "the event was dispatched from the " + evt.target.tagName.toLowerCase() + " element.");
-      });
-    });
-
   // Check initial state upon load
   is(video.paused, true, "checking video play state");
   is(video.muted, false, "checking video mute state");
 });
 
 add_task(async function click_playbutton() {
   synthesizeMouse(video, playButtonCenterX, playButtonCenterY, {});
   await waitForEvent("play");
@@ -217,34 +207,25 @@ add_task(async function reset_currentTim
 /*
  * Drag the slider's thumb to the halfway point with the mouse.
  */
 add_task(async function drag_slider() {
   const beginDragX = scrubberOffsetX;
   const endDragX = scrubberOffsetX + (scrubberWidth / 2);
   const expectedTime = videoDuration / 2;
 
-  function mousemoved(evt) {
-    ok(false, "Mousemove event should not be handled by content while dragging; " +
-      "the event was dispatched from the " + evt.target.tagName.toLowerCase() + " element.");
-  };
-
-  window.addEventListener("mousemove", mousemoved);
-
   synthesizeMouse(video, beginDragX, scrubberCenterY, {type: "mousedown", button: 0});
   synthesizeMouse(video, endDragX, scrubberCenterY, {type: "mousemove", button: 0});
   synthesizeMouse(video, endDragX, scrubberCenterY, {type: "mouseup",   button: 0});
   await waitForEvent("seeking", "seeked");
   ok(true, "video position is at " + video.currentTime);
   // The width of srubber is not equal in every platform as we use system default font
   // in duration and position box. We can not precisely drag to expected position, so
   // we just make sure the difference is within 10% of video duration.
   ok(Math.abs(video.currentTime - expectedTime) < videoDuration / 10, "checking expected playback position");
-
-  window.removeEventListener("mousemove", mousemoved);
 });
 
 /*
  * Click the slider at the 1/4 point with the mouse (jump backwards)
  */
 add_task(async function click_slider() {
   synthesizeMouse(video, scrubberOffsetX + (scrubberWidth / 4), scrubberCenterY, {});
   await waitForEvent("seeking", "seeked");
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -155,31 +155,31 @@
                   tabindex="-1"/>
           <div anonid="scrubberStack" class="scrubberStack progressContainer" role="none">
             <div class="progressBackgroundBar stackItem" role="none">
               <div class="progressStack" role="none">
                 <progress anonid="bufferBar" class="bufferBar" value="0" max="100" tabindex="-1"></progress>
                 <progress anonid="progressBar" class="progressBar" value="0" max="100" tabindex="-1"></progress>
               </div>
             </div>
-            <input type="range" anonid="scrubber" class="scrubber" tabindex="-1"/>
+            <input type="range" anonid="scrubber" class="scrubber" tabindex="-1" mozinputrangeignorepreventdefault="true" />
           </div>
           <span anonid="positionLabel" class="positionLabel" role="presentation"></span>
           <span anonid="durationLabel" class="durationLabel" role="presentation"></span>
           <span anonid="positionDurationBox" class="positionDurationBox" aria-hidden="true">
             &positionAndDuration.nameFormat;
           </span>
           <div anonid="controlBarSpacer" class="controlBarSpacer" hidden="true" role="none"></div>
           <button anonid="muteButton"
                   class="muteButton"
                   mutelabel="&muteButton.muteLabel;"
                   unmutelabel="&muteButton.unmuteLabel;"
                   tabindex="-1"/>
           <div anonid="volumeStack" class="volumeStack progressContainer" role="none">
-            <input type="range" anonid="volumeControl" class="volumeControl" min="0" max="100" step="1" tabindex="-1"/>
+            <input type="range" anonid="volumeControl" class="volumeControl" min="0" max="100" step="1" tabindex="-1" mozinputrangeignorepreventdefault="true" />
           </div>
           <button anonid="closedCaptionButton" class="closedCaptionButton"/>
           <button anonid="fullscreenButton"
                   class="fullscreenButton"
                   enterfullscreenlabel="&fullscreenButton.enterfullscreenlabel;"
                   exitfullscreenlabel="&fullscreenButton.exitfullscreenlabel;"/>
         </div>
         <div anonid="textTrackList" class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></div>