Bug 1540150 - Make it impossible to enter the native drag-drop loop in test automation. r=NeilDeakin
authorMike Conley <mconley@mozilla.com>
Thu, 11 Apr 2019 17:17:36 +0000
changeset 469071 c523c4658e98d236594a1124820a0b142300e6cd
parent 469070 d679d6a5d63f00f5a4bdacdd9280682a41138eca
child 469072 186322f1d1f212f92a5a925814a5869e9c78d19b
push id35856
push usercsabou@mozilla.com
push dateFri, 12 Apr 2019 03:19:48 +0000
treeherdermozilla-central@940684cd1065 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersNeilDeakin
bugs1540150
milestone68.0a1
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
Bug 1540150 - Make it impossible to enter the native drag-drop loop in test automation. r=NeilDeakin Differential Revision: https://phabricator.services.mozilla.com/D25428
dom/events/test/test_bug1264380.html
layout/generic/test/mochitest.ini
layout/generic/test/test_bug470212.html
widget/nsBaseDragService.cpp
--- a/dom/events/test/test_bug1264380.html
+++ b/dom/events/test/test_bug1264380.html
@@ -8,47 +8,68 @@
 
 function runTests()
 {
   let dragService = SpecialPowers.Cc["@mozilla.org/widget/dragservice;1"].
     getService(SpecialPowers.Ci.nsIDragService);
 
   let iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
-  iframe.contentDocument.body.innerHTML = '<div id="outter"/>';
+  iframe.contentDocument.body.innerHTML = '<div id="outer"/>';
 
   let iframeDoc = iframe.contentDocument;
   let iframeWin = iframe.contentWindow;
 
-  let shadow = iframeDoc.querySelector('#outter').attachShadow({mode: 'open'});
+  let shadow = iframeDoc.querySelector('#outer').attachShadow({mode: 'open'});
   let target = iframeDoc.createElement('a');
-  let linkText = iframeDoc.createTextNode("Drag me if you can!");
+
+  const TEXT = "Drag me if you can!";
+  let linkText = iframeDoc.createTextNode(TEXT);
   target.appendChild(linkText);
-  target.href = "http://www.mozilla.org/";
+
+  const URL = "http://www.mozilla.org/";
+  target.href = URL;
   shadow.appendChild(target);
 
-  let dataTransfer;
-  let trapDrag = function(event) {
-    ok(true, "Got dragstart event");
-    dataTransfer = event.dataTransfer;
-    ok(dataTransfer, "DataTransfer object is available.");
-    is(SpecialPowers.wrap(dataTransfer).mozItemCount, 1, "initial link item count");
-    is(dataTransfer.getData("text/uri-list"), "http://www.mozilla.org/", "link text/uri-list");
-    is(dataTransfer.getData("text/plain"), "http://www.mozilla.org/", "link text/plain");
+  // Some of the drag data we don't actually care about for this test,
+  // so we'll use this comparator function to ignore them.
+  function ignoreFunc(actualData, expectedData) {
+    return true;
   }
 
-  ok(!dragService.getCurrentSession(), "There shouldn't be a drag session!");
-  iframeWin.addEventListener("dragstart", trapDrag, true);
-  synthesizeMouse(target, 2, 2, { type: "mousedown" }, iframeWin);
-  synthesizeMouse(target, 11, 11, { type: "mousemove" }, iframeWin);
-  synthesizeMouse(target, 20, 20, { type: "mousemove" }, iframeWin);
-  iframeWin.removeEventListener("dragstart", trapDrag, true);
-  ok(dragService.getCurrentSession(), "Drag session is available.");
-  dragService.endDragSession(false);
-  ok(!dragService.getCurrentSession(), "There shouldn't be a drag session anymore!");
+  const EXPECTED_DRAG_DATA = [[{
+    type: "text/x-moz-url",
+    data: "",
+    eqTest: ignoreFunc,
+  }, {
+    type: "text/x-moz-url-data",
+    data: "",
+    eqTest: ignoreFunc,
+  }, {
+    type: "text/x-moz-url-desc",
+    data: "",
+    eqTest: ignoreFunc,
+  }, {
+    type: "text/uri-list",
+    data: URL,
+  }, {
+    type: "text/_moz_htmlinfo",
+    data: "",
+    eqTest: ignoreFunc,
+  }, {
+    type: "text/html",
+    data: "",
+    eqTest: ignoreFunc,
+  }, {
+    type: "text/plain",
+    data: URL,
+  }]];
+
+  let result = synthesizeDragStart(target, EXPECTED_DRAG_DATA, iframeWin);
+  is(result, null, "Should have gotten the expected drag data.");
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 window.onload = () => {
   SimpleTest.waitForFocus(runTests);
 };
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -101,17 +101,17 @@ support-files = file_bug1307853.html
 [test_bug1408607.html]
 [test_bug1499961.html]
 [test_contained_plugin_transplant.html]
 skip-if = os=='win'
 [test_dynamic_reflow_root_disallowal.html]
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || headless # Headless:Bug 1405871
 [test_intrinsic_size_on_loading.html]
 [test_movement_by_characters.html]
 [test_movement_by_words.html]
 # Disable the caret movement by word test on Linux because the shortcut keys
 # are defined in system level.  So, it depends on the environment.
 # Disable on Windows for too many intermittent failures (bug 916143).
 skip-if = (toolkit == "gtk3") || (os == "win")
 [test_overflow_event.html]
--- a/layout/generic/test/test_bug470212.html
+++ b/layout/generic/test/test_bug470212.html
@@ -21,16 +21,21 @@ function doShiftDrag(){
   setTimeout(function() {
     var wu = SpecialPowers.DOMWindowUtils;
     var canvas = document.getElementById("dragSource");
     var canvasRect = canvas.getBoundingClientRect();
 
     // Drag canvas element starts with a mouse down event, combine with shift
     // key, follows by two mouse move events.
 
+    window.addEventListener("dragstart", e => {
+      e.preventDefault();
+      e.stopPropagation();
+    }, { once: true });
+
     // Press on left-top corner of the canvas element.
     wu.sendMouseEvent('mousedown',  canvasRect.left, canvasRect.top, 0, 1, 4);
     // Move to the center of this cavas element.
     wu.sendMouseEvent('mousemove',  canvasRect.left + (canvasRect.width / 2),
                       canvasRect.top + (canvasRect.height / 2), 0, 0, 4);
     // move out of cavas's region.
     wu.sendMouseEvent('mousemove',  canvasRect.left + (canvasRect.width / 2),
                       canvasRect.bottom + 10, 0, 0, 4);
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -200,16 +200,33 @@ void nsBaseDragService::SetDataTransfer(
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSession(
     nsINode* aDOMNode, nsIPrincipal* aPrincipal, nsIArray* aTransferableArray,
     uint32_t aActionType,
     nsContentPolicyType aContentPolicyType = nsIContentPolicy::TYPE_OTHER) {
   AUTO_PROFILER_LABEL("nsBaseDragService::InvokeDragSession", OTHER);
 
+  // If you're hitting this, a test is causing the browser to attempt to enter
+  // the drag-drop native nested event loop, which will put the browser in a
+  // state that won't run tests properly until there's manual intervention
+  // to exit the drag-drop loop (either by moving the mouse or hitting escape),
+  // which can't be done from script since we're in the nested loop.
+  //
+  // The best way to avoid this is to catch the dragstart event on the item
+  // being dragged, and then to call preventDefault() and stopPropagating() on
+  // it. Alternatively, use EventUtils.synthesizeDragStart, which will do this
+  // for you.
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(
+        !xpc::IsInAutomation(),
+        "About to start drag-drop native loop on which will prevent later "
+        "tests from running properly.");
+  }
+
   NS_ENSURE_TRUE(aDOMNode, NS_ERROR_INVALID_ARG);
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
   // stash the document of the dom node
   mSourceDocument = aDOMNode->OwnerDoc();
   mTriggeringPrincipal = aPrincipal;
   mSourceNode = aDOMNode;
   mContentPolicyType = aContentPolicyType;