Bug 883294 - Add ability to take full viewport screenshots. r=mdas

This commit is contained in:
Dave Hunt 2014-09-30 14:42:00 -04:00
parent 5449ebd11b
commit 8d56be189c
3 changed files with 78 additions and 19 deletions

View File

@ -246,9 +246,9 @@ class HTMLReportingTestResultMixin(object):
def gather_debug(self):
debug = {}
try:
# TODO make screenshot consistant size by using full viewport
# Bug 883294 - Add ability to take full viewport screenshots
self.marionette.switch_context(self.marionette.CONTEXT_CHROME)
debug['screenshot'] = self.marionette.screenshot()
self.marionette.switch_context(self.marionette.CONTEXT_CONTENT)
debug['source'] = self.marionette.page_source
self.marionette.switch_to_frame()
debug['settings'] = json.dumps(self.marionette.execute_async_script("""

View File

@ -1,11 +1,25 @@
from marionette_test import MarionetteTestCase
import base64
import imghdr
from marionette_test import MarionetteTestCase
RED_ELEMENT_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAVUlEQVRoge3PsQ0AIAzAsI78fzBwBhHykD2ePev80LweAAGJB1ILpBZILZBaILVAaoHUAqkFUgukFkgtkFogtUBqgdQCqQVSC6QWSC2QWiC1QGp9A7ma+7nyXgOpzQAAAABJRU5ErkJggg=='
GREEN_ELEMENT_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAV0lEQVRoge3PQRGAQAwAsWINvXgsNnI3+4iAzM7sDWZn9vneoxXRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNHcF7nBD/Ha5Ye4BbsYAAAAAElFTkSuQmCC'
class ScreenshotTests(MarionetteTestCase):
def testWeCanTakeAScreenShotOfEntireViewport(self):
test_url = self.marionette.absolute_url('html5Page.html')
self.marionette.navigate(test_url)
content = self.marionette.screenshot()
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
chrome = self.marionette.screenshot()
# Check the base64 decoded string is a PNG file.
image = base64.decodestring(chrome)
self.assertEqual(imghdr.what('', image), 'png')
self.assertNotEqual(content, chrome)
def testWeCanTakeAScreenShotOfAnElement(self):
test_url = self.marionette.absolute_url('html5Page.html')
self.marionette.navigate(test_url)
@ -20,11 +34,12 @@ class ScreenshotTests(MarionetteTestCase):
self.assertEqual(GREEN_ELEMENT_BASE64,
self.marionette.screenshot(element=el, highlights=[el]))
def testWeCanTakeAScreenShotEntireCanvas(self):
def testWeCanTakeAScreenShotOfEntireCanvas(self):
test_url = self.marionette.absolute_url('html5Page.html')
self.marionette.navigate(test_url)
self.assertTrue('iVBORw0KGgo' in
self.marionette.screenshot())
# Check the base64 decoded string is a PNG file.
image = base64.decodestring(self.marionette.screenshot())
self.assertEqual(imghdr.what('', image), 'png')
def testWeCanTakeABinaryScreenShotOfAnElement(self):
test_url = self.marionette.absolute_url('html5Page.html')
@ -33,7 +48,7 @@ class ScreenshotTests(MarionetteTestCase):
binary_data = self.marionette.screenshot(element=el, format="binary")
self.assertEqual(RED_ELEMENT_BASE64,
base64.b64encode(binary_data))
def testNotAllowedScreenshotFormatRaiseValueError(self):
test_url = self.marionette.absolute_url('html5Page.html')
self.marionette.navigate(test_url)

View File

@ -2371,26 +2371,70 @@ MarionetteServerConnection.prototype = {
},
/**
* Takes a screenshot of a web element or the current frame.
* Takes a screenshot of a web element, current frame, or viewport.
*
* The screen capture is returned as a lossless PNG image encoded as
* a base 64 string. If the <code>id</code> argument is not null
* and refers to a present and visible web element's ID, the capture
* area will be limited to the bounding box of that element.
* Otherwise, the capture area will be the bounding box of the
* current frame.
* a base 64 string.
*
* @param id an optional reference to a web element
* @param highlights an optional list of web elements to draw a red
* box around in the returned capture
* @return PNG image encoded as base 64 string
*/
* If called in the content context, the <code>id</code> argument is not null
* and refers to a present and visible web element's ID, the capture area
* will be limited to the bounding box of that element. Otherwise, the
* capture area will be the bounding box of the current frame.
*
* If called in the chrome context, the screenshot will always represent the
* entire viewport.
*
* @param {string} [id] Reference to a web element.
* @param {string} [highlights] List of web elements to highlight.
* @return {string} PNG image encoded as base 64 string.
*/
takeScreenshot: function MDA_takeScreenshot(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("takeScreenshot",
if (this.context == "chrome") {
var win = this.getCurrentWindow();
var canvas = win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
var doc;
if (appName == "B2G") {
doc = win.document.body;
} else {
doc = win.document.getElementsByTagName('window')[0];
}
var docRect = doc.getBoundingClientRect();
var width = docRect.width;
var height = docRect.height;
// Convert width and height from CSS pixels (potentially fractional)
// to device pixels (integer).
var scale = win.devicePixelRatio;
canvas.setAttribute("width", Math.round(width * scale));
canvas.setAttribute("height", Math.round(height * scale));
var context = canvas.getContext("2d");
var flags;
if (appName == "B2G") {
flags =
context.DRAWWINDOW_DRAW_CARET |
context.DRAWWINDOW_DRAW_VIEW |
context.DRAWWINDOW_USE_WIDGET_LAYERS;
} else {
// Bug 1075168 - CanvasRenderingContext2D image is distorted
// when using certain flags in chrome context.
flags =
context.DRAWWINDOW_DRAW_VIEW |
context.DRAWWINDOW_USE_WIDGET_LAYERS;
}
context.scale(scale, scale);
context.drawWindow(win, 0, 0, width, height, "rgb(255,255,255)", flags);
var dataUrl = canvas.toDataURL("image/png", "");
var data = dataUrl.substring(dataUrl.indexOf(",") + 1);
this.sendResponse(data, this.command_id);
}
else {
this.sendAsync("takeScreenshot",
{id: aRequest.parameters.id,
highlights: aRequest.parameters.highlights},
this.command_id);
}
},
/**