mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 810259: Adding support for getting screenshot from Marionette; r=mdas
This commit is contained in:
parent
07aab17c73
commit
c93c8514aa
@ -498,3 +498,8 @@ class Marionette(object):
|
||||
@property
|
||||
def application_cache(self):
|
||||
return ApplicationCache(self)
|
||||
|
||||
def screenshot(self, element=None, highlights=None):
|
||||
if element is not None:
|
||||
element = element.id
|
||||
return self._send_message("screenShot", 'value', element=element, highlights=highlights)
|
||||
|
@ -0,0 +1,18 @@
|
||||
from marionette_test import MarionetteTestCase
|
||||
|
||||
|
||||
class ScreenshotTests(MarionetteTestCase):
|
||||
|
||||
def testWeCanTakeAScreenShotOfAnElement(self):
|
||||
test_url = self.marionette.absolute_url('html5Page.html')
|
||||
self.marionette.navigate(test_url)
|
||||
el = self.marionette.find_element('id', 'red')
|
||||
self.assertEqual('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAVUlEQVRoge3PsQ0AIAzAsI78fzBwBhHykD2ePev80LweAAGJB1ILpBZILZBaILVAaoHUAqkFUgukFkgtkFogtUBqgdQCqQVSC6QWSC2QWiC1QGp9A7ma+7nyXgOpzQAAAABJRU5ErkJggg==',
|
||||
self.marionette.screenshot(element=el))
|
||||
|
||||
def testWeCanTakeAScreenShotEntireCanvas(self):
|
||||
test_url = self.marionette.absolute_url('html5Page.html')
|
||||
self.marionette.navigate(test_url)
|
||||
self.assertTrue('data:image/png;base64,iVBORw0KGgo' in
|
||||
self.marionette.screenshot())
|
||||
|
@ -51,4 +51,4 @@ b2g = false
|
||||
b2g = false
|
||||
|
||||
[test_appcache.py]
|
||||
|
||||
[test_screenshot.py]
|
||||
|
@ -1594,6 +1594,15 @@ MarionetteDriverActor.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes a screenshot of a DOM node. If there is no node given a screenshot
|
||||
* of the window will be taken.
|
||||
*/
|
||||
screenShot: function MDA_saveScreenshot(aRequest) {
|
||||
this.sendAsync("screenShot", {element: aRequest.element,
|
||||
highlights: aRequest.highlights});
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to convert an outerWindowID into a UID that Marionette
|
||||
* tracks.
|
||||
@ -1771,7 +1780,8 @@ MarionetteDriverActor.prototype.requestTypes = {
|
||||
"importScript": MarionetteDriverActor.prototype.importScript,
|
||||
"getAppCacheStatus": MarionetteDriverActor.prototype.getAppCacheStatus,
|
||||
"closeWindow": MarionetteDriverActor.prototype.closeWindow,
|
||||
"setTestName": MarionetteDriverActor.prototype.setTestName
|
||||
"setTestName": MarionetteDriverActor.prototype.setTestName,
|
||||
"screenShot": MarionetteDriverActor.prototype.screenShot
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -120,6 +120,7 @@ function startListeners() {
|
||||
addMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus);
|
||||
addMessageListenerId("Marionette:setTestName", setTestName);
|
||||
addMessageListenerId("Marionette:setState", setState);
|
||||
addMessageListenerId("Marionette:screenShot", screenShot);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,6 +201,7 @@ function deleteSession(msg) {
|
||||
removeMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus);
|
||||
removeMessageListenerId("Marionette:setTestName", setTestName);
|
||||
removeMessageListenerId("Marionette:setState", setState);
|
||||
removeMessageListenerId("Marionette:screenShot", screenShot);
|
||||
this.elementManager.reset();
|
||||
// reset frame to the top-most frame
|
||||
curWindow = content;
|
||||
@ -944,6 +946,88 @@ function importScript(msg) {
|
||||
sendOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a screenshot and returns a Base64 string
|
||||
*/
|
||||
function screenShot(msg) {
|
||||
let node = null;
|
||||
if (msg.json.element) {
|
||||
try {
|
||||
node = elementManager.getKnownElement(msg.json.element, curWindow)
|
||||
}
|
||||
catch (e) {
|
||||
sendResponse(e.message, e.code, e.stack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
node = curWindow;
|
||||
}
|
||||
let highlights = msg.json.highlights;
|
||||
|
||||
var document = curWindow.document;
|
||||
var rect, win, width, height, left, top, needsOffset;
|
||||
// node can be either a window or an arbitrary DOM node
|
||||
if (node == curWindow) {
|
||||
// node is a window
|
||||
win = node;
|
||||
width = win.innerWidth;
|
||||
height = win.innerHeight;
|
||||
top = 0;
|
||||
left = 0;
|
||||
// offset needed for highlights to take 'outerHeight' of window into account
|
||||
needsOffset = true;
|
||||
}
|
||||
else {
|
||||
// node is an arbitrary DOM node
|
||||
win = node.ownerDocument.defaultView;
|
||||
rect = node.getBoundingClientRect();
|
||||
width = rect.width;
|
||||
height = rect.height;
|
||||
top = rect.top;
|
||||
left = rect.left;
|
||||
// offset for highlights not needed as they will be relative to this node
|
||||
needsOffset = false;
|
||||
}
|
||||
|
||||
var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
var ctx = canvas.getContext("2d");
|
||||
// Draws the DOM contents of the window to the canvas
|
||||
ctx.drawWindow(win, left, top, width, height, 'rgb(255,255,255)');
|
||||
|
||||
// This section is for drawing a red rectangle around each element passed in via the highlights array
|
||||
if (highlights) {
|
||||
ctx.lineWidth = "2";
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.save();
|
||||
|
||||
for (var i = 0; i < highlights.length; ++i) {
|
||||
var elem = highlights[i];
|
||||
rect = elem.getBoundingClientRect();
|
||||
|
||||
var offsetY = 0, offsetX = 0;
|
||||
if (needsOffset) {
|
||||
var offset = getChromeOffset(elem);
|
||||
offsetX = offset.x;
|
||||
offsetY = offset.y;
|
||||
} else {
|
||||
// Don't need to offset the window chrome, just make relative to containing node
|
||||
offsetY = -top;
|
||||
offsetX = -left;
|
||||
}
|
||||
|
||||
// Draw the rectangle
|
||||
ctx.strokeRect(rect.left + offsetX, rect.top + offsetY, rect.width, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the Base64 String back to the client bindings and they can manage
|
||||
// saving the file to disk if it is required
|
||||
sendResponse({value:canvas.toDataURL("image/png","")});
|
||||
}
|
||||
|
||||
//call register self when we get loaded
|
||||
registerSelf();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user