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

Side by Side Diff: content/test/data/media/getusermedia.html

Issue 635833002: Refactor WebRTC getUserMedia tests to be more explicit and clear. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
« no previous file with comments | « content/browser/media/webrtc_getusermedia_browsertest.cc ('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
1 <html> 1 <html>
2 <head> 2 <head>
3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> 3 <script type="text/javascript" src="webrtc_test_utilities.js"></script>
4 <script type="text/javascript"> 4 <script type="text/javascript">
5 $ = function(id) { 5 $ = function(id) {
6 return document.getElementById(id); 6 return document.getElementById(id);
7 }; 7 };
8 8
9 var gLocalStream = null;
10
11 setAllEventsOccuredHandler(function() { 9 setAllEventsOccuredHandler(function() {
12 gLocalStream.stop();
13 reportTestSuccess(); 10 reportTestSuccess();
14 }); 11 });
15 12
16 function getSources() { 13 function getSources() {
17 MediaStreamTrack.getSources(function(devices) { 14 MediaStreamTrack.getSources(function(devices) {
18 document.title = 'Media devices available'; 15 document.title = 'Media devices available';
19 sendValueToTest(JSON.stringify(devices)); 16 sendValueToTest(JSON.stringify(devices));
20 }); 17 });
21 } 18 }
22 19
23 // Creates a MediaStream and renders it locally. When the video is detected to 20 // Creates a MediaStream and renders it locally. When the video is detected to
24 // be rolling, the stream should be stopped. 21 // be rolling, the stream should be stopped.
25 function getUserMediaAndStop(constraints) { 22 function getUserMediaAndStop(constraints) {
26 console.log('Calling getUserMediaAndStop.'); 23 console.log('Calling getUserMediaAndStop.');
27 navigator.webkitGetUserMedia( 24 navigator.webkitGetUserMedia(
28 constraints, 25 constraints,
29 function(stream) { displayAndDetectVideo(stream, stopVideoTrack); }, 26 function(stream) {
27 detectVideoInLocalView1(stream, function() {
28 stream.getVideoTracks()[0].stop();
29 waitForVideoToStop('local-view-1');
30 });
31 },
30 failedCallback); 32 failedCallback);
31 } 33 }
32 34
33 // Requests getusermedia and expects it to fail. The error name is returned 35 // Requests getusermedia and expects it to fail. The error name is returned
34 // to the test. 36 // to the test.
35 function getUserMediaAndExpectFailure(constraints) { 37 function getUserMediaAndExpectFailure(constraints) {
36 console.log('Calling getUserMediaAndExpectFailure.'); 38 console.log('Calling getUserMediaAndExpectFailure.');
37 navigator.webkitGetUserMedia( 39 navigator.webkitGetUserMedia(
38 constraints, 40 constraints,
39 function(stream) { failTest('Unexpectedly succeeded getUserMedia.'); }, 41 function(stream) { failTest('Unexpectedly succeeded getUserMedia.'); },
40 function(error) { sendValueToTest(error.name); }); 42 function(error) { sendValueToTest(error.name); });
41 } 43 }
42 44
43 function renderClonedMediastreamAndStop(constraints, waitTimeInSeconds) { 45 function renderClonedMediastreamAndStop(constraints, waitTimeInSeconds) {
44 console.log('Calling renderClonedMediastreamAndStop.'); 46 console.log('Calling renderClonedMediastreamAndStop.');
45 navigator.webkitGetUserMedia( 47 navigator.webkitGetUserMedia(
46 constraints, 48 constraints,
47 function(stream) { 49 function(stream) {
48 var s = stream.clone(); 50 var duplicate = stream.clone();
49 assertEquals(stream.getVideoTracks().length, 1); 51 assertEquals(stream.getVideoTracks().length, 1);
50 assertEquals(s.getVideoTracks().length, 1); 52 assertEquals(duplicate.getVideoTracks().length, 1);
51 assertNotEquals(stream.getVideoTracks()[0].id, 53 assertNotEquals(stream.getVideoTracks()[0].id,
52 s.getVideoTracks()[0].id); 54 duplicate.getVideoTracks()[0].id);
53 displayAndDetectVideo( 55 detectVideoInLocalView1(
54 s, 56 stream,
55 function() { 57 function() {
56 reportTestSuccess(); 58 reportTestSuccess();
57 }); 59 });
58 }, 60 },
59 failedCallback); 61 failedCallback);
60 } 62 }
61 63
62 function renderDuplicatedMediastreamAndStop(constraints, waitTimeInSeconds) { 64 function renderDuplicatedMediastreamAndStop(constraints, waitTimeInSeconds) {
63 console.log('Calling renderDuplicateMediastreamAndStop.'); 65 console.log('Calling renderDuplicateMediastreamAndStop.');
64 navigator.webkitGetUserMedia( 66 navigator.webkitGetUserMedia(
65 constraints, 67 constraints,
66 function(stream) { 68 function(stream) {
67 s = new webkitMediaStream(stream); 69 var duplicate = new webkitMediaStream(stream);
68 assertEquals(stream.getVideoTracks().length, 1); 70 assertEquals(stream.getVideoTracks().length, 1);
69 assertEquals(s.getVideoTracks().length, 1); 71 assertEquals(duplicate.getVideoTracks().length, 1);
70 assertEquals(stream.getVideoTracks()[0].id, 72 assertEquals(stream.getVideoTracks()[0].id,
71 s.getVideoTracks()[0].id); 73 duplicate.getVideoTracks()[0].id);
72 displayAndDetectVideo( 74 detectVideoInLocalView1(
73 s, 75 duplicate,
74 function() { 76 function() {
75 reportTestSuccess(); 77 reportTestSuccess();
76 }); 78 });
77 }, 79 },
78 failedCallback); 80 failedCallback);
79 } 81 }
80 82
81 function renderSameTrackMediastreamAndStop(constraints, waitTimeInSeconds) { 83 function renderSameTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
82 console.log('Calling renderSameTrackMediastreamAndStop.'); 84 console.log('Calling renderSameTrackMediastreamAndStop.');
83 navigator.webkitGetUserMedia( 85 navigator.webkitGetUserMedia(
84 constraints, 86 constraints,
85 function(stream) { 87 function(stream) {
86 s = new webkitMediaStream(); 88 var duplicate = new webkitMediaStream();
87 s.addTrack(stream.getVideoTracks()[0]); 89 duplicate.addTrack(stream.getVideoTracks()[0]);
88 assertEquals(s.getVideoTracks().length, 1); 90 assertEquals(duplicate.getVideoTracks().length, 1);
89 assertEquals(s.getVideoTracks().length, 1); 91 assertEquals(duplicate.getVideoTracks().length, 1);
90 assertEquals(stream.getVideoTracks()[0].id, s.getVideoTracks()[0].id); 92 assertEquals(stream.getVideoTracks()[0].id,
91 displayAndDetectVideo( 93 duplicate.getVideoTracks()[0].id);
92 s, 94 detectVideoInLocalView1(
95 duplicate,
93 function() { 96 function() {
94 reportTestSuccess(); 97 reportTestSuccess();
95 }); 98 });
96 }, 99 },
97 failedCallback); 100 failedCallback);
98 } 101 }
99 102
100 function renderClonedTrackMediastreamAndStop(constraints, waitTimeInSeconds) { 103 function renderClonedTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
101 console.log('Calling renderClonedTrackMediastreamAndStop.'); 104 console.log('Calling renderClonedTrackMediastreamAndStop.');
102 navigator.webkitGetUserMedia( 105 navigator.webkitGetUserMedia(
103 constraints, 106 constraints,
104 function(stream) { 107 function(stream) {
105 s = new webkitMediaStream(); 108 var duplicate = new webkitMediaStream();
106 s.addTrack(stream.getVideoTracks()[0].clone()); 109 duplicate.addTrack(stream.getVideoTracks()[0].clone());
107 assertEquals(s.getVideoTracks().length, 1); 110 assertEquals(duplicate.getVideoTracks().length, 1);
108 assertEquals(s.getVideoTracks().length, 1); 111 assertEquals(duplicate.getVideoTracks().length, 1);
109 assertNotEquals(stream.getVideoTracks()[0].id, 112 assertNotEquals(stream.getVideoTracks()[0].id,
110 s.getVideoTracks()[0].id) 113 duplicate.getVideoTracks()[0].id)
111 displayAndDetectVideo( 114 detectVideoInLocalView1(
112 s, 115 duplicate,
113 function() { 116 function() {
114 reportTestSuccess(); 117 reportTestSuccess();
115 }); 118 });
116 }, 119 },
117 failedCallback); 120 failedCallback);
118 } 121 }
119 122
120 // Creates a MediaStream and renders it locally. When the video is detected to 123 // Creates a MediaStream and renders it locally. When the video is detected to
121 // be rolling we return ok-stream-running through the automation controller. 124 // be rolling we report success. The acquired stream is stored in window
122 function getUserMediaAndGetStreamUp(constraints, waitTimeInSeconds) { 125 // under the name |streamName|.
126 function getUserMediaAndGetStreamUp(constraints, streamName) {
123 console.log('Calling getUserMediaAndGetStreamUp.'); 127 console.log('Calling getUserMediaAndGetStreamUp.');
124 navigator.webkitGetUserMedia( 128 navigator.webkitGetUserMedia(
125 constraints, 129 constraints,
126 function(stream) { 130 function(stream) {
127 displayAndDetectVideo( 131 window[streamName] = stream;
132 detectVideoInLocalView1(
128 stream, 133 stream,
129 function() { 134 function() {
130 reportTestSuccess(); 135 reportTestSuccess();
131 }); 136 });
132 }, 137 },
133 failedCallback); 138 failedCallback);
134 } 139 }
135 140
136 function getUserMediaAndRenderInSeveralVideoTags() { 141 function getUserMediaAndRenderInSeveralVideoTags() {
137 navigator.webkitGetUserMedia( 142 navigator.webkitGetUserMedia(
(...skipping 15 matching lines...) Expand all
153 function getUserMediaAndClone() { 158 function getUserMediaAndClone() {
154 console.log('Calling getUserMediaAndClone.'); 159 console.log('Calling getUserMediaAndClone.');
155 navigator.webkitGetUserMedia({video: true, audio: true}, 160 navigator.webkitGetUserMedia({video: true, audio: true},
156 createAndRenderClone, failedCallback); 161 createAndRenderClone, failedCallback);
157 } 162 }
158 163
159 // Creates two MediaStream and renders them locally. When the video of both 164 // Creates two MediaStream and renders them locally. When the video of both
160 // streams are detected to be rolling, we stop the local video tracks one at 165 // streams are detected to be rolling, we stop the local video tracks one at
161 // the time. 166 // the time.
162 function twoGetUserMediaAndStop(constraints) { 167 function twoGetUserMediaAndStop(constraints) {
163 console.log('Calling Two GetUserMedia'); 168 // TODO(phoglund): make gUM requests in parallel; this test is too slow
perkj_chrome 2014/10/07 13:07:23 its not the actual request that is slow right? It
phoglund_chromium 2014/10/07 13:57:53 No, I mean that the cycle of detect - gum - detect
169 // and flakes on slow bots (http://crbug.com/417756).
170 var stream1 = null;
171 var stream2 = null;
164 navigator.webkitGetUserMedia( 172 navigator.webkitGetUserMedia(
165 constraints, 173 constraints,
166 function(stream) { 174 function(stream) {
167 displayAndDetectVideo(stream, requestSecondGetUserMedia); 175 stream1 = stream;
176 detectVideoInLocalView1(stream, requestSecondGetUserMedia);
168 }, 177 },
169 failedCallback); 178 failedCallback);
170 var requestSecondGetUserMedia = function() { 179 var requestSecondGetUserMedia = function() {
171 navigator.webkitGetUserMedia( 180 navigator.webkitGetUserMedia(
172 constraints, 181 constraints,
173 function(stream) { 182 function(stream) {
174 displayIntoVideoElement(stream, 183 stream2 = stream;
175 function() { 184 attachMediaStream(stream, 'local-view-2');
176 stopBothVideoTracksAndVerify(stream); 185 detectVideoPlaying('local-view-2', stopBothVideoTracksAndVerify);
177 },
178 'local-view-2');
179 }, 186 },
180 failedCallback); 187 failedCallback);
181 }; 188 };
182 189
183 var stopBothVideoTracksAndVerify = function(streamPlayingInLocalView2) { 190 var stopBothVideoTracksAndVerify = function() {
184 streamPlayingInLocalView2.getVideoTracks()[0].stop(); 191 // Stop track 2, ensure that stops track 2 but not track 1, then stop
192 // track 1.
193 stream2.getVideoTracks()[0].stop();
194 waitForVideoToStop('local-view-1');
185 waitForVideoToStop('local-view-2'); 195 waitForVideoToStop('local-view-2');
186 // Make sure the video track in gLocalStream is still playing in 196 detectVideoInLocalView1(stream1, function() {
187 // 'local-view1' and then stop it. 197 stream1.getVideoTracks()[0].stop();
188 displayAndDetectVideo(gLocalStream, stopVideoTrack); 198 });
189 }; 199 };
190 } 200 }
191 201
192 function twoGetUserMedia(constraints1, 202 function twoGetUserMedia(constraints1,
193 constraints2) { 203 constraints2) {
204 // TODO(phoglund): make gUM requests in parallel; this test is too slow
205 // and flakes on slow bots (http://crbug.com/417756).
194 var result=""; 206 var result="";
195 navigator.webkitGetUserMedia( 207 navigator.webkitGetUserMedia(
196 constraints1, 208 constraints1,
197 function(stream) { 209 function(stream) {
198 displayDetectAndAnalyzeVideoInElement( 210 displayDetectAndAnalyzeVideoInElement(
199 stream, 211 stream,
200 function(aspectRatio) { 212 function(aspectRatio) {
201 result = aspectRatio; 213 result = aspectRatio;
202 requestSecondGetUserMedia(); 214 requestSecondGetUserMedia();
203 }, 215 },
204 'local-view'); 216 'local-view-1');
205 }, 217 },
206 failedCallback); 218 failedCallback);
207 var requestSecondGetUserMedia = function() { 219 var requestSecondGetUserMedia = function() {
208 navigator.webkitGetUserMedia( 220 navigator.webkitGetUserMedia(
209 constraints2, 221 constraints2,
210 function(stream) { 222 function(stream) {
211 displayDetectAndAnalyzeVideoInElement( 223 displayDetectAndAnalyzeVideoInElement(
212 stream, 224 stream,
213 function(aspectRatio) { 225 function(aspectRatio) {
214 result = result + '-' + aspectRatio; 226 result = result + '-' + aspectRatio;
215 sendValueToTest(result); 227 sendValueToTest(result);
216 }, 228 },
217 'local-view-2'); 229 'local-view-2');
218 }, 230 },
219 failedCallback); 231 failedCallback);
220 } 232 }
221 } 233 }
222 234
223 // Calls GetUserMedia twice and verify that the frame rate is as expected for 235 // Calls GetUserMedia twice and verify that the frame rate is as expected for
224 // both streams. 236 // both streams.
225 function twoGetUserMediaAndVerifyFrameRate(constraints1, 237 function twoGetUserMediaAndVerifyFrameRate(constraints1,
226 constraints2, 238 constraints2,
227 expected_frame_rate1, 239 expected_frame_rate1,
228 expected_frame_rate2) { 240 expected_frame_rate2) {
241 // TODO(phoglund): make gUM requests in parallell; this test is too slow
242 // and flakes on slow bots (http://crbug.com/417756).
229 addExpectedEvent(); 243 addExpectedEvent();
230 addExpectedEvent(); 244 addExpectedEvent();
231 var validateFrameRateCallback = function (success) { 245 var validateFrameRateCallback = function (success) {
232 if (!success) 246 if (!success)
233 failTest("Failed to validate frameRate."); 247 failTest("Failed to validate frameRate.");
234 eventOccured(); 248 eventOccured();
235 }; 249 };
236 250
237 navigator.webkitGetUserMedia( 251 navigator.webkitGetUserMedia(
238 constraints1, 252 constraints1,
239 function(stream) { 253 function(stream) {
240 requestSecondGetUserMedia(); 254 requestSecondGetUserMedia();
241 plugStreamIntoVideoElement(stream, 'local-view'); 255 attachMediaStream(stream, 'local-view-1');
242 detectVideoPlaying('local-view', 256 detectVideoPlaying('local-view-1',
243 function() { 257 function() {
244 validateFrameRate('local-view', expected_frame_rate1, 258 validateFrameRate('local-view-1', expected_frame_rate1,
245 validateFrameRateCallback); 259 validateFrameRateCallback);
246 }); 260 });
247 }, 261 },
248 failedCallback); 262 failedCallback);
249 var requestSecondGetUserMedia = function() { 263 var requestSecondGetUserMedia = function() {
250 navigator.webkitGetUserMedia( 264 navigator.webkitGetUserMedia(
251 constraints2, 265 constraints2,
252 function(stream) { 266 function(stream) {
253 plugStreamIntoVideoElement(stream, 'local-view-2'); 267 attachMediaStream(stream, 'local-view-2');
254 detectVideoPlaying('local-view-2', 268 detectVideoPlaying('local-view-2',
255 function() { 269 function() {
256 validateFrameRate('local-view-2', expected_frame_rate2, 270 validateFrameRate('local-view-2', expected_frame_rate2,
257 validateFrameRateCallback); 271 validateFrameRateCallback);
258 }); 272 });
259 }, 273 },
260 failedCallback); 274 failedCallback);
261 } 275 }
262 } 276 }
263 277
264 function failedCallback(error) { 278 function failedCallback(error) {
265 failTest('GetUserMedia call failed with code ' + error.code); 279 failTest('GetUserMedia call failed with code ' + error.code);
266 } 280 }
267 281
268 function plugStreamIntoVideoElement(stream, videoElement) { 282 function attachMediaStream(stream, videoElement) {
269 gLocalStream = stream;
270 var localStreamUrl = URL.createObjectURL(stream); 283 var localStreamUrl = URL.createObjectURL(stream);
271 $(videoElement).src = localStreamUrl; 284 $(videoElement).src = localStreamUrl;
272 } 285 }
273 286
274 function displayIntoVideoElement(stream, callback, videoElement) { 287 function detectVideoInLocalView1(stream, callback) {
275 plugStreamIntoVideoElement(stream, videoElement); 288 attachMediaStream(stream, 'local-view-1');
276 detectVideoPlaying(videoElement, callback); 289 detectVideoPlaying('local-view-1', callback);
277 }
278
279 function displayAndDetectVideo(stream, callback) {
280 displayIntoVideoElement(stream, callback, 'local-view');
281 } 290 }
282 291
283 function displayDetectAndAnalyzeVideo(stream) { 292 function displayDetectAndAnalyzeVideo(stream) {
284 displayDetectAndAnalyzeVideoInElement(stream, 293 displayDetectAndAnalyzeVideoInElement(stream,
285 function(aspectRatio) { 294 function(aspectRatio) {
286 sendValueToTest(aspectRatio); 295 sendValueToTest(aspectRatio);
287 }, 296 },
288 'local-view'); 297 'local-view-1');
289 } 298 }
290 299
291 function displayDetectAndAnalyzeVideoInElement( 300 function displayDetectAndAnalyzeVideoInElement(
292 stream, callback, videoElement) { 301 stream, callback, videoElement) {
293 plugStreamIntoVideoElement(stream, videoElement); 302 attachMediaStream(stream, videoElement);
294 detectAspectRatio(callback, videoElement); 303 detectAspectRatio(callback, videoElement);
295 } 304 }
296 305
297 function createAndRenderClone(stream) { 306 function createAndRenderClone(stream) {
298 gLocalStream = stream;
299 // TODO(perkj): --use-fake-device-for-media-stream do not currently 307 // TODO(perkj): --use-fake-device-for-media-stream do not currently
300 // work with audio devices and not all bots has a microphone. 308 // work with audio devices and not all bots has a microphone.
301 new_stream = new webkitMediaStream(); 309 newStream = new webkitMediaStream();
302 new_stream.addTrack(stream.getVideoTracks()[0]); 310 newStream.addTrack(stream.getVideoTracks()[0]);
303 assertEquals(new_stream.getVideoTracks().length, 1); 311 assertEquals(newStream.getVideoTracks().length, 1);
304 if (stream.getAudioTracks().length > 0) { 312 if (stream.getAudioTracks().length > 0) {
305 new_stream.addTrack(stream.getAudioTracks()[0]); 313 newStream.addTrack(stream.getAudioTracks()[0]);
306 assertEquals(new_stream.getAudioTracks().length, 1); 314 assertEquals(newStream.getAudioTracks().length, 1);
307 new_stream.removeTrack(new_stream.getAudioTracks()[0]); 315 newStream.removeTrack(newStream.getAudioTracks()[0]);
308 assertEquals(new_stream.getAudioTracks().length, 0); 316 assertEquals(newStream.getAudioTracks().length, 0);
309 } 317 }
310 318
311 var newStreamUrl = URL.createObjectURL(new_stream); 319 detectVideoInLocalView1(newStream, reportTestSuccess);
312 $('local-view').src = newStreamUrl;
313 waitForVideo('local-view');
314 } 320 }
315 321
316 function stopVideoTrack() { 322 // Calls stop on |stream|'s video track after a delay and reports success.
317 gLocalStream.getVideoTracks()[0].stop(); 323 function waitAndStopVideoTrack(stream, waitTimeInSeconds) {
318 waitForVideoToStop('local-view'); 324 setTimeout(function() {
319 } 325 stream.getVideoTracks()[0].stop();
320 326 reportTestSuccess();
321 function waitAndStopVideoTrack(waitTimeInSeconds) { 327 }, waitTimeInSeconds * 1000);
322 setTimeout(stopVideoTrack, waitTimeInSeconds * 1000);
323 } 328 }
324 329
325 // This test make sure multiple video renderers can be created for the same 330 // This test make sure multiple video renderers can be created for the same
326 // local video track and make sure a renderer can still render if other 331 // local video track and make sure a renderer can still render if other
327 // renderers are paused. See http://crbug/352619. 332 // renderers are paused. See http://crbug/352619.
328 function createMultipleVideoRenderersAndPause(stream) { 333 function createMultipleVideoRenderersAndPause(stream) {
329 function createDetectableRenderer(stream, id) { 334 function createDetectableRenderer(stream, id) {
330 var video = document.createElement('video'); 335 var video = document.createElement('video');
331 document.body.appendChild(video); 336 document.body.appendChild(video);
332 var localStreamUrl = URL.createObjectURL(stream); 337 var localStreamUrl = URL.createObjectURL(stream);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 console.log(result); 446 console.log(result);
442 callback(result); 447 callback(result);
443 } 448 }
444 } 449 }
445 var detectorInterval = setInterval(detectorFunction, 50); 450 var detectorInterval = setInterval(detectorFunction, 50);
446 } 451 }
447 </script> 452 </script>
448 </head> 453 </head>
449 <body> 454 <body>
450 <table border="0"> 455 <table border="0">
456 <!-- Canvases are named after their corresponding video elements. -->
451 <tr> 457 <tr>
452 <td><video width="320" height="240" id="local-view" 458 <td><video id="local-view-1" width="320" height="240" autoplay
453 autoplay="autoplay" style="display:none"></video></td> 459 style="display:none"></video></td>
454 <td><canvas id="local-view-canvas" 460 <td><canvas id="local-view-1-canvas" width="320" height="240"
455 style="display:none"></canvas></td> 461 style="display:none"></canvas></td>
456 </tr> 462 </tr>
457 <tr> 463 <tr>
458 <td><video width="320" height="240" id="local-view-2" 464 <td><video id="local-view-2" width="320" height="240" autoplay
459 autoplay style="display:none"></video></td> 465 style="display:none"></video></td>
460 <!-- Canvases are named after their corresponding video elements. --> 466 <td><canvas id="local-view-2-canvas" width="320" height="240"
461 <td><canvas width="320" height="240" id="local-view-2-canvas"
462 style="display:none"></canvas></td> 467 style="display:none"></canvas></td>
463 </tr> 468 </tr>
464 </table> 469 </table>
465 </body> 470 </body>
466 </html> 471 </html>
OLDNEW
« no previous file with comments | « content/browser/media/webrtc_getusermedia_browsertest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698