Bug 1474006 - Work in progress
This code shows a way to retrieve the content of the tab from the parent process by using the message manager.
It requires additional work to merge this screenshot into the parent process one by using Canvas API,
as well as polish and a test.
It mostly highlights how to do the cross process communication via message managers in order to retrieve the missing piece of the screenshot.
I'm not planning to finish this patch, so anyone is free to pick this up.
MozReview-Commit-ID: 3Vm9xbr0Y0R
--- a/devtools/server/actors/webconsole/screenshot.js
+++ b/devtools/server/actors/webconsole/screenshot.js
@@ -44,16 +44,49 @@ function captureScreenshot(args, documen
return createScreenshotData(document, args);
}
/**
* This does the dirty work of creating a base64 string out of an
* area of the browser window
*/
function createScreenshotData(document, args) {
+ if (document.location.href.includes("browser.xul")) { // if we are in browser console codepath
+ // Get the message manager for the current tab
+ // document should be a reference to the topmost firefox window (I think)
+ // otherwise `Services.wm.getMostRecentWindow("navigator:browser")` returns it for sure
+ const { messageManager } = document.defaultView.gBrowser.selectedBrowser;
+ // you may already be used to such data + stringified function trick, we use that in ContentTask
+ // an important thing to know is that stringification doesn't like comments because it stringify without "\n"
+ // It is very hard to have comments in them, /* */ are supposed to work but I wasn't able to have them working here...
+ /* In a "frame script", you have access to some special globals like `content` */
+ /* which is the window object of the current content document */
+ /* More globals listed here: https://searchfox.org/mozilla-central/source/dom/chrome-webidl/MessageManager.webidl#464-492 */
+ messageManager.loadFrameScript("data:,new " + function () {
+ const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
+ const { createScreenshotData } = require("devtools/server/actors/webconsole/screenshot");
+ const onMessage = async (msg) => {
+ removeMessageListener("debug:screenshot-command", onMessage);
+
+ const data = await createScreenshotData(content.document, msg.data);
+ sendAsyncMessage("debug:screenshot-command", data);
+ };
+ addMessageListener("debug:screenshot-command", onMessage);
+ }, false /* false as we want to execute it only against the current document and not the next one to come */);
+ /* https://searchfox.org/mozilla-central/source/dom/chrome-webidl/MessageManager.webidl#391-400 */
+
+ return new Promise(resolve => {
+ const onMessage = (msg) => {
+ messageManager.removeMessageListener("debug:screenshot-command", onMessage);
+ resolve(msg.data);
+ };
+ messageManager.addMessageListener("debug:screenshot-command", onMessage);
+ messageManager.sendAsyncMessage("debug:screenshot-command", args);
+ });
+ }
const window = document.defaultView;
let left = 0;
let top = 0;
let width;
let height;
const currentX = window.scrollX;
const currentY = window.scrollY;
@@ -106,16 +139,17 @@ function createScreenshotData(document,
return Promise.resolve({
destinations: [],
data: data,
height: height,
width: width,
filename: filename,
});
}
+exports.createScreenshotData = createScreenshotData;
/**
* We may have a filename specified in args, or we might have to generate
* one.
*/
function getFilename(defaultName) {
// Create a name for the file if not present
if (defaultName) {