backout aba885aafee0210b1f063a423b1c0b3ce28d15f7 for intermittent bug 1272834
authorJoel Maher <jmaher@mozilla.com>
Wed, 14 Dec 2016 10:59:43 -0500
changeset 373165 8fcd8f50264be9c64aa85ac39097808f5bd59b30
parent 373164 9a2a507e5b17b8bbb2360196a69df59fedc4e535
child 373166 38470e52b9d3beb7f648d8726d0c731684ddb75c
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1272834
milestone53.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
backout aba885aafee0210b1f063a423b1c0b3ce28d15f7 for intermittent bug 1272834 MozReview-Commit-ID: BTJ13wWojaI
browser/base/content/test/general/browser_selectpopup.js
toolkit/content/widgets/popup.xml
toolkit/content/widgets/scrollbox.xml
toolkit/modules/SelectParentHelper.jsm
--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -59,29 +59,23 @@ const PAGECONTENT_SOMEHIDDEN =
 const PAGECONTENT_TRANSLATED =
   "<html><body>" +
   "<div id='div'>" +
   "<iframe id='frame' width='320' height='295' style='border: none;'" +
   "        src='data:text/html,<select id=select autofocus><option>he he he</option><option>boo boo</option><option>baz baz</option></select>'" +
   "</iframe>" +
   "</div></body></html>";
 
-function openSelectPopup(selectPopup, mode = "key", selector = "select",  win = window)
+function openSelectPopup(selectPopup, withMouse, selector = "select",  win = window)
 {
   let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
 
-  if (mode == "click" || mode == "mousedown") {
-    let mousePromise;
-    if (mode == "click") {
-      mousePromise = BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser);
-    } else {
-      mousePromise = BrowserTestUtils.synthesizeMouse(selector, 5, 5, { type: "mousedown" }, win.gBrowser.selectedBrowser);
-    }
-
-    return Promise.all([popupShownPromise, mousePromise]);
+  if (withMouse) {
+    return Promise.all([popupShownPromise,
+                        BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser)]);
   }
 
   EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, code: "ArrowDown" }, win);
   return popupShownPromise;
 }
 
 function hideSelectPopup(selectPopup, mode = "enter", win = window)
 {
@@ -174,26 +168,26 @@ function* doSelectTests(contentType, dtd
 
   yield hideSelectPopup(selectPopup);
 
   is(menulist.selectedIndex, 3, "Item 3 still selected");
   is((yield getInputEvents()), 1, "After closed - number of input events");
   is((yield getChangeEvents()), 1, "After closed - number of change events");
 
   // Opening and closing the popup without changing the value should not fire a change event.
-  yield openSelectPopup(selectPopup, "click");
+  yield openSelectPopup(selectPopup, true);
   yield hideSelectPopup(selectPopup, "escape");
   is((yield getInputEvents()), 1, "Open and close with no change - number of input events");
   is((yield getChangeEvents()), 1, "Open and close with no change - number of change events");
   EventUtils.synthesizeKey("VK_TAB", { });
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
   is((yield getInputEvents()), 1, "Tab away from select with no change - number of input events");
   is((yield getChangeEvents()), 1, "Tab away from select with no change - number of change events");
 
-  yield openSelectPopup(selectPopup, "click");
+  yield openSelectPopup(selectPopup, true);
   EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
   yield hideSelectPopup(selectPopup, "escape");
   is((yield getInputEvents()), isWindows ? 2 : 1, "Open and close with change - number of input events");
   is((yield getChangeEvents()), isWindows ? 2 : 1, "Open and close with change - number of change events");
   EventUtils.synthesizeKey("VK_TAB", { });
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
   is((yield getInputEvents()), isWindows ? 2 : 1, "Tab away from select with change - number of input events");
   is((yield getChangeEvents()), isWindows ? 2 : 1, "Tab away from select with change - number of change events");
@@ -217,42 +211,42 @@ add_task(function*() {
 add_task(function*() {
   const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
 
   let menulist = document.getElementById("ContentSelectDropdown");
   let selectPopup = menulist.menupopup;
 
   // First, try it when a different <select> element than the one that is open is removed
-  yield openSelectPopup(selectPopup, "click", "#one");
+  yield openSelectPopup(selectPopup, true, "#one");
 
   yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
     content.document.body.removeChild(content.document.getElementById("two"));
   });
 
   // Wait a bit just to make sure the popup won't close.
   yield new Promise(resolve => setTimeout(resolve, 1000));
 
   is(selectPopup.state, "open", "Different popup did not affect open popup");
 
   yield hideSelectPopup(selectPopup);
 
   // Next, try it when the same <select> element than the one that is open is removed
-  yield openSelectPopup(selectPopup, "click", "#three");
+  yield openSelectPopup(selectPopup, true, "#three");
 
   let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
   yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
     content.document.body.removeChild(content.document.getElementById("three"));
   });
   yield popupHiddenPromise;
 
   ok(true, "Popup hidden when select is removed");
 
   // Finally, try it when the tab is closed while the select popup is open.
-  yield openSelectPopup(selectPopup, "click", "#one");
+  yield openSelectPopup(selectPopup, true, "#one");
 
   popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
   yield BrowserTestUtils.removeTab(tab);
   yield popupHiddenPromise;
 
   ok(true, "Popup hidden when tab is closed");
 });
 
@@ -260,17 +254,17 @@ add_task(function*() {
 add_task(function*() {
   const pageUrl = "data:text/html," + escape(PAGECONTENT_TRANSLATED);
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
 
   let menulist = document.getElementById("ContentSelectDropdown");
   let selectPopup = menulist.menupopup;
 
   // First, get the position of the select popup when no translations have been applied.
-  yield openSelectPopup(selectPopup);
+  yield openSelectPopup(selectPopup, false);
 
   let rect = selectPopup.getBoundingClientRect();
   let expectedX = rect.left;
   let expectedY = rect.top;
 
   yield hideSelectPopup(selectPopup);
 
   // Iterate through a set of steps which each add more translation to the select's expected position.
@@ -301,17 +295,17 @@ add_task(function*() {
           changedWin.removeEventListener("MozAfterPaint", onPaint);
           resolve();
         });
 
         elem.style = contentStep[1];
       });
     });
 
-    yield openSelectPopup(selectPopup);
+    yield openSelectPopup(selectPopup, false);
 
     expectedX += step[2];
     expectedY += step[3];
 
     let popupRect = selectPopup.getBoundingClientRect();
     is(popupRect.left, expectedX, "step " + (stepIndex + 1) + " x");
     is(popupRect.top, expectedY, "step " + (stepIndex + 1) + " y");
 
@@ -372,17 +366,17 @@ add_task(function* test_event_order() {
         type: "click",
         cancelable: true,
         targetIsOption: true,
       },
     ];
 
     for (let mode of ["enter", "click"]) {
       let expected = mode == "enter" ? expectedEnter : expectedClick;
-      yield openSelectPopup(selectPopup, "click", mode == "enter" ? "#one" : "#two");
+      yield openSelectPopup(selectPopup, true, mode == "enter" ? "#one" : "#two");
 
       let eventsPromise = ContentTask.spawn(browser, [mode, expected], function*([contentMode, contentExpected]) {
         return new Promise((resolve) => {
           function onEvent(event) {
             select.removeEventListener(event.type, onEvent);
             Assert.ok(contentExpected.length, "Unexpected event " + event.type);
             let expectation = contentExpected.shift();
             Assert.equal(event.type, expectation.type,
@@ -425,57 +419,25 @@ function* performLargePopupTests(win)
 
     select.options[60].selected = true;
     select.focus();
   });
 
   let selectPopup = win.document.getElementById("ContentSelectDropdown").menupopup;
   let browserRect = browser.getBoundingClientRect();
 
-  // Check if a drag-select works and scrolls the list.
-  yield openSelectPopup(selectPopup, "mousedown", "select", win);
-
-  let scrollPos = selectPopup.scrollBox.scrollTop;
-  let popupRect = selectPopup.getBoundingClientRect();
-
-  // First, check that scrolling does not occur when the mouse is moved over the
-  // anchor button but not the popup yet.
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 5, popupRect.top - 10, { type: "mousemove" }, win);
-  is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position after mousemove over button");
-
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.top + 10, { type: "mousemove" }, win);
-
-  // Dragging above the popup scrolls it up.
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.top - 20, { type: "mousemove" }, win);
-  ok(selectPopup.scrollBox.scrollTop < scrollPos - 5, "scroll position at drag up");
-
-  // Dragging below the popup scrolls it down.
-  scrollPos = selectPopup.scrollBox.scrollTop;
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 20, { type: "mousemove" }, win);
-  ok(selectPopup.scrollBox.scrollTop > scrollPos + 5, "scroll position at drag down");
-
-  // Releasing the mouse button and moving the mouse does not change the scroll position.
-  scrollPos = selectPopup.scrollBox.scrollTop;
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 25, { type: "mouseup" }, win);
-  is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position at mouseup");
-
-  EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 20, { type: "mousemove" }, win);
-  is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position at mouseup again");
-
-  yield hideSelectPopup(selectPopup, "escape", win);
-
   let positions = [
     "margin-top: 300px;",
     "position: fixed; bottom: 100px;",
     "width: 100%; height: 9999px;"
   ];
 
   let position;
-  while (positions.length) {
-    yield openSelectPopup(selectPopup, "key", "select", win);
+  while (true) {
+    yield openSelectPopup(selectPopup, false, "select", win);
 
     let rect = selectPopup.getBoundingClientRect();
     ok(rect.top >= browserRect.top, "Popup top position in within browser area");
     ok(rect.bottom <= browserRect.bottom, "Popup bottom position in within browser area");
 
     // Don't check the scroll position for the last step as the popup will be cut off.
     if (positions.length > 0) {
       let cs = win.getComputedStyle(selectPopup);
@@ -484,21 +446,24 @@ function* performLargePopupTests(win)
       is(selectPopup.childNodes[60].getBoundingClientRect().bottom,
          selectPopup.getBoundingClientRect().bottom - bpBottom,
          "Popup scroll at correct position " + bpBottom);
     }
 
     yield hideSelectPopup(selectPopup, "enter", win);
 
     position = positions.shift();
+    if (!position) {
+      break;
+    }
 
     let contentPainted = BrowserTestUtils.contentPainted(browser);
     yield ContentTask.spawn(browser, position, function*(contentPosition) {
       let select = content.document.getElementById("one");
-      select.setAttribute("style", contentPosition || "");
+      select.setAttribute("style", contentPosition);
     });
     yield contentPainted;
   }
 }
 
 // This test checks select elements with a large number of options to ensure that
 // the popup appears within the browser area.
 add_task(function* test_large_popup() {
@@ -549,17 +514,17 @@ add_task(function* test_mousemove_correc
   });
 
   yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mouseup" }, gBrowser.selectedBrowser);
 
   yield hideSelectPopup(selectPopup);
 
   // The popup should be closed when fullscreen mode is entered or exited.
   for (let steps = 0; steps < 2; steps++) {
-    yield openSelectPopup(selectPopup, "click");
+    yield openSelectPopup(selectPopup, true);
     let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
     let sizeModeChanged = BrowserTestUtils.waitForEvent(window, "sizemodechange");
     BrowserFullScreen();
     yield sizeModeChanged;
     yield popupHiddenPromise;
   }
 
   yield BrowserTestUtils.removeTab(tab);
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -241,22 +241,16 @@
 
     <content>
       <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
                           smoothscroll="false">
         <children/>
       </xul:arrowscrollbox>
     </content>
 
-    <implementation>
-      <field name="scrollBox" readonly="true">
-        document.getAnonymousElementByAttribute(this, "class", "popup-internal-box");
-      </field>
-    </implementation>
-
     <handlers>
       <handler event="popupshowing" phase="target">
         <![CDATA[
           var array = [];
           var width = 0;
           for (var menuitem = this.firstChild; menuitem; menuitem = menuitem.nextSibling) {
             if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) {
               var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel");
@@ -627,15 +621,15 @@
         this._isMouseOver = false;
         this._mouseOutCount = 0;
       ]]></handler>
     </handlers>
   </binding>
 
   <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
     <content>
-      <xul:scrollbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;">
+      <xul:hbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;">
         <children/>
-      </xul:scrollbox>
+      </xul:hbox>
     </content>
   </binding>
 
 </bindings>
--- a/toolkit/content/widgets/scrollbox.xml
+++ b/toolkit/content/widgets/scrollbox.xml
@@ -16,25 +16,16 @@
   </binding>
 
   <binding id="scrollbox" extends="chrome://global/content/bindings/scrollbox.xml#scrollbox-base">
     <content>
       <xul:box class="box-inherit scrollbox-innerbox" xbl:inherits="orient,align,pack,dir" flex="1">
         <children/>
       </xul:box>
     </content>
-
-    <implementation>
-      <method name="scrollByIndex">
-        <parameter name="index"/>
-        <body>
-          this.boxObject.scrollByIndex(index);
-        </body>
-      </method>
-    </implementation>
   </binding>
 
   <binding id="arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#scrollbox-base">
     <content>
       <xul:autorepeatbutton class="autorepeatbutton-up"
                             anonid="scrollbutton-up"
                             xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtostart"
                             oncommand="_autorepeatbuttonScroll(event);"/>
--- a/toolkit/modules/SelectParentHelper.jsm
+++ b/toolkit/modules/SelectParentHelper.jsm
@@ -9,28 +9,22 @@ this.EXPORTED_SYMBOLS = [
 ];
 
 const {utils: Cu} = Components;
 const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
 
 // Maximum number of rows to display in the select dropdown.
 const MAX_ROWS = 20;
 
-// Interval between autoscrolls
-const AUTOSCROLL_INTERVAL = 25;
-
 var currentBrowser = null;
 var currentMenulist = null;
 var currentZoom = 1;
 var closedWithEnter = false;
 
 this.SelectParentHelper = {
-  draggedOverPopup: false,
-  scrollTimer: 0,
-
   populate: function(menulist, items, selectedIndex, zoom) {
     // Clear the current contents of the popup
     menulist.menupopup.textContent = "";
     currentZoom = zoom;
     currentMenulist = menulist;
     populateChildren(menulist, items, selectedIndex, zoom);
   },
 
@@ -62,85 +56,38 @@ this.SelectParentHelper = {
     menupopup.classList.toggle("isOpenedViaTouch", isOpenedViaTouch);
 
     let constraintRect = browser.getBoundingClientRect();
     constraintRect = new win.DOMRect(constraintRect.left + win.mozInnerScreenX,
                                      constraintRect.top + win.mozInnerScreenY,
                                      constraintRect.width, constraintRect.height);
     menupopup.setConstraintRect(constraintRect);
     menupopup.openPopupAtScreenRect(AppConstants.platform == "macosx" ? "selection" : "after_start", rect.left, rect.top, rect.width, rect.height, false, false);
-
-    // Set up for dragging
-    menupopup.setCaptureAlways();
-    this.draggedOverPopup = false;
-    menupopup.addEventListener("mousemove", this);
   },
 
   hide: function(menulist, browser) {
     if (currentBrowser == browser) {
       menulist.menupopup.hidePopup();
     }
   },
 
-  clearScrollTimer: function() {
-    if (this.scrollTimer) {
-      let win = currentBrowser.ownerDocument.defaultView;
-      win.clearInterval(this.scrollTimer);
-      this.scrollTimer = 0;
-    }
-  },
-
   handleEvent: function(event) {
     switch (event.type) {
       case "mouseup":
-        this.clearScrollTimer();
-        currentMenulist.menupopup.removeEventListener("mousemove", this);
         currentBrowser.messageManager.sendAsyncMessage("Forms:MouseUp", {});
         break;
 
       case "mouseover":
         currentBrowser.messageManager.sendAsyncMessage("Forms:MouseOver", {});
         break;
 
       case "mouseout":
         currentBrowser.messageManager.sendAsyncMessage("Forms:MouseOut", {});
         break;
 
-      case "mousemove":
-        let menupopup = currentMenulist.menupopup;
-        let popupRect = menupopup.getOuterScreenRect();
-
-        this.clearScrollTimer();
-
-        // If dragging outside the top or bottom edge of the popup, but within
-        // the popup area horizontally, scroll the list in that direction. The
-        // draggedOverPopup flag is used to ensure that scrolling does not start
-        // until the mouse has moved over the popup first, preventing scrolling
-        // while over the dropdown button.
-        if (event.screenX >= popupRect.left && event.screenX <= popupRect.right) {
-          if (!this.draggedOverPopup) {
-            if (event.screenY > popupRect.top && event.screenY < popupRect.bottom) {
-              this.draggedOverPopup = true;
-            }
-          }
-
-          if (this.draggedOverPopup &&
-              (event.screenY <= popupRect.top || event.screenY >= popupRect.bottom)) {
-            let scrollAmount = event.screenY <= popupRect.top ? -1 : 1;
-            menupopup.scrollBox.scrollByIndex(scrollAmount);
-
-            let win = currentBrowser.ownerDocument.defaultView;
-            this.scrollTimer = win.setInterval(function() {
-              menupopup.scrollBox.scrollByIndex(scrollAmount);
-            }, AUTOSCROLL_INTERVAL);
-          }
-        }
-
-        break;
-
       case "keydown":
         if (event.keyCode == event.DOM_VK_RETURN) {
           closedWithEnter = true;
         }
         break;
 
       case "command":
         if (event.target.hasAttribute("value")) {
@@ -156,18 +103,16 @@ this.SelectParentHelper = {
           currentMenulist.menupopup.hidePopup();
         }
         break;
 
       case "popuphidden":
         currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {});
         let popup = event.target;
         this._unregisterListeners(currentBrowser, popup);
-        this.clearScrollTimer();
-        popup.releaseCapture();
         popup.parentNode.hidden = true;
         currentBrowser = null;
         currentMenulist = null;
         currentZoom = 1;
         break;
     }
   },