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

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: Clarified TODO 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
169 // and flakes on slow bots (http://crbug.com/417756). The current cycle of
170 // detect - gum - detect - gum - stop - detect - stop - detect contains too
171 // many detection phases. On bots with GPU emulation this looks to be really
172 // slow, so I was thinking we could at least get video up for both streams
173 // simultaneously and thereby run the first two detects in parallel.
174 var stream1 = null;
175 var stream2 = null;
164 navigator.webkitGetUserMedia( 176 navigator.webkitGetUserMedia(
165 constraints, 177 constraints,
166 function(stream) { 178 function(stream) {
167 displayAndDetectVideo(stream, requestSecondGetUserMedia); 179 stream1 = stream;
180 detectVideoInLocalView1(stream, requestSecondGetUserMedia);
168 }, 181 },
169 failedCallback); 182 failedCallback);
170 var requestSecondGetUserMedia = function() { 183 var requestSecondGetUserMedia = function() {
171 navigator.webkitGetUserMedia( 184 navigator.webkitGetUserMedia(
172 constraints, 185 constraints,
173 function(stream) { 186 function(stream) {
174 displayIntoVideoElement(stream, 187 stream2 = stream;
175 function() { 188 attachMediaStream(stream, 'local-view-2');
176 stopBothVideoTracksAndVerify(stream); 189 detectVideoPlaying('local-view-2', stopBothVideoTracksAndVerify);
177 },
178 'local-view-2');
179 }, 190 },
180 failedCallback); 191 failedCallback);
181 }; 192 };
182 193
183 var stopBothVideoTracksAndVerify = function(streamPlayingInLocalView2) { 194 var stopBothVideoTracksAndVerify = function() {
184 streamPlayingInLocalView2.getVideoTracks()[0].stop(); 195 // Stop track 2, ensure that stops track 2 but not track 1, then stop
196 // track 1.
197 stream2.getVideoTracks()[0].stop();
198 waitForVideoToStop('local-view-1');
185 waitForVideoToStop('local-view-2'); 199 waitForVideoToStop('local-view-2');
186 // Make sure the video track in gLocalStream is still playing in 200 detectVideoInLocalView1(stream1, function() {
187 // 'local-view1' and then stop it. 201 stream1.getVideoTracks()[0].stop();
188 displayAndDetectVideo(gLocalStream, stopVideoTrack); 202 });
189 }; 203 };
190 } 204 }
191 205
192 function twoGetUserMedia(constraints1, 206 function twoGetUserMedia(constraints1,
193 constraints2) { 207 constraints2) {
208 // TODO(phoglund): see TODO on twoGetUserMediaAndStop.
194 var result=""; 209 var result="";
195 navigator.webkitGetUserMedia( 210 navigator.webkitGetUserMedia(
196 constraints1, 211 constraints1,
197 function(stream) { 212 function(stream) {
198 displayDetectAndAnalyzeVideoInElement( 213 displayDetectAndAnalyzeVideoInElement(
199 stream, 214 stream,
200 function(aspectRatio) { 215 function(aspectRatio) {
201 result = aspectRatio; 216 result = aspectRatio;
202 requestSecondGetUserMedia(); 217 requestSecondGetUserMedia();
203 }, 218 },
204 'local-view'); 219 'local-view-1');
205 }, 220 },
206 failedCallback); 221 failedCallback);
207 var requestSecondGetUserMedia = function() { 222 var requestSecondGetUserMedia = function() {
208 navigator.webkitGetUserMedia( 223 navigator.webkitGetUserMedia(
209 constraints2, 224 constraints2,
210 function(stream) { 225 function(stream) {
211 displayDetectAndAnalyzeVideoInElement( 226 displayDetectAndAnalyzeVideoInElement(
212 stream, 227 stream,
213 function(aspectRatio) { 228 function(aspectRatio) {
214 result = result + '-' + aspectRatio; 229 result = result + '-' + aspectRatio;
215 sendValueToTest(result); 230 sendValueToTest(result);
216 }, 231 },
217 'local-view-2'); 232 'local-view-2');
218 }, 233 },
219 failedCallback); 234 failedCallback);
220 } 235 }
221 } 236 }
222 237
223 // Calls GetUserMedia twice and verify that the frame rate is as expected for 238 // Calls GetUserMedia twice and verify that the frame rate is as expected for
224 // both streams. 239 // both streams.
225 function twoGetUserMediaAndVerifyFrameRate(constraints1, 240 function twoGetUserMediaAndVerifyFrameRate(constraints1,
226 constraints2, 241 constraints2,
227 expected_frame_rate1, 242 expected_frame_rate1,
228 expected_frame_rate2) { 243 expected_frame_rate2) {
244 // TODO(phoglund): see TODO on twoGetUserMediaAndStop.
229 addExpectedEvent(); 245 addExpectedEvent();
230 addExpectedEvent(); 246 addExpectedEvent();
231 var validateFrameRateCallback = function (success) { 247 var validateFrameRateCallback = function (success) {
232 if (!success) 248 if (!success)
233 failTest("Failed to validate frameRate."); 249 failTest("Failed to validate frameRate.");
234 eventOccured(); 250 eventOccured();
235 }; 251 };
236 252
237 navigator.webkitGetUserMedia( 253 navigator.webkitGetUserMedia(
238 constraints1, 254 constraints1,
239 function(stream) { 255 function(stream) {
240 requestSecondGetUserMedia(); 256 requestSecondGetUserMedia();
241 plugStreamIntoVideoElement(stream, 'local-view'); 257 attachMediaStream(stream, 'local-view-1');
242 detectVideoPlaying('local-view', 258 detectVideoPlaying('local-view-1',
243 function() { 259 function() {
244 validateFrameRate('local-view', expected_frame_rate1, 260 validateFrameRate('local-view-1', expected_frame_rate1,
245 validateFrameRateCallback); 261 validateFrameRateCallback);
246 }); 262 });
247 }, 263 },
248 failedCallback); 264 failedCallback);
249 var requestSecondGetUserMedia = function() { 265 var requestSecondGetUserMedia = function() {
250 navigator.webkitGetUserMedia( 266 navigator.webkitGetUserMedia(
251 constraints2, 267 constraints2,
252 function(stream) { 268 function(stream) {
253 plugStreamIntoVideoElement(stream, 'local-view-2'); 269 attachMediaStream(stream, 'local-view-2');
254 detectVideoPlaying('local-view-2', 270 detectVideoPlaying('local-view-2',
255 function() { 271 function() {
256 validateFrameRate('local-view-2', expected_frame_rate2, 272 validateFrameRate('local-view-2', expected_frame_rate2,
257 validateFrameRateCallback); 273 validateFrameRateCallback);
258 }); 274 });
259 }, 275 },
260 failedCallback); 276 failedCallback);
261 } 277 }
262 } 278 }
263 279
264 function failedCallback(error) { 280 function failedCallback(error) {
265 failTest('GetUserMedia call failed with code ' + error.code); 281 failTest('GetUserMedia call failed with code ' + error.code);
266 } 282 }
267 283
268 function plugStreamIntoVideoElement(stream, videoElement) { 284 function attachMediaStream(stream, videoElement) {
269 gLocalStream = stream;
270 var localStreamUrl = URL.createObjectURL(stream); 285 var localStreamUrl = URL.createObjectURL(stream);
271 $(videoElement).src = localStreamUrl; 286 $(videoElement).src = localStreamUrl;
272 } 287 }
273 288
274 function displayIntoVideoElement(stream, callback, videoElement) { 289 function detectVideoInLocalView1(stream, callback) {
275 plugStreamIntoVideoElement(stream, videoElement); 290 attachMediaStream(stream, 'local-view-1');
276 detectVideoPlaying(videoElement, callback); 291 detectVideoPlaying('local-view-1', callback);
277 }
278
279 function displayAndDetectVideo(stream, callback) {
280 displayIntoVideoElement(stream, callback, 'local-view');
281 } 292 }
282 293
283 function displayDetectAndAnalyzeVideo(stream) { 294 function displayDetectAndAnalyzeVideo(stream) {
284 displayDetectAndAnalyzeVideoInElement(stream, 295 displayDetectAndAnalyzeVideoInElement(stream,
285 function(aspectRatio) { 296 function(aspectRatio) {
286 sendValueToTest(aspectRatio); 297 sendValueToTest(aspectRatio);
287 }, 298 },
288 'local-view'); 299 'local-view-1');
289 } 300 }
290 301
291 function displayDetectAndAnalyzeVideoInElement( 302 function displayDetectAndAnalyzeVideoInElement(
292 stream, callback, videoElement) { 303 stream, callback, videoElement) {
293 plugStreamIntoVideoElement(stream, videoElement); 304 attachMediaStream(stream, videoElement);
294 detectAspectRatio(callback, videoElement); 305 detectAspectRatio(callback, videoElement);
295 } 306 }
296 307
297 function createAndRenderClone(stream) { 308 function createAndRenderClone(stream) {
298 gLocalStream = stream;
299 // TODO(perkj): --use-fake-device-for-media-stream do not currently 309 // TODO(perkj): --use-fake-device-for-media-stream do not currently
300 // work with audio devices and not all bots has a microphone. 310 // work with audio devices and not all bots has a microphone.
301 new_stream = new webkitMediaStream(); 311 newStream = new webkitMediaStream();
302 new_stream.addTrack(stream.getVideoTracks()[0]); 312 newStream.addTrack(stream.getVideoTracks()[0]);
303 assertEquals(new_stream.getVideoTracks().length, 1); 313 assertEquals(newStream.getVideoTracks().length, 1);
304 if (stream.getAudioTracks().length > 0) { 314 if (stream.getAudioTracks().length > 0) {
305 new_stream.addTrack(stream.getAudioTracks()[0]); 315 newStream.addTrack(stream.getAudioTracks()[0]);
306 assertEquals(new_stream.getAudioTracks().length, 1); 316 assertEquals(newStream.getAudioTracks().length, 1);
307 new_stream.removeTrack(new_stream.getAudioTracks()[0]); 317 newStream.removeTrack(newStream.getAudioTracks()[0]);
308 assertEquals(new_stream.getAudioTracks().length, 0); 318 assertEquals(newStream.getAudioTracks().length, 0);
309 } 319 }
310 320
311 var newStreamUrl = URL.createObjectURL(new_stream); 321 detectVideoInLocalView1(newStream, reportTestSuccess);
312 $('local-view').src = newStreamUrl;
313 waitForVideo('local-view');
314 } 322 }
315 323
316 function stopVideoTrack() { 324 // Calls stop on |stream|'s video track after a delay and reports success.
317 gLocalStream.getVideoTracks()[0].stop(); 325 function waitAndStopVideoTrack(stream, waitTimeInSeconds) {
318 waitForVideoToStop('local-view'); 326 setTimeout(function() {
319 } 327 stream.getVideoTracks()[0].stop();
320 328 reportTestSuccess();
321 function waitAndStopVideoTrack(waitTimeInSeconds) { 329 }, waitTimeInSeconds * 1000);
322 setTimeout(stopVideoTrack, waitTimeInSeconds * 1000);
323 } 330 }
324 331
325 // This test make sure multiple video renderers can be created for the same 332 // 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 333 // local video track and make sure a renderer can still render if other
327 // renderers are paused. See http://crbug/352619. 334 // renderers are paused. See http://crbug/352619.
328 function createMultipleVideoRenderersAndPause(stream) { 335 function createMultipleVideoRenderersAndPause(stream) {
329 function createDetectableRenderer(stream, id) { 336 function createDetectableRenderer(stream, id) {
330 var video = document.createElement('video'); 337 var video = document.createElement('video');
331 document.body.appendChild(video); 338 document.body.appendChild(video);
332 var localStreamUrl = URL.createObjectURL(stream); 339 var localStreamUrl = URL.createObjectURL(stream);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 console.log(result); 448 console.log(result);
442 callback(result); 449 callback(result);
443 } 450 }
444 } 451 }
445 var detectorInterval = setInterval(detectorFunction, 50); 452 var detectorInterval = setInterval(detectorFunction, 50);
446 } 453 }
447 </script> 454 </script>
448 </head> 455 </head>
449 <body> 456 <body>
450 <table border="0"> 457 <table border="0">
458 <!-- Canvases are named after their corresponding video elements. -->
451 <tr> 459 <tr>
452 <td><video width="320" height="240" id="local-view" 460 <td><video id="local-view-1" width="320" height="240" autoplay
453 autoplay="autoplay" style="display:none"></video></td> 461 style="display:none"></video></td>
454 <td><canvas id="local-view-canvas" 462 <td><canvas id="local-view-1-canvas" width="320" height="240"
455 style="display:none"></canvas></td> 463 style="display:none"></canvas></td>
456 </tr> 464 </tr>
457 <tr> 465 <tr>
458 <td><video width="320" height="240" id="local-view-2" 466 <td><video id="local-view-2" width="320" height="240" autoplay
459 autoplay style="display:none"></video></td> 467 style="display:none"></video></td>
460 <!-- Canvases are named after their corresponding video elements. --> 468 <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> 469 style="display:none"></canvas></td>
463 </tr> 470 </tr>
464 </table> 471 </table>
465 </body> 472 </body>
466 </html> 473 </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