blob: 9192bcf10105e4a0a5c7e8e386a3aadceec7d94d [file] [log] [blame]
avm9996304def3e2016-11-27 22:53:05 +01001// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2// source code is governed by a BSD-style license that can be found in the
3// LICENSE file.
4
5var screenshot = {
6 tab: 0,
7 canvas: document.createElement("canvas"),
8 startX: 0,
9 startY: 0,
10 scrollX: 0,
11 scrollY: 0,
12 docHeight: 0,
13 docWidth: 0,
14 visibleWidth: 0,
15 visibleHeight: 0,
16 scrollXCount: 0,
17 scrollYCount: 0,
18 scrollBarX: 17,
19 scrollBarY: 17,
20 captureStatus: true,
21 screenshotName: null,
22
avm9996304def3e2016-11-27 22:53:05 +010023 /**
24 * Receive messages from content_script, and then decide what to do next
25 */
26 addMessageListener: function() {
27 chrome.extension.onMessage.addListener(function(request, sender, response) {
avm99963873bf6f2021-02-07 00:01:31 +010028 console.log(request);
avm9996304def3e2016-11-27 22:53:05 +010029 var obj = request;
avm9996304def3e2016-11-27 22:53:05 +010030 switch (obj.msg) {
avm9996304def3e2016-11-27 22:53:05 +010031 case 'capture_selected':
32 screenshot.captureSelected();
33 break;
34 case 'capture_window':
avm99963873bf6f2021-02-07 00:01:31 +010035 screenshot.captureWindow();
avm9996304def3e2016-11-27 22:53:05 +010036 break;
37 case 'capture_area':
avm99963873bf6f2021-02-07 00:01:31 +010038 screenshot.showSelectionArea();
avm9996304def3e2016-11-27 22:53:05 +010039 break;
40 case 'capture_webpage':
avm99963873bf6f2021-02-07 00:01:31 +010041 screenshot.captureWebpage();
avm9996304def3e2016-11-27 22:53:05 +010042 break;
43 }
44 });
45 },
46
47 /**
48 * Send the Message to content-script
49 */
50 sendMessage: function(message, callback) {
51 chrome.tabs.getSelected(null, function(tab) {
52 chrome.tabs.sendMessage(tab.id, message, callback);
53 });
54 },
55
56 showSelectionArea: function() {
57 screenshot.sendMessage({msg: 'show_selection_area'}, null);
58 },
59
60 captureWindow: function() {
61 screenshot.sendMessage({msg: 'capture_window'},
62 screenshot.onResponseVisibleSize);
63 },
64
65 captureSelected: function() {
66 screenshot.sendMessage({msg: 'capture_selected'},
67 screenshot.onResponseVisibleSize);
68 },
69
70 captureWebpage: function() {
71 screenshot.sendMessage({msg: 'scroll_init'},
72 screenshot.onResponseVisibleSize);
73 },
74
75 onResponseVisibleSize: function(response) {
76 switch (response.msg) {
77 case 'capture_window':
78 screenshot.captureVisible(response.docWidth, response.docHeight);
79 break;
80 case 'scroll_init_done':
81 screenshot.startX = response.startX,
82 screenshot.startY = response.startY,
83 screenshot.scrollX = response.scrollX,
84 screenshot.scrollY = response.scrollY,
85 screenshot.canvas.width = response.canvasWidth;
86 screenshot.canvas.height = response.canvasHeight;
87 screenshot.visibleHeight = response.visibleHeight,
88 screenshot.visibleWidth = response.visibleWidth,
89 screenshot.scrollXCount = response.scrollXCount;
90 screenshot.scrollYCount = response.scrollYCount;
91 screenshot.docWidth = response.docWidth;
92 screenshot.docHeight = response.docHeight;
93 screenshot.zoom = response.zoom;
Adrià Vilanova Martínezf4683cd2024-01-31 17:26:10 +010094 setTimeout("screenshot.captureAndScroll()", screenshot.captureDelayInMs());
avm9996304def3e2016-11-27 22:53:05 +010095 break;
96 case 'scroll_next_done':
97 screenshot.scrollXCount = response.scrollXCount;
98 screenshot.scrollYCount = response.scrollYCount;
Adrià Vilanova Martínezf4683cd2024-01-31 17:26:10 +010099 setTimeout("screenshot.captureAndScroll()", screenshot.captureDelayInMs());
avm9996304def3e2016-11-27 22:53:05 +0100100 break;
101 case 'scroll_finished':
102 screenshot.captureAndScrollDone();
103 break;
104 }
105 },
106
107 captureSpecialPage: function() {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100108 screenshot.getScreenshotQuality(function(formatParam) {
109 chrome.tabs.captureVisibleTab(
110 null, {format: formatParam, quality: 50}, function(data) {
111 var image = new Image();
112 image.onload = function() {
113 screenshot.canvas.width = image.width;
114 screenshot.canvas.height = image.height;
115 var context = screenshot.canvas.getContext("2d");
116 context.drawImage(image, 0, 0);
117 screenshot.postImage();
118 };
119 image.src = data;
120 });
avm9996304def3e2016-11-27 22:53:05 +0100121 });
122 },
123
124 captureScreenCallback: function(data) {
125 var image = new Image();
126 image.onload = function() {
127 screenshot.canvas.width = image.width;
128 screenshot.canvas.height = image.height;
129 var context = screenshot.canvas.getContext("2d");
130 context.drawImage(image, 0, 0);
131 screenshot.postImage();
132 };
133 image.src = "data:image/bmp;base64," + data;
134 },
135
136 /**
137 * Use drawImage method to slice parts of a source image and draw them to
138 * the canvas
139 */
140 capturePortion: function(x, y, width, height,
141 visibleWidth, visibleHeight, docWidth, docHeight) {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100142 screenshot.getScreenshotQuality(function(formatParam) {
143 chrome.tabs.captureVisibleTab(
144 null, {format: formatParam, quality: 50}, function(data) {
145 var image = new Image();
146 image.onload = function() {
147 var curHeight = image.width < docWidth ?
148 image.height - screenshot.scrollBarY : image.height;
149 var curWidth = image.height < docHeight ?
150 image.width - screenshot.scrollBarX : image.width;
151 var zoomX = curWidth / visibleWidth;
152 var zoomY = curHeight / visibleHeight;
153 screenshot.canvas.width = width * zoomX;
154 screenshot.canvas.height = height * zoomY;
155 var context = screenshot.canvas.getContext("2d");
156 context.drawImage(image, x * zoomX, y * zoomY, width * zoomX,
157 height * zoomY, 0, 0, width * zoomX, height * zoomY);
158 screenshot.postImage();
159 };
160 image.src = data;
161 });
avm9996304def3e2016-11-27 22:53:05 +0100162 });
163 },
164
165 captureVisible: function(docWidth, docHeight) {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100166 screenshot.getScreenshotQuality(function(formatParam) {
167 chrome.tabs.captureVisibleTab(
168 null, {format: formatParam, quality: 50}, function(data) {
169 var image = new Image();
170 image.onload = function() {
171 var width = image.height < docHeight ?
172 image.width - 17 : image.width;
173 var height = image.width < docWidth ?
174 image.height - 17 : image.height;
175 screenshot.canvas.width = width;
176 screenshot.canvas.height = height;
177 var context = screenshot.canvas.getContext("2d");
178 context.drawImage(image, 0, 0, width, height, 0, 0, width, height);
179 screenshot.postImage();
180 };
181 image.src = data;
182 });
avm9996304def3e2016-11-27 22:53:05 +0100183 });
184 },
185
186 /**
187 * Use the drawImage method to stitching images, and render to canvas
188 */
189 captureAndScroll: function() {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100190 screenshot.getScreenshotQuality(function(formatParam) {
191 chrome.tabs.captureVisibleTab(
192 null, {format: formatParam, quality: 50}, function(data) {
193 var image = new Image();
194 image.onload = function() {
195 var context = screenshot.canvas.getContext('2d');
196 var width = 0;
197 var height = 0;
avm9996304def3e2016-11-27 22:53:05 +0100198
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100199 // Get scroll bar's width.
200 screenshot.scrollBarY =
201 screenshot.visibleHeight < screenshot.docHeight ? 17 : 0;
202 screenshot.scrollBarX =
203 screenshot.visibleWidth < screenshot.docWidth ? 17 : 0;
avm9996304def3e2016-11-27 22:53:05 +0100204
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100205 // Get visible width and height of capture result.
206 var visibleWidth =
207 (image.width - screenshot.scrollBarY < screenshot.canvas.width ?
208 image.width - screenshot.scrollBarY : screenshot.canvas.width);
209 var visibleHeight =
210 (image.height - screenshot.scrollBarX < screenshot.canvas.height ?
211 image.height - screenshot.scrollBarX : screenshot.canvas.height);
avm9996304def3e2016-11-27 22:53:05 +0100212
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100213 // Get region capture start x coordinate.
214 var zoom = screenshot.zoom;
215 var x1 = screenshot.startX - Math.round(screenshot.scrollX * zoom);
216 var x2 = 0;
217 var y1 = screenshot.startY - Math.round(screenshot.scrollY * zoom);
218 var y2 = 0;
avm9996304def3e2016-11-27 22:53:05 +0100219
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100220 if ((screenshot.scrollYCount + 1) * visibleWidth >
221 screenshot.canvas.width) {
222 width = screenshot.canvas.width % visibleWidth;
223 x1 = (screenshot.scrollYCount + 1) * visibleWidth -
224 screenshot.canvas.width + screenshot.startX - screenshot.scrollX;
avm9996304def3e2016-11-27 22:53:05 +0100225 } else {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100226 width = visibleWidth;
avm9996304def3e2016-11-27 22:53:05 +0100227 }
228
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100229 if ((screenshot.scrollXCount + 1) * visibleHeight >
230 screenshot.canvas.height) {
231 height = screenshot.canvas.height % visibleHeight;
232 if ((screenshot.scrollXCount + 1) * visibleHeight +
233 screenshot.scrollY < screenshot.docHeight) {
234 y1 = 0;
235 } else {
236 y1 = (screenshot.scrollXCount + 1) * visibleHeight +
237 screenshot.scrollY - screenshot.docHeight;
238 }
239
240 } else {
241 height = visibleHeight;
242 }
243 x2 = screenshot.scrollYCount * visibleWidth;
244 y2 = screenshot.scrollXCount * visibleHeight;
245 context.drawImage(image, x1, y1, width, height, x2, y2, width, height);
246 screenshot.sendMessage({msg: 'scroll_next', visibleWidth: visibleWidth,
247 visibleHeight: visibleHeight}, screenshot.onResponseVisibleSize);
248 };
249 image.src = data;
250 });
avm9996304def3e2016-11-27 22:53:05 +0100251 });
252 },
253
254 captureAndScrollDone: function() {
255 screenshot.postImage();
256 },
257
258 /**
259 * Post the image to 'showimage.html'
260 */
261 postImage: function() {
262 chrome.tabs.getSelected(null, function(tab) {
263 screenshot.tab = tab;
264 });
265 var date = new Date();
266 screenshot.screenshotName = "Screenshot "+dateFormat(date, 'Y-m-d H.i.s');
267 chrome.tabs.create({'url': 'showimage.html'});
268 var popup = chrome.extension.getViews({type: 'popup'})[0];
269 if (popup)
270 popup.close();
271 },
272
273 isThisPlatform: function(operationSystem) {
274 return navigator.userAgent.toLowerCase().indexOf(operationSystem) > -1;
275 },
276
avm9996304def3e2016-11-27 22:53:05 +0100277 init: function() {
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100278 chrome.storage.local.get('screenshotQuality', values => {
279 var screenshotQuality = values.screenshotQuality;
280 if (screenshotQuality) return;
281
282 chrome.storage.local.set({
283 screenshotQuality: screenshotQuality || 'png',
284 });
285 });
avm9996304def3e2016-11-27 22:53:05 +0100286 screenshot.addMessageListener();
Adrià Vilanova Martínezf4683cd2024-01-31 17:26:10 +0100287 },
288
289 captureDelayInMs: function() {
290 var maxCallsPerSecond = chrome?.tabs?.MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND;
291 if (!maxCallsPerSecond) return 100;
292
293 return Math.ceil(1000/maxCallsPerSecond) + 10;
294 },
Adrià Vilanova Martínezce99ce82024-02-07 19:34:38 +0100295
296 getScreenshotQuality: function(callback) {
297 chrome.storage.local.get('screenshotQuality', function(values) {
298 callback(values.screenshotQuality || 'png');
299 });
300 },
avm9996304def3e2016-11-27 22:53:05 +0100301};
302
303screenshot.init();