Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Side by Side Diff: native_client_sdk/src/build_tools/screenshot_extension/screenshot.js

Issue 23458018: [NaCl SDK] Screen capture extension for use with SDK visual testing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix nits Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « native_client_sdk/src/build_tools/screenshot_extension/manifest.json ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var screenshot = (function() {
6 /** A map of id to pending callback. */
7 var callbackMap = {};
8
9 /** An array of queued requests. They will all be executed when the
10 * background page injects screen code into this page
11 */
12 var queuedRequests = [];
13
14 /** The next id to assign. Used for mapping id to callback. */
15 var nextId = 0;
16
17 /** This is set to true when the background page injects screenshot code into
18 * this page
19 */
20 var extensionInjected = false;
21
22 /** Generate a new id, which maps to the given callbacks.
23 *
24 * @param {function(string)} onSuccess
25 * @param {function(string)} onError
26 * @return {number} The id.
27 */
28 function addCallback(onSuccess, onError) {
29 var id = nextId++;
30 callbackMap[id] = [onSuccess, onError];
31 return id;
32 }
33
34 /** Call the callback mapped to |id|.
35 *
36 * @param {number} id
37 * @param {boolean} success true to call the success callback, false for the
38 * error callback.
39 * @param {...} A variable number of arguments to pass to the callback.
40 */
41 function callCallback(id, success) {
42 var callbacks = callbackMap[id];
43 if (!callbacks) {
44 console.log('Unknown id: ' + id);
45 return;
46 }
47
48 delete callbackMap[id];
49 var callback = success ? callbacks[0] : callbacks[1];
50 if (callback)
51 callback(Array.prototype.slice.call(arguments, 2));
52 }
53
54 /** Post a message to take a screenshot.
55 *
56 * This message will be enqueued if the extension has not yet injected the
57 * screenshot code.
58 *
59 * @param {number} id An id to associate with this request. When the
60 * screenshot is complete, the background page will return
61 * a result with this id.
62 */
63 function postScreenshotMessage(id) {
64 if (!extensionInjected) {
65 queuedRequests.push(id);
66 return;
67 }
68
69 window.postMessage({id: id, target: 'background'}, '*');
70 }
71
72 /** Post all queued screenshot requests.
73 *
74 * Should only be called after the screenshot code has been injected by the
75 * background page.
76 */
77 function postQueuedRequests() {
78 for (var i = 0; i < queuedRequests.length; ++i) {
79 var id = queuedRequests[i];
80 postScreenshotMessage(id);
81 }
82 queuedRequests = [];
83 }
84
85 /** Predicate whether the extension has injected code yet.
86 *
87 * @return {boolean}
88 */
89 function isInjected() {
90 // NOTE: This attribute name must match the one in injected.js.
91 return document.body &&
92 document.body.getAttribute('screenshot_extension_injected');
93 }
94
95 /** Start an interval that polls for when the extension has injected code
96 * into this page.
97 *
98 * The extension first adds a postMessage handler to listen for requests,
99 * then adds an attribute to the body element. If we see this attribute, we
100 * know the listener is ready.
101 */
102 function pollForInjection() {
103 var intervalId = window.setInterval(function() {
104 if (!isInjected())
105 return;
106
107 // Finally injected!
108 window.clearInterval(intervalId);
109 extensionInjected = true;
110 postQueuedRequests();
111 }, 100); // Every 100ms.
112 }
113
114 // Add a postMessage listener for when the injected code returns a result
115 // from the background page.
116 window.addEventListener('message', function(event) {
117 // If the message comes from another window, or is outbound (i.e.
118 // event.data.target === 'background'), ignore it.
119 if (event.source !== window || event.data.target !== 'page')
120 return;
121
122 var success = event.data.error === undefined;
123 callCallback(event.data.id, success, event.data.data);
124 }, false);
125
126 if (isInjected())
127 extensionInjected = true;
128 else
129 pollForInjection();
130
131 // Public functions.
132
133 /** Capture the current visible area of the tab as a PNG.
134 *
135 * If the request succeeds, |onSuccess| will be called with one parameter:
136 * the image encoded as a data URL.
137 *
138 * If the request fails, |onError| will be called with one parameter: an
139 * informational error message.
140 *
141 * @param {function(string)} onSuccess The success callback.
142 * @param {function(string)} onError The error callback.
143 */
144 function captureTab(onSuccess, onError) {
145 var id = addCallback(onSuccess, onError);
146 postScreenshotMessage(id);
147 }
148
149 /** Capture the current visible area of a given element as a PNG.
150 *
151 * If the request succeeds, |onSuccess| will be called with one parameter:
152 * the image encoded as a data URL.
153 *
154 * If the request fails, |onError| will be called with one parameter: an
155 * informational error message.
156 *
157 * @param {Element} element The element to capture.
158 * @param {function(string)} onSuccess The success callback.
159 * @param {function(string)} onError The error callback.
160 */
161 function captureElement(element, onSuccess, onError) {
162 var elementRect = element.getBoundingClientRect();
163 var elX = elementRect.left;
164 var elY = elementRect.top;
165 var elW = elementRect.width;
166 var elH = elementRect.height;
167
168 function onScreenCaptured(dataURL) {
169 // Create a canvas of the correct size.
170 var canvasEl = document.createElement('canvas');
171 canvasEl.setAttribute('width', elW);
172 canvasEl.setAttribute('height', elH);
173 var ctx = canvasEl.getContext('2d');
174
175 var imgEl = new Image();
176 imgEl.onload = function() {
177 // Draw only the element region of the image.
178 ctx.drawImage(imgEl, elX, elY, elW, elH, 0, 0, elW, elH);
179
180 // Extract the canvas to a new data URL, and return it via the callback.
181 onSuccess(canvasEl.toDataURL());
182 };
183
184 // Load the full screenshot into imgEl.
185 imgEl.src = dataURL;
186 }
187
188 var id = addCallback(onScreenCaptured, onError);
189 postScreenshotMessage(id);
190 }
191
192 return {
193 captureTab: captureTab,
194 captureElement: captureElement
195 };
196 })();
OLDNEW
« no previous file with comments | « native_client_sdk/src/build_tools/screenshot_extension/manifest.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698