Bug 1392281 - Pass window global to action module instead of container. r?automatedtester draft
authorAndreas Tolfsen <ato@sny.no>
Mon, 21 Aug 2017 17:34:23 +0100
changeset 650043 874d9f04dab41d7ab29552a01a337226130a5a1d
parent 649871 c7c96eebbcb91e5e0c8ef0dbbb5324812fa1e476
child 727261 13af6b44057d63c27d13f154bc1a52e7f88f8a56
push id75229
push userbmo:ato@sny.no
push dateMon, 21 Aug 2017 16:34:54 +0000
reviewersautomatedtester
bugs1392281
milestone57.0a1
Bug 1392281 - Pass window global to action module instead of container. r?automatedtester Various functions in the action module take a container object such as {frame: <WindowProxy global>, shadowRoot: <Element>} when it in fact never uses the shadowRoot entry. As part of the new window tracking we will get rid of the container concept altogether. Because the action module is sufficiently self-contained, we can start with removing it from there already. MozReview-Commit-ID: KeeNF08mqnX
testing/marionette/action.js
testing/marionette/listener.js
--- a/testing/marionette/action.js
+++ b/testing/marionette/action.js
@@ -956,31 +956,30 @@ action.Mouse = class {
  * tick's actions are not dispatched until the Promise for the current
  * tick is resolved.
  *
  * @param {action.Chain} chain
  *     Actions grouped by tick; each element in |chain| is a sequence of
  *     actions for one tick.
  * @param {element.Store} seenEls
  *     Element store.
- * @param {Object.<string, nsIDOMWindow>} container
- *     Object with <code>frame</code> property of type
- *     <code>nsIDOMWindow</code>.
+ * @param {WindowProxy} window
+ *     Current window global.
  *
  * @return {Promise}
  *     Promise for dispatching all actions in |chain|.
  */
-action.dispatch = function(chain, seenEls, container) {
+action.dispatch = function(chain, seenEls, window) {
   let chainEvents = (async () => {
     for (let tickActions of chain) {
       await action.dispatchTickActions(
           tickActions,
           action.computeTickDuration(tickActions),
           seenEls,
-          container);
+          window);
     }
   })();
   return chainEvents;
 };
 
 /**
  * Dispatch sequence of actions for one tick.
  *
@@ -993,29 +992,28 @@ action.dispatch = function(chain, seenEl
  * different durations and therefore may not end in the same order.
  *
  * @param {Array.<action.Action>} tickActions
  *     List of actions for one tick.
  * @param {number} tickDuration
  *     Duration in milliseconds of this tick.
  * @param {element.Store} seenEls
  *     Element store.
- * @param {Object.<string, nsIDOMWindow>} container
- *     Object with <code>frame</code> property of type
- *     <code>nsIDOMWindow</code>.
+ * @param {WindowProxy} window
+ *     Current window global.
  *
  * @return {Promise}
  *     Promise for dispatching all tick-actions and pending DOM events.
  */
 action.dispatchTickActions = function(
-    tickActions, tickDuration, seenEls, container) {
+    tickActions, tickDuration, seenEls, window) {
   let pendingEvents = tickActions.map(
-      toEvents(tickDuration, seenEls, container));
+      toEvents(tickDuration, seenEls, window));
   return Promise.all(pendingEvents).then(
-      () => interaction.flushEventLoop(container.frame));
+      () => interaction.flushEventLoop(window));
 };
 
 /**
  * Compute tick duration in milliseconds for a collection of actions.
  *
  * @param {Array.<action.Action>} tickActions
  *     List of actions for one tick.
  *
@@ -1071,50 +1069,51 @@ action.computePointerDestination = funct
 
 /**
  * Create a closure to use as a map from action definitions to Promise events.
  *
  * @param {number} tickDuration
  *     Duration in milliseconds of this tick.
  * @param {element.Store} seenEls
  *     Element store.
- * @param {Object.<string, nsIDOMWindow>} container
- *     Object with <code>frame</code> property of type
- *     <code>nsIDOMWindow</code>.
+ * @param {WindowProxy} window
+ *     Current window global.
  *
  * @return {function(action.Action): Promise}
  *     Function that takes an action and returns a Promise for dispatching
  *     the event that corresponds to that action.
  */
-function toEvents(tickDuration, seenEls, container) {
+function toEvents(tickDuration, seenEls, window) {
   return a => {
     let inputState = action.inputStateMap.get(a.id);
+
     switch (a.subtype) {
       case action.KeyUp:
-        return dispatchKeyUp(a, inputState, container.frame);
+        return dispatchKeyUp(a, inputState, window);
 
       case action.KeyDown:
-        return dispatchKeyDown(a, inputState, container.frame);
+        return dispatchKeyDown(a, inputState, window);
 
       case action.PointerDown:
-        return dispatchPointerDown(a, inputState, container.frame);
+        return dispatchPointerDown(a, inputState, window);
 
       case action.PointerUp:
-        return dispatchPointerUp(a, inputState, container.frame);
+        return dispatchPointerUp(a, inputState, window);
 
       case action.PointerMove:
         return dispatchPointerMove(
-            a, inputState, tickDuration, seenEls, container);
+            a, inputState, tickDuration, seenEls, window);
 
       case action.PointerCancel:
         throw new UnsupportedOperationError();
 
       case action.Pause:
         return dispatchPause(a, tickDuration);
     }
+
     return undefined;
   };
 }
 
 /**
  * Dispatch a keyDown action equivalent to pressing a key on a keyboard.
  *
  * @param {action.Action} a
@@ -1282,73 +1281,77 @@ function dispatchPointerUp(a, inputState
  * with the pointer coordinates being updated around 60 times per second.
  *
  * @param {action.Action} a
  *     Action to dispatch.
  * @param {action.InputState} inputState
  *     Input state for this action's input source.
  * @param {element.Store} seenEls
  *     Element store.
- * @param {Object.<string, nsIDOMWindow>} container
- *     Object with <code>frame</code> property of type
- *     <code>nsIDOMWindow</code>.
+ * @param {WindowProxy} window
+ *     Current window global.
  *
  * @return {Promise}
  *     Promise to dispatch at least one pointermove event, as well as
  *     mousemove events as appropriate.
  */
-function dispatchPointerMove(
-    a, inputState, tickDuration, seenEls, container) {
+function dispatchPointerMove(a, inputState, tickDuration, seenEls, window) {
   const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   // interval between pointermove increments in ms, based on common vsync
   const fps60 = 17;
+
   return new Promise(resolve => {
     const start = Date.now();
     const [startX, startY] = [inputState.x, inputState.y];
+
     let target = action.computePointerDestination(a, inputState,
-        getElementCenter(a.origin, seenEls, container));
+        getElementCenter(a.origin, seenEls, window));
     const [targetX, targetY] = [target.x, target.y];
-    if (!inViewPort(targetX, targetY, container.frame)) {
+
+    if (!inViewPort(targetX, targetY, window)) {
       throw new MoveTargetOutOfBoundsError(
           `(${targetX}, ${targetY}) is out of bounds of viewport ` +
-          `width (${container.frame.innerWidth}) ` +
-          `and height (${container.frame.innerHeight})`);
+          `width (${window.innerWidth}) ` +
+          `and height (${window.innerHeight})`);
     }
 
     const duration = typeof a.duration == "undefined" ? tickDuration : a.duration;
     if (duration === 0) {
       // move pointer to destination in one step
-      performOnePointerMove(inputState, targetX, targetY, container.frame);
+      performOnePointerMove(inputState, targetX, targetY, window);
       resolve();
       return;
     }
 
     const distanceX = targetX - startX;
     const distanceY = targetY - startY;
     const ONE_SHOT = Ci.nsITimer.TYPE_ONE_SHOT;
     let intermediatePointerEvents = (async () => {
       // wait |fps60| ms before performing first incremental pointer move
       await new Promise(resolveTimer =>
           timer.initWithCallback(resolveTimer, fps60, ONE_SHOT));
+
       let durationRatio = Math.floor(Date.now() - start) / duration;
       const epsilon = fps60 / duration / 10;
       while ((1 - durationRatio) > epsilon) {
         let x = Math.floor(durationRatio * distanceX + startX);
         let y = Math.floor(durationRatio * distanceY + startY);
-        performOnePointerMove(inputState, x, y, container.frame);
+        performOnePointerMove(inputState, x, y, window);
         // wait |fps60| ms before performing next pointer move
         await new Promise(resolveTimer =>
             timer.initWithCallback(resolveTimer, fps60, ONE_SHOT));
+
         durationRatio = Math.floor(Date.now() - start) / duration;
       }
     })();
+
     // perform last pointer move after all incremental moves are resolved and
     // durationRatio is close enough to 1
     intermediatePointerEvents.then(() => {
-      performOnePointerMove(inputState, targetX, targetY, container.frame);
+      performOnePointerMove(inputState, targetX, targetY, window);
       resolve();
     });
 
   });
 }
 
 function performOnePointerMove(inputState, targetX, targetY, win) {
   if (targetX == inputState.x && targetY == inputState.y) {
@@ -1404,17 +1407,17 @@ function capitalize(str) {
 
 function inViewPort(x, y, win) {
   assert.number(x, `Expected x to be finite number`);
   assert.number(y, `Expected y to be finite number`);
   // Viewport includes scrollbars if rendered.
   return !(x < 0 || y < 0 || x > win.innerWidth || y > win.innerHeight);
 }
 
-function getElementCenter(elementReference, seenEls, container) {
+function getElementCenter(elementReference, seenEls, window) {
   if (element.isWebElementReference(elementReference)) {
     let uuid = elementReference[element.Key] ||
         elementReference[element.LegacyKey];
-    let el = seenEls.get(uuid, container);
+    let el = seenEls.get(uuid, {frame: window});
     return element.coordinates(el);
   }
   return {};
 }
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -932,28 +932,28 @@ function createATouch(el, corx, cory, to
  * Perform a series of grouped actions at the specified points in time.
  *
  * @param {obj} msg
  *      Object with an |actions| attribute that is an Array of objects
  *      each of which represents an action sequence.
  */
 async function performActions(msg) {
   let chain = action.Chain.fromJson(msg.actions);
-  await action.dispatch(chain, seenEls, curContainer);
+  await action.dispatch(chain, seenEls, curContainer.frame);
 }
 
 /**
  * The release actions command is used to release all the keys and pointer
  * buttons that are currently depressed. This causes events to be fired
  * as if the state was released by an explicit series of actions. It also
  * clears all the internal state of the virtual devices.
  */
 async function releaseActions() {
   await action.dispatchTickActions(
-      action.inputsToCancel.reverse(), 0, seenEls, curContainer);
+      action.inputsToCancel.reverse(), 0, seenEls, curContainer.frame);
   action.inputsToCancel.length = 0;
   action.inputStateMap.clear();
 }
 
 /**
  * Start action chain on one finger.
  */
 function actionChain(chain, touchId) {