1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-2017 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 {PrivateBrowsingUtils} = Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", {});
let {port} = require("messaging");
let {Utils} = require("utils");
port.on("collectData", onCollectData);
function onCollectData({outerWindowID, screenshotWidth}, sender)
{
let window = Services.wm.getOuterWindowWithId(outerWindowID);
if (window)
{
return Task.spawn(function*()
{
let data = {};
data.isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window);
data.opener = window.opener ? window.opener.location.href : null;
data.referrer = window.document.referrer;
data.frames = yield scanFrames(window);
data.screenshot = yield createScreenshot(window, screenshotWidth);
return data;
});
}
}
function scanFrames(window)
{
let frames = [];
for (let i = 0; i < window.frames.length; i++)
{
let frame = window.frames[i];
frames.push({
url: frame.location.href,
frames: scanFrames(frame)
});
}
return frames;
}
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 data = pixelData.data;
let mapping = [0x00, 0x55, 0xAA, 0xFF];
for (let i = 0; i < data.length; i++)
{
data[i] = mapping[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));
}
}
return pixelData;
}
|