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) |
Wladimir Palant
2016/01/07 17:02:58
This function is mostly what we had in sendReport.
|
+{ |
+ 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"); |
+} |