Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/child/dataCollector.js

Issue 29333297: Issue 3375 - Issue reporter: move screenshot creation into the content process (Closed)
Patch Set: Made sure screenshotDataCollector is always initialized Created Jan. 7, 2016, 6:57 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/content/ui/sendReport.js ('k') | lib/child/main.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/child/dataCollector.js
===================================================================
new file mode 100644
--- /dev/null
+++ b/lib/child/dataCollector.js
@@ -0,0 +1,112 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @fileOverview Collects some data for a content window, to be attached to
+ * issue reports.
+ */
+
+"use strict";
+
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+
+let {Utils} = require("utils");
+
+addMessageListener("AdblockPlus:CollectData", onCollectData);
+onShutdown.add(() => {
+ removeMessageListener("AdblockPlus:CollectData", onCollectData);
+});
+
+function onCollectData(message)
+{
+ let {outerWindowID, screenshotWidth, responseID} = message.data;
+
+ function success(data)
+ {
+ sendAsyncMessage("AdblockPlus:CollectDataResponse", {
+ responseID,
+ data
+ });
+ }
+
+ function error(e)
+ {
+ Cu.reportError(e);
+ sendAsyncMessage("AdblockPlus:CollectDataResponse", {
+ responseID,
+ data: null
+ });
+ }
+
+ let window = Services.wm.getOuterWindowWithId(outerWindowID);
+ if (window)
+ {
+ Task.spawn(function*()
+ {
+ let data = {};
+ data.screenshot = yield createScreenshot(window, screenshotWidth);
+ return data;
+ }).then(success, error);
+ }
+}
+
+function* createScreenshot(window, screenshotWidth)
+{
+ let canvas = window.document.createElement("canvas");
+ canvas.width = screenshotWidth;
+
+ let context = canvas.getContext("2d");
+ let wndWidth = window.document.documentElement.scrollWidth;
+ let wndHeight = window.document.documentElement.scrollHeight;
+
+ // Copy scaled screenshot of the webpage, according to the specified width.
+
+ // Gecko doesn't like sizes more than 64k, restrict to 30k to be on the safe side.
+ // Also, make sure height is at most five times the width to keep image size down.
+ let copyWidth = Math.min(wndWidth, 30000);
+ let copyHeight = Math.min(wndHeight, 30000, copyWidth * 5);
+ let copyX = Math.max(Math.min(window.scrollX - copyWidth / 2, wndWidth - copyWidth), 0);
+ let copyY = Math.max(Math.min(window.scrollY - copyHeight / 2, wndHeight - copyHeight), 0);
+
+ let scalingFactor = screenshotWidth / copyWidth;
+ canvas.height = copyHeight * scalingFactor;
+
+ context.save();
+ context.scale(scalingFactor, scalingFactor);
+ context.drawWindow(window, copyX, copyY, copyWidth, copyHeight, "rgb(255,255,255)");
+ context.restore();
+
+ // Reduce colors
+ let pixelData = context.getImageData(0, 0, canvas.width, canvas.height);
+ let max = pixelData.width * pixelData.height * 4;
+ let mapping = [0x00, 0x55, 0xAA, 0xFF];
+ for (let i = 0; i < max; i++)
+ {
+ pixelData.data[i] = mapping[pixelData.data[i] >> 6];
+
+ if (i % 5000 == 0)
+ {
+ // Take a break every 5000 bytes to prevent browser hangs
+ yield new Promise((resolve, reject) => Utils.runAsync(resolve));
+ }
+ }
+
+ // Convert the data into an image URL
+ context.putImageData(pixelData, 0, 0);
+ return canvas.toDataURL("image/png");
+}
« no previous file with comments | « chrome/content/ui/sendReport.js ('k') | lib/child/main.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld