Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firefox Addon API for Taking Screenshot

I am looking for firefox addon api to take screenshot of visible area of document.

Chrome and Safari have api's to achieve this. And they are pretty fast. I could not find anything specific for firefox.

I found a workaround at How do I use the canvas drawWindow function in an addon created using the addon sdk? but this solution takes full page screenshot with scrolls including (hidden parts of document). There are 2 issues for this solution;

1- if page has long scroll, it takes long time to complete screenshot process. Because it is using canvas based drawing.

2- I would like to get screenshot of visible area of document, not whole document.

Is there any workaround for this?

Thanks.

like image 918
Teoman shipahi Avatar asked Aug 15 '14 18:08

Teoman shipahi


People also ask

How do I capture a screenshot in Firefox?

To take a screenshot in Firefox using the Firefox Screenshots feature: Right-clickHold down the control key while you click on an empty part of the page and select Take Screenshot. Alternatively, use the keyboard shortcut Ctrl + Shift + S .

What happened to Firefox screenshots?

Sorry for the non-obvious change, but in Firefox 88, Firefox Screenshot stopped being a "Page Action" that you could access from the ••• menu in the address bar. It now has an optional toolbar button ("Browser Action") in addition to right-click context menu integration and the keyboard shortcut (Ctrl+Shift+S).

How do you take a scrolling screenshot in Firefox?

Once you have the Firefox browser up and running, click on the three-lined menu at the top right. Go to More tools, followed by the Customize Toolbar option. Find the Screenshot icon and move it to the toolbar. Once the icon is where you want it to be, go to the page where you want to take the scrolling screenshot.


2 Answers

Using the SDK you can do something like this:

const { window: { document } } = require('sdk/addon/window');
const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');

const canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
document.documentElement.appendChild(canvas);

function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
  let contentWindow = getTabContentWindow(tab);

  let w = contentWindow.innerWidth;
  let h = contentWindow.innerHeight;
  let x = contentWindow.scrollX;
  let y = contentWindow.scrollY;

  canvas.width = w;
  canvas.height = h;

  let ctx = canvas.getContext('2d');

  ctx.drawWindow(contentWindow, x, y, w, h, '#000');
  return canvas.toDataURL();
}

That should takes only the visible area. By default, it grabs the active tab, but you can pass any other tab – because is designed as low level API it takes a native tab, however, not a SDK tab. You can put in a module and exports just the captureTab function.

Edit: e10s version

The code above is not currently compatible with Firefox with e10s available, as Ian Bicking noted in the comment. An easy way to workaround this issue, is create a temporary canvas in the same document and content process we want to capture the screenshot:

const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');

function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
  let contentWindow = getTabContentWindow(tab);
  let { document } = contentWindow;

  let w = contentWindow.innerWidth;
  let h = contentWindow.innerHeight;
  let x = contentWindow.scrollX;
  let y = contentWindow.scrollY;

  let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');

  canvas.width = w;
  canvas.height = h;

  let ctx = canvas.getContext('2d');

  ctx.drawWindow(contentWindow, x, y, w, h, '#000');

  let dataURL = canvas.toDataURL();

  canvas = null;

  return dataURL;
}

That works in both e10s and no-e10s FF version; the downside comparing to the previous one is creating a canvas every time we want to take a screenshot, but I think is acceptable.

like image 115
ZER0 Avatar answered Oct 05 '22 16:10

ZER0


Your assumption that taking a screenshot on Firefox with canvas is somehow slow is wrong.

I did a couple of screenshots and Firefox/canvas was faster than Chrome/captureVisibleTab.

Actually Firefox is better suited for as-fast-as-possible screenshots, since its canvas expose to privileged code the mozFetchAsStream method, allowing to bypass the actual bottleneck which is the base64 encoding of the image data.

Some numbers

  • Chrome: captureVisibleTab 200-205ms
  • Firefox: drawImage 20-25ms + toDataURL 125-130ms

The devtools screenshot command is a good example of how to capture just the visible part

In all fairness, to make a meaningful comparison one has to take into account whether Chrome's PNG encoder favors compression over speed. Still, this doesn't change the fact that Firefox's canvas is fine.

edit: OK, that base64 encoding remark is dumb, I don't know what I was thinking. Perhaps what I should write instead is that Firefox's canvas is not only fast but also versatile.

like image 34
paa Avatar answered Oct 05 '22 16:10

paa