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

Side by Side Diff: chrome/test/data/extensions/api_test/tab_capture/offscreen_test_harness.js

Issue 1221483002: New tabCapture.captureOffscreenTab API, initially for Presentation API 1UA mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mostly revert to Patch Set 6, plus minor tweaks. [and REBASE] Created 5 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2015 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 // This file contains a test harness for testing the behavior of pages running
6 // inside off-screen tabs:
7 //
8 // 1. It provides a simple way to formulate a data URI containing a full HTML
9 // document that executes arbitrary script. The arbitrary script running
10 // in the off-screen tab calls setFillColor() to expose its current state
11 // by rendering a color fill. In addition, the off-screen tab continuously
12 // paints changes that force the tab capture implementation to continuously
13 // capture new video frames.
14 //
15 // 2. In the extension's JavaScript context, a waitAnForExpectedColor()
16 // function is provided to sample the video frames of the captured
17 // off-screen tab until the center pixel contains one of the colors in a
18 // set of expected colors.
19
20 // Width/Height of off-screen tab, rendered content, and captured content.
21 var width = 160;
22 var height = 120;
23
24 // Capture frame rate.
25 var frameRate = 8;
26
27 // Return a full HTML document that executes the |script|. The script calls
28 // setFillColor() to expose changes to its internal state.
29 function makeOffscreenTabTestDocument(script) {
30 return '\
31 <html><body style="background-color:black; margin:0; padding:0;"></body>\n\
32 <script>\n\
33 var redColor = [255, 0, 0];\n\
34 var greenColor = [0, 255, 0];\n\
35 var blueColor = [0, 0, 255];\n\
36 \n\
37 var fillColor = [0, 0, 0];\n\
38 function setFillColor(color) {\n\
39 fillColor = color;\n\
40 }\n\
41 \n\
42 var debugMessage = "";\n\
43 function setDebugMessage(msg) {\n\
44 debugMessage = msg;\n\
45 }\n\
46 \n\
47 function updateTestPattern() {\n\
48 if (!this.canvas) {\n\
49 this.canvas = document.createElement("canvas");\n\
50 this.canvas.width = ' + width + ';\n\
51 this.canvas.height = ' + height + ';\n\
52 this.canvas.style.position = "absolute";\n\
53 this.canvas.style.top = "0px";\n\
54 this.canvas.style.left = "0px";\n\
55 this.canvas.style.width = "100%";\n\
56 this.canvas.style.height = "100%";\n\
57 document.body.appendChild(this.canvas);\n\
58 }\n\
59 var context = this.canvas.getContext("2d");\n\
60 // Fill with solid color.\n\
61 context.fillStyle = "rgb(" + fillColor + ")";\n\
62 context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\
63 // Draw the circle that moves around the page.\n\
64 var inverseColor =\n\
65 [255 - fillColor[0], 255 - fillColor[1], 255 - fillColor[2]];\n\
66 if (debugMessage) {\n\
67 context.fillStyle = "rgb(" + inverseColor + ")";\n\
68 context.font = "xx-small monospace";\n\
69 context.fillText(debugMessage, 0, 0);\n\
70 }\n\
71 context.fillStyle = "rgba(" + inverseColor + ", 0.5)";\n\
72 context.beginPath();\n\
73 if (!this.frameNumber) {\n\
74 this.frameNumber = 1;\n\
75 } else {\n\
76 ++this.frameNumber;\n\
77 }\n\
78 var i = this.frameNumber % 200;\n\
79 var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);\n\
80 var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;\n\
81 var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;\n\
82 context.arc(x, y, 16, 0, 2 * Math.PI, false);\n\
83 context.closePath();\n\
84 context.fill();\n\
85 }\n\
86 \n\
87 function renderTestPatternLoop() {\n\
88 updateTestPattern();\n\
89 requestAnimationFrame(renderTestPatternLoop);\n\
90 }\n\
91 renderTestPatternLoop();\n\
92 \n' +
93 script + '\n\
94 </script></html>';
95 }
96
97 // Return the given |html| document as an encoded data URI.
98 function makeDataUriFromDocument(html) {
99 return 'data:text/html;charset=UTF-8,' + encodeURIComponent(html);
100 }
101
102 // Returns capture options for starting the off-screen tab.
103 function getCaptureOptions() {
104 return {
105 video: true,
106 audio: false,
107 videoConstraints: {
108 mandatory: {
109 minWidth: width,
110 minHeight: height,
111 maxWidth: width,
112 maxHeight: height,
113 maxFrameRate: frameRate,
114 }
115 }
116 };
117 }
118
119 // Samples the video frames from a capture |stream|, testing the color of the
120 // center pixel. Once the pixel matches one of the colors in |expectedColors|,
121 // run |callback| with the index of the matched color. |colorDeviation| is used
122 // to imprecisely match colors.
123 function waitForAnExpectedColor(
124 stream, expectedColors, colorDeviation, callback) {
125 chrome.test.assertTrue(!!stream);
126 chrome.test.assertTrue(expectedColors.length > 0);
127 chrome.test.assertTrue(!!callback);
128
129 var video = document.getElementById('video');
130 chrome.test.assertTrue(!!video);
131
132 // If not yet done, plug the LocalMediaStream into the video element.
133 if (!this.stream || this.stream != stream) {
134 this.stream = stream;
135 video.src = URL.createObjectURL(stream);
136 video.play();
137 }
138
139 // Create a canvas to sample frames from the video element.
140 if (!this.canvas) {
141 this.canvas = document.createElement("canvas");
142 this.canvas.width = width;
143 this.canvas.height = height;
144 }
145
146 // Only bother examining a video frame if the video timestamp has advanced.
147 var currentVideoTimestamp = video.currentTime;
148 if (!this.lastVideoTimestamp ||
149 this.lastVideoTimestamp < currentVideoTimestamp) {
150 this.lastVideoTimestamp = currentVideoTimestamp;
151
152 // Grab a snapshot of the center pixel of the video.
153 var ctx = this.canvas.getContext("2d");
154 ctx.drawImage(video, 0, 0, width, height);
155 var imageData = ctx.getImageData(width / 2, height / 2, 1, 1);
156 var pixel = [imageData.data[0], imageData.data[1], imageData.data[2]];
157
158 // Does the pixel match one of the expected colors?
159 for (var i = 0, end = expectedColors.length; i < end; ++i) {
160 var color = expectedColors[i];
161 if (Math.abs(pixel[0] - color[0]) <= colorDeviation &&
162 Math.abs(pixel[1] - color[1]) <= colorDeviation &&
163 Math.abs(pixel[2] - color[2]) <= colorDeviation) {
164 console.debug("Observed expected color RGB(" + color +
165 ") in the video as RGB(" + pixel + ")");
166 setTimeout(function () { callback(i); }, 0);
167 return;
168 }
169 }
170 }
171
172 // At this point, an expected color has not been observed. Schedule another
173 // check after a short delay.
174 setTimeout(
175 function () {
176 waitForAnExpectedColor(stream, expectedColors, colorDeviation, callback);
177 },
178 1000 / frameRate);
179 }
180
181 // Stops all the tracks in a MediaStream.
182 function stopAllTracks(stream) {
183 var tracks = stream.getTracks();
184 for (var i = 0, end = tracks.length; i < end; ++i) {
185 tracks[i].stop();
186 }
187 chrome.test.assertFalse(stream.active);
188 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698