- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / tab_capture / experimental / end_to_end.js
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 // The tests here cover the end-to-end functionality of tab capturing and
6 // playback as video.  The page generates a test signal (a full color fill), and
7 // the rendering output of the tab is captured into a LocalMediaStream.  Then,
8 // the LocalMediaStream is plugged into a video element for playback, and a
9 // canvas is used to examine the frames of the video for expected content.
10 //
11 // A previous version of this test used a polling scheme and two separate tabs
12 // with very little control logic.  This setup resulted in flakiness, as there
13 // were numerous issues that could cause the test to time out.  This new version
14 // uses an entirely event-based scheme, which ensures everything is synchronized
15 // as the test advances through its stages.
16
17
18 // Video needs to be global, or the big bad garbage collector will come and
19 // huff and puff it all away.
20 var video = null;
21
22 function TestStream(stream) {
23   chrome.test.assertTrue(stream != null);
24
25   // The test source is a color fill of red, then green, then blue.
26   var colors = [ [ 255, 0, 0 ], [ 0, 255, 0 ], [ 0, 0, 255 ] ];
27   var curColorIdx = 0;
28
29   // Create video and canvas elements, but no need to append them to the
30   // DOM.
31   video = document.createElement("video");
32   video.width = 64;
33   video.height = 48;
34   video.addEventListener("error", chrome.test.fail);
35   var canvas = document.createElement("canvas");
36
37   function updateTestDocument() {
38     document.body.style.backgroundColor =
39         "rgb(" + colors[curColorIdx] + ")";
40
41     // Important: Blink the testing message so that the capture pipeline
42     // will observe drawing updates and continue to produce video frames.
43     var message = document.getElementById("message");
44     if (!message.blinkInterval) {
45       message.innerHTML = "Testing...";
46       message.blinkInterval = setInterval(function toggleVisibility() {
47         message.style.visibility =
48             message.style.visibility == "hidden" ? "visible" : "hidden";
49       }, 500);
50     }
51   }
52
53   function checkVideoForFillColor(event) {
54     var curColor = colors[curColorIdx];
55     var width = video.videoWidth;
56     var height = video.videoHeight;
57
58     // Grab a snapshot of the center pixel of the video.
59     canvas.width = width;
60     canvas.height = height;
61     var ctx = canvas.getContext("2d");
62     ctx.drawImage(video, 0, 0, width, height);
63     var imageData = ctx.getImageData(width / 2, height / 2, 1, 1);
64     var pixel = [ imageData.data[0], imageData.data[1], imageData.data[2] ];
65
66     // Check whether the pixel is of the expected color value, and proceed
67     // to the next test stage when a match is encountered.  Note: The video
68     // encode/decode process loses color accuracy, which is accounted for
69     // here.
70     if (Math.abs(pixel[0] - curColor[0]) < 10 &&
71         Math.abs(pixel[1] - curColor[1]) < 10 &&
72         Math.abs(pixel[2] - curColor[2]) < 10) {
73       console.debug("Observed expected color RGB(" + curColor +
74           ") in the video as RGB(" + pixel + ")");
75       // Continue with the next color; or, if there are no more colors,
76       // consider the test successful.
77       if (curColorIdx + 1 < colors.length) {
78         ++curColorIdx;
79         updateTestDocument();
80       } else {
81         video.removeEventListener("timeupdate", checkVideoForFillColor);
82         stream.stop();
83         chrome.test.succeed();
84       }
85     }
86   }
87   // Play the LocalMediaStream in the video element.
88   video.src = webkitURL.createObjectURL(stream);
89   video.play();
90
91   // Kick it off.
92   updateTestDocument();
93   video.addEventListener("timeupdate", checkVideoForFillColor);
94 }
95
96 // Set up a WebRTC connection and pipe |stream| through it.
97 // Call TestStream with the new stream when done.
98 function testThroughWebRTC(stream) {
99   var sender = new webkitRTCPeerConnection(null);
100   var receiver = new webkitRTCPeerConnection(null);
101   sender.onicecandidate = function (event) {
102     if (event.candidate) {
103       receiver.addIceCandidate(new RTCIceCandidate(event.candidate));
104     }
105   };
106   receiver.onicecandidate = function (event) {
107     if (event.candidate) {
108       sender.addIceCandidate(new RTCIceCandidate(event.candidate));
109     }
110   };
111   receiver.onaddstream = function (event) {
112     TestStream(event.stream);
113   };
114   sender.addStream(stream);
115   sender.createOffer(function (sender_description) {
116     sender.setLocalDescription(sender_description);
117     receiver.setRemoteDescription(sender_description);
118     receiver.createAnswer(function (receiver_description) {
119       receiver.setLocalDescription(receiver_description);
120       sender.setRemoteDescription(receiver_description);
121     });
122   });
123 }
124
125 function endToEndVideoTest() {
126   chrome.tabCapture.capture(
127       { video: true,
128         audio: false,
129         videoConstraints: {
130           mandatory: {
131           minWidth: 64,
132           minHeight: 48
133         }
134       }
135     },
136     TestStream);
137 }
138
139 function endToEndVideoTestWithWebRTC() {
140   chrome.tabCapture.capture(
141       { video: true,
142         audio: false,
143         videoConstraints: {
144           mandatory: {
145           minWidth: 64,
146           minHeight: 48
147         }
148       }
149     },
150     testThroughWebRTC);
151 }
152
153 chrome.test.runTests([
154   endToEndVideoTest,
155   endToEndVideoTestWithWebRTC
156 ]);
157
158 // TODO(miu): Once the WebAudio API is finalized, we should add a test to emit a
159 // tone from the sender page, and have the receiver page check for the audio
160 // tone.