| OLD | NEW | 
| (Empty) |  | 
 |    1 /* | 
 |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
 |    3  * Copyright (C) 2006-2015 Eyeo GmbH | 
 |    4  * | 
 |    5  * Adblock Plus is free software: you can redistribute it and/or modify | 
 |    6  * it under the terms of the GNU General Public License version 3 as | 
 |    7  * published by the Free Software Foundation. | 
 |    8  * | 
 |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
 |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |   12  * GNU General Public License for more details. | 
 |   13  * | 
 |   14  * You should have received a copy of the GNU General Public License | 
 |   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
 |   16  */ | 
 |   17  | 
 |   18 /** | 
 |   19  * @fileOverview Collects some data for a content window, to be attached to | 
 |   20  * issue reports. | 
 |   21  */ | 
 |   22  | 
 |   23 "use strict"; | 
 |   24  | 
 |   25 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 
 |   26 let {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); | 
 |   27  | 
 |   28 let {Utils} = require("utils"); | 
 |   29  | 
 |   30 addMessageListener("AdblockPlus:CollectData", onCollectData); | 
 |   31 onShutdown.add(() => { | 
 |   32   removeMessageListener("AdblockPlus:CollectData", onCollectData); | 
 |   33 }); | 
 |   34  | 
 |   35 function onCollectData(message) | 
 |   36 { | 
 |   37   let {outerWindowID, screenshotWidth, responseID} = message.data; | 
 |   38  | 
 |   39   function success(data) | 
 |   40   { | 
 |   41     sendAsyncMessage("AdblockPlus:CollectDataResponse", { | 
 |   42       responseID, | 
 |   43       data | 
 |   44     }); | 
 |   45   } | 
 |   46  | 
 |   47   function error(e) | 
 |   48   { | 
 |   49     Cu.reportError(e); | 
 |   50     sendAsyncMessage("AdblockPlus:CollectDataResponse", { | 
 |   51       responseID, | 
 |   52       data: null | 
 |   53     }); | 
 |   54   } | 
 |   55  | 
 |   56   let window = Services.wm.getOuterWindowWithId(outerWindowID); | 
 |   57   if (window) | 
 |   58   { | 
 |   59     Task.spawn(function*() | 
 |   60     { | 
 |   61       let data = {}; | 
 |   62       data.screenshot = yield createScreenshot(window, screenshotWidth); | 
 |   63       return data; | 
 |   64     }).then(success, error); | 
 |   65   } | 
 |   66 } | 
 |   67  | 
 |   68 function* createScreenshot(window, screenshotWidth) | 
 |   69 { | 
 |   70   let canvas = window.document.createElement("canvas"); | 
 |   71   canvas.width = screenshotWidth; | 
 |   72  | 
 |   73   let context = canvas.getContext("2d"); | 
 |   74   let wndWidth = window.document.documentElement.scrollWidth; | 
 |   75   let wndHeight = window.document.documentElement.scrollHeight; | 
 |   76  | 
 |   77   // Copy scaled screenshot of the webpage, according to the specified width. | 
 |   78  | 
 |   79   // Gecko doesn't like sizes more than 64k, restrict to 30k to be on the safe s
     ide. | 
 |   80   // Also, make sure height is at most five times the width to keep image size d
     own. | 
 |   81   let copyWidth = Math.min(wndWidth, 30000); | 
 |   82   let copyHeight = Math.min(wndHeight, 30000, copyWidth * 5); | 
 |   83   let copyX = Math.max(Math.min(window.scrollX - copyWidth / 2, wndWidth - copyW
     idth), 0); | 
 |   84   let copyY = Math.max(Math.min(window.scrollY - copyHeight / 2, wndHeight - cop
     yHeight), 0); | 
 |   85  | 
 |   86   let scalingFactor = screenshotWidth / copyWidth; | 
 |   87   canvas.height = copyHeight * scalingFactor; | 
 |   88  | 
 |   89   context.save(); | 
 |   90   context.scale(scalingFactor, scalingFactor); | 
 |   91   context.drawWindow(window, copyX, copyY, copyWidth, copyHeight, "rgb(255,255,2
     55)"); | 
 |   92   context.restore(); | 
 |   93  | 
 |   94   // Reduce colors | 
 |   95   let pixelData = context.getImageData(0, 0, canvas.width, canvas.height); | 
 |   96   let max = pixelData.width * pixelData.height * 4; | 
 |   97   let mapping = [0x00,  0x55,  0xAA,  0xFF]; | 
 |   98   for (let i = 0; i < max; i++) | 
 |   99   { | 
 |  100     pixelData.data[i] = mapping[pixelData.data[i] >> 6]; | 
 |  101  | 
 |  102     if (i % 5000 == 0) | 
 |  103     { | 
 |  104       // Take a break every 5000 bytes to prevent browser hangs | 
 |  105       yield new Promise((resolve, reject) => Utils.runAsync(resolve)); | 
 |  106     } | 
 |  107   } | 
 |  108  | 
 |  109   // Convert the data into an image URL | 
 |  110   context.putImageData(pixelData, 0, 0); | 
 |  111   return canvas.toDataURL("image/png"); | 
 |  112 } | 
| OLD | NEW |