Bug 1101628 - Refactor snapshotting code to allow reusing it across tests. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 01 Jun 2016 15:48:05 -0400
changeset 339007 f06e9936989826dcdcaee97cf8f75fb03381190f
parent 339006 274c6d39f9635a7ef4844930043a9d28c13130b5
child 339008 30cffc59820746939a2fd8f928a65ecb8853379c
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1101628
milestone49.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 1101628 - Refactor snapshotting code to allow reusing it across tests. r=botond MozReview-Commit-ID: BRSUNn5gxSX
gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
gfx/layers/apz/test/mochitest/apz_test_utils.js
gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -85,16 +85,30 @@ function coordinatesRelativeToScreen(aX,
   var scale = targetWindow.devicePixelRatio;
   var rect = aElement.getBoundingClientRect();
   return {
     x: (targetWindow.mozInnerScreenX + rect.left + aX) * scale,
     y: (targetWindow.mozInnerScreenY + rect.top + aY) * scale
   };
 }
 
+// Get the bounding box of aElement, and return it in device pixels
+// relative to the screen.
+function rectRelativeToScreen(aElement) {
+  var targetWindow = aElement.ownerDocument.defaultView;
+  var scale = targetWindow.devicePixelRatio;
+  var rect = aElement.getBoundingClientRect();
+  return {
+    x: (targetWindow.mozInnerScreenX + rect.left) * scale,
+    y: (targetWindow.mozInnerScreenY + rect.top) * scale,
+    w: (rect.width * scale),
+    h: (rect.height * scale)
+  };
+}
+
 // Synthesizes a native mousewheel event and returns immediately. This does not
 // guarantee anything; you probably want to use one of the other functions below
 // which actually wait for results.
 // aX and aY are relative to the top-left of |aElement|'s containing window.
 // aDeltaX and aDeltaY are pixel deltas, and aObserver can be left undefined
 // if not needed.
 function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) {
   var pt = coordinatesRelativeToScreen(aX, aY, aElement);
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -262,8 +262,53 @@ function runContinuation(testFunction) {
           resolve();
         }
       }
 
       driveTest();
     });
   };
 }
+
+// Take a snapshot of the given rect, *including compositor transforms* (i.e.
+// includes async scroll transforms applied by APZ). If you don't need the
+// compositor transforms, you can probably get away with using
+// SpecialPowers.snapshotWindowWithOptions or one of the friendlier wrappers.
+// The rect provided is expected to be relative to the screen, for example as
+// returned by rectRelativeToScreen in apz_test_native_event_utils.js.
+// Example usage:
+//   var snapshot = getSnapshot(rectRelativeToScreen(myDiv));
+// which will take a snapshot of the 'myDiv' element. Note that if part of the
+// element is obscured by other things on top, the snapshot will include those
+// things. If it is clipped by a scroll container, the snapshot will include
+// that area anyway, so you will probably get parts of the scroll container in
+// the snapshot. If the rect extends outside the browser window then the
+// results are undefined.
+// The snapshot is returned in the form of a data URL.
+function getSnapshot(rect) {
+  function parentProcessSnapshot() {
+    addMessageListener('snapshot', function(rect) {
+      Components.utils.import('resource://gre/modules/Services.jsm');
+      var topWin = Services.wm.getMostRecentWindow('navigator:browser');
+
+      // reposition the rect relative to the top-level browser window
+      rect = JSON.parse(rect);
+      rect.x -= topWin.mozInnerScreenX;
+      rect.y -= topWin.mozInnerScreenY;
+
+      // take the snapshot
+      var canvas = topWin.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+      canvas.width = rect.w;
+      canvas.height = rect.h;
+      var ctx = canvas.getContext("2d");
+      ctx.drawWindow(topWin, rect.x, rect.y, rect.w, rect.h, 'rgb(255,255,255)', ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_CARET);
+      return canvas.toDataURL();
+    });
+  }
+
+  if (typeof getSnapshot.chromeHelper == 'undefined') {
+    // This is the first time getSnapshot is being called; do initialization
+    getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
+    SimpleTest.registerCleanupFunction(function() { getSnapshot.chromeHelper.destroy() });
+  }
+
+  return getSnapshot.chromeHelper.sendSyncMessage('snapshot', JSON.stringify(rect)).toString();
+}
--- a/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
+++ b/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
@@ -22,59 +22,33 @@ https://bugzilla.mozilla.org/show_bug.cg
   <div id="box" style="width: 200px; height: 200px; background-color: blue"></div>
   <div style="height: 1000px; width: 10px">Div to make 'content' scrollable</div>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 const kResponseTimeoutMs = 2 * 60 * 1000; // 2 minutes
 
-function parentProcessSnapshot() {
-  addMessageListener('snapshot', function(rect) {
-    Components.utils.import('resource://gre/modules/Services.jsm');
-    var topWin = Services.wm.getMostRecentWindow('navigator:browser');
-
-    // reposition the rect relative to the top-level browser window
-    rect = JSON.parse(rect);
-    rect.x -= topWin.mozInnerScreenX;
-    rect.y -= topWin.mozInnerScreenY;
-
-    // take the snapshot
-    var canvas = topWin.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-    canvas.width = rect.w;
-    canvas.height = rect.h;
-    var ctx = canvas.getContext("2d");
-    ctx.drawWindow(topWin, rect.x, rect.y, rect.w, rect.h, 'rgb(255,255,255)', ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_CARET);
-    return canvas.toDataURL();
-  });
-}
-
 function takeSnapshots(e) {
   // Grab some snapshots, and make sure some of them are different (i.e. check
   // the page is scrolling in the compositor, concurrently with this wheel
   // listener running).
   // Note that we want this function to take less time than the content response
   // timeout, otherwise the scrolling will start even if we haven't returned,
   // and that would invalidate purpose of the test.
   var start = Date.now();
   var lastSnapshot = null;
   var success = false;
 
-  var chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
-  SimpleTest.registerCleanupFunction(function() { chromeHelper.destroy() });
-
   // Get the position of the 'content' div relative to the screen
-  var contentDiv = document.getElementById('content');
-  var rect = coordinatesRelativeToWindow(0, 0, contentDiv);
-  rect.w = contentDiv.getBoundingClientRect().width * window.devicePixelRatio;
-  rect.h = contentDiv.getBoundingClientRect().height * window.devicePixelRatio;
+  var rect = rectRelativeToScreen(document.getElementById('content'));
 
   for (var i = 0; i < 10; i++) {
     SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(16);
-    var snapshot = chromeHelper.sendSyncMessage('snapshot', JSON.stringify(rect)).toString();
+    var snapshot = getSnapshot(rect);
     //dump("Took snapshot " + snapshot + "\n"); // this might help with debugging
 
     if (lastSnapshot && lastSnapshot != snapshot) {
       ok(true, "Found some different pixels in snapshot " + i + " compared to previous");
       success = true;
     }
     lastSnapshot = snapshot;
   }