1 // Copyright 2014 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 #include "base/command_line.h" 6 #include "base/debug/trace_event_impl.h" 7 #include "base/json/json_reader.h" 8 #include "base/strings/stringprintf.h" 9 #include "base/test/trace_event_analyzer.h" 10 #include "base/values.h" 11 #include "content/browser/media/webrtc_internals.h" 12 #include "content/browser/web_contents/web_contents_impl.h" 13 #include "content/public/common/content_switches.h" 14 #include "content/public/test/browser_test_utils.h" 15 #include "content/public/test/content_browser_test_utils.h" 16 #include "content/public/test/test_utils.h" 17 #include "content/shell/browser/shell.h" 18 #include "content/test/webrtc_content_browsertest_base.h" 19 #include "net/test/embedded_test_server/embedded_test_server.h" 20 #include "testing/perf/perf_test.h" 21 22 #if defined(OS_WIN) 23 #include "base/win/windows_version.h" 24 #endif 25 26 using trace_analyzer::TraceAnalyzer; 27 using trace_analyzer::Query; 28 using trace_analyzer::TraceEventVector; 29 30 namespace { 31 32 static const char kGetUserMediaAndStop[] = "getUserMediaAndStop"; 33 static const char kGetUserMediaAndGetStreamUp[] = "getUserMediaAndGetStreamUp"; 34 static const char kGetUserMediaAndAnalyseAndStop[] = 35 "getUserMediaAndAnalyseAndStop"; 36 static const char kGetUserMediaAndExpectFailure[] = 37 "getUserMediaAndExpectFailure"; 38 static const char kRenderSameTrackMediastreamAndStop[] = 39 "renderSameTrackMediastreamAndStop"; 40 static const char kRenderClonedMediastreamAndStop[] = 41 "renderClonedMediastreamAndStop"; 42 static const char kRenderClonedTrackMediastreamAndStop[] = 43 "renderClonedTrackMediastreamAndStop"; 44 static const char kRenderDuplicatedMediastreamAndStop[] = 45 "renderDuplicatedMediastreamAndStop"; 46 47 // Results returned by JS. 48 static const char kOK[] = "OK"; 49 50 std::string GenerateGetUserMediaWithMandatorySourceID( 51 const std::string& function_name, 52 const std::string& audio_source_id, 53 const std::string& video_source_id) { 54 const std::string audio_constraint = 55 "audio: {mandatory: { sourceId:\"" + audio_source_id + "\"}}, "; 56 57 const std::string video_constraint = 58 "video: {mandatory: { sourceId:\"" + video_source_id + "\"}}"; 59 return function_name + "({" + audio_constraint + video_constraint + "});"; 60 } 61 62 std::string GenerateGetUserMediaWithOptionalSourceID( 63 const std::string& function_name, 64 const std::string& audio_source_id, 65 const std::string& video_source_id) { 66 const std::string audio_constraint = 67 "audio: {optional: [{sourceId:\"" + audio_source_id + "\"}]}, "; 68 69 const std::string video_constraint = 70 "video: {optional: [{ sourceId:\"" + video_source_id + "\"}]}"; 71 return function_name + "({" + audio_constraint + video_constraint + "});"; 72 } 73 74 } // namespace 75 76 namespace content { 77 78 class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest, 79 public testing::WithParamInterface<bool> { 80 public: 81 WebRtcGetUserMediaBrowserTest() : trace_log_(NULL) {} 82 virtual ~WebRtcGetUserMediaBrowserTest() {} 83 84 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 85 WebRtcContentBrowserTest::SetUpCommandLine(command_line); 86 87 bool enable_audio_track_processing = GetParam(); 88 if (!enable_audio_track_processing) 89 command_line->AppendSwitch(switches::kDisableAudioTrackProcessing); 90 } 91 92 void StartTracing() { 93 CHECK(trace_log_ == NULL) << "Can only can start tracing once"; 94 trace_log_ = base::debug::TraceLog::GetInstance(); 95 trace_log_->SetEnabled(base::debug::CategoryFilter("video"), 96 base::debug::TraceLog::RECORDING_MODE, 97 base::debug::TraceLog::ENABLE_SAMPLING); 98 // Check that we are indeed recording. 99 EXPECT_EQ(trace_log_->GetNumTracesRecorded(), 1); 100 } 101 102 void StopTracing() { 103 CHECK(message_loop_runner_ == NULL) << "Calling StopTracing more than once"; 104 trace_log_->SetDisabled(); 105 message_loop_runner_ = new MessageLoopRunner; 106 trace_log_->Flush(base::Bind( 107 &WebRtcGetUserMediaBrowserTest::OnTraceDataCollected, 108 base::Unretained(this))); 109 message_loop_runner_->Run(); 110 } 111 112 void OnTraceDataCollected( 113 const scoped_refptr<base::RefCountedString>& events_str_ptr, 114 bool has_more_events) { 115 CHECK(!has_more_events); 116 recorded_trace_data_ = events_str_ptr; 117 message_loop_runner_->Quit(); 118 } 119 120 TraceAnalyzer* CreateTraceAnalyzer() { 121 return TraceAnalyzer::Create("[" + recorded_trace_data_->data() + "]"); 122 } 123 124 void RunGetUserMediaAndCollectMeasures(const int time_to_sample_secs, 125 const std::string& measure_filter, 126 const std::string& graph_name) { 127 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 128 129 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 130 NavigateToURL(shell(), url); 131 132 // Put getUserMedia to work and let it run for a couple of seconds. 133 DCHECK(time_to_sample_secs); 134 ExecuteJavascriptAndWaitForOk( 135 base::StringPrintf("%s({video: true});", 136 kGetUserMediaAndGetStreamUp)); 137 138 // Now the stream is up and running, start collecting traces. 139 StartTracing(); 140 141 // Let the stream run for a while in javascript. 142 ExecuteJavascriptAndWaitForOk( 143 base::StringPrintf("waitAndStopVideoTrack(%d);", time_to_sample_secs)); 144 145 // Wait until the page title changes to "OK". Do not sleep() here since that 146 // would stop both this code and the browser underneath. 147 StopTracing(); 148 149 scoped_ptr<TraceAnalyzer> analyzer(CreateTraceAnalyzer()); 150 analyzer->AssociateBeginEndEvents(); 151 trace_analyzer::TraceEventVector events; 152 DCHECK(measure_filter.size()); 153 analyzer->FindEvents( 154 Query::EventNameIs(measure_filter), 155 &events); 156 ASSERT_GT(events.size(), 0u) 157 << "Could not collect any samples during test, this is bad"; 158 159 std::string duration_us; 160 std::string interarrival_us; 161 for (size_t i = 0; i != events.size(); ++i) { 162 duration_us.append( 163 base::StringPrintf("%d,", static_cast<int>(events[i]->duration))); 164 } 165 166 for (size_t i = 1; i < events.size(); ++i) { 167 // The event |timestamp| comes in ns, divide to get us like |duration|. 168 interarrival_us.append(base::StringPrintf("%d,", 169 static_cast<int>((events[i]->timestamp - events[i - 1]->timestamp) / 170 base::Time::kNanosecondsPerMicrosecond))); 171 } 172 173 perf_test::PrintResultList( 174 graph_name, "", "sample_duration", duration_us, "us", true); 175 176 perf_test::PrintResultList( 177 graph_name, "", "interarrival_time", interarrival_us, "us", true); 178 } 179 180 void RunTwoGetTwoGetUserMediaWithDifferentContraints( 181 const std::string& constraints1, 182 const std::string& constraints2, 183 const std::string& expected_result) { 184 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 185 186 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 187 NavigateToURL(shell(), url); 188 189 std::string command = "twoGetUserMedia(" + constraints1 + ',' + 190 constraints2 + ')'; 191 192 EXPECT_EQ(expected_result, ExecuteJavascriptAndReturnResult(command)); 193 } 194 195 void GetInputDevices(std::vector<std::string>* audio_ids, 196 std::vector<std::string>* video_ids) { 197 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 198 NavigateToURL(shell(), url); 199 200 std::string devices_as_json = ExecuteJavascriptAndReturnResult( 201 "getSources()"); 202 EXPECT_FALSE(devices_as_json.empty()); 203 204 int error_code; 205 std::string error_message; 206 scoped_ptr<base::Value> value( 207 base::JSONReader::ReadAndReturnError(devices_as_json, 208 base::JSON_ALLOW_TRAILING_COMMAS, 209 &error_code, 210 &error_message)); 211 212 ASSERT_TRUE(value.get() != NULL) << error_message; 213 EXPECT_EQ(value->GetType(), base::Value::TYPE_LIST); 214 215 base::ListValue* values; 216 ASSERT_TRUE(value->GetAsList(&values)); 217 218 for (base::ListValue::iterator it = values->begin(); 219 it != values->end(); ++it) { 220 const base::DictionaryValue* dict; 221 std::string kind; 222 std::string device_id; 223 ASSERT_TRUE((*it)->GetAsDictionary(&dict)); 224 ASSERT_TRUE(dict->GetString("kind", &kind)); 225 ASSERT_TRUE(dict->GetString("id", &device_id)); 226 ASSERT_FALSE(device_id.empty()); 227 EXPECT_TRUE(kind == "audio" || kind == "video"); 228 if (kind == "audio") { 229 audio_ids->push_back(device_id); 230 } else if (kind == "video") { 231 video_ids->push_back(device_id); 232 } 233 } 234 ASSERT_FALSE(audio_ids->empty()); 235 ASSERT_FALSE(video_ids->empty()); 236 } 237 238 private: 239 base::debug::TraceLog* trace_log_; 240 scoped_refptr<base::RefCountedString> recorded_trace_data_; 241 scoped_refptr<MessageLoopRunner> message_loop_runner_; 242 }; 243 244 static const bool kRunTestsWithFlag[] = { false, true }; 245 INSTANTIATE_TEST_CASE_P(WebRtcGetUserMediaBrowserTests, 246 WebRtcGetUserMediaBrowserTest, 247 testing::ValuesIn(kRunTestsWithFlag)); 248 249 // These tests will all make a getUserMedia call with different constraints and 250 // see that the success callback is called. If the error callback is called or 251 // none of the callbacks are called the tests will simply time out and fail. 252 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, GetVideoStreamAndStop) { 253 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 254 255 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 256 NavigateToURL(shell(), url); 257 258 ExecuteJavascriptAndWaitForOk( 259 base::StringPrintf("%s({video: true});", kGetUserMediaAndStop)); 260 } 261 262 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 263 RenderSameTrackMediastreamAndStop) { 264 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 265 266 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 267 NavigateToURL(shell(), url); 268 269 ExecuteJavascriptAndWaitForOk( 270 base::StringPrintf("%s({video: true});", 271 kRenderSameTrackMediastreamAndStop)); 272 } 273 274 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 275 RenderClonedMediastreamAndStop) { 276 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 277 278 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 279 NavigateToURL(shell(), url); 280 281 282 ExecuteJavascriptAndWaitForOk( 283 base::StringPrintf("%s({video: true});", 284 kRenderClonedMediastreamAndStop)); 285 } 286 287 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 288 kRenderClonedTrackMediastreamAndStop) { 289 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 290 291 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 292 NavigateToURL(shell(), url); 293 294 ExecuteJavascriptAndWaitForOk( 295 base::StringPrintf("%s({video: true});", 296 kRenderClonedTrackMediastreamAndStop)); 297 } 298 299 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 300 kRenderDuplicatedMediastreamAndStop) { 301 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 302 303 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 304 NavigateToURL(shell(), url); 305 306 ExecuteJavascriptAndWaitForOk( 307 base::StringPrintf("%s({video: true});", 308 kRenderDuplicatedMediastreamAndStop)); 309 } 310 311 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 312 GetAudioAndVideoStreamAndStop) { 313 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 314 315 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 316 NavigateToURL(shell(), url); 317 318 ExecuteJavascriptAndWaitForOk(base::StringPrintf( 319 "%s({video: true, audio: true});", kGetUserMediaAndStop)); 320 } 321 322 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 323 GetAudioAndVideoStreamAndClone) { 324 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 325 326 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 327 NavigateToURL(shell(), url); 328 329 ExecuteJavascriptAndWaitForOk("getUserMediaAndClone();"); 330 } 331 332 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 333 RenderVideoTrackInMultipleTagsAndPause) { 334 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 335 336 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 337 NavigateToURL(shell(), url); 338 339 ExecuteJavascriptAndWaitForOk("getUserMediaAndRenderInSeveralVideoTags();"); 340 } 341 342 343 344 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 345 GetUserMediaWithMandatorySourceID) { 346 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 347 348 std::vector<std::string> audio_ids; 349 std::vector<std::string> video_ids; 350 GetInputDevices(&audio_ids, &video_ids); 351 352 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 353 354 // Test all combinations of mandatory sourceID; 355 for (std::vector<std::string>::const_iterator video_it = video_ids.begin(); 356 video_it != video_ids.end(); ++video_it) { 357 for (std::vector<std::string>::const_iterator audio_it = audio_ids.begin(); 358 audio_it != audio_ids.end(); ++audio_it) { 359 NavigateToURL(shell(), url); 360 EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult( 361 GenerateGetUserMediaWithMandatorySourceID( 362 kGetUserMediaAndStop, 363 *audio_it, 364 *video_it))); 365 } 366 } 367 } 368 369 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 370 GetUserMediaWithInvalidMandatorySourceID) { 371 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 372 373 std::vector<std::string> audio_ids; 374 std::vector<std::string> video_ids; 375 GetInputDevices(&audio_ids, &video_ids); 376 377 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 378 379 // Test with invalid mandatory audio sourceID. 380 NavigateToURL(shell(), url); 381 EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult( 382 GenerateGetUserMediaWithMandatorySourceID( 383 kGetUserMediaAndExpectFailure, 384 "something invalid", 385 video_ids[0]))); 386 387 // Test with invalid mandatory video sourceID. 388 EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult( 389 GenerateGetUserMediaWithMandatorySourceID( 390 kGetUserMediaAndExpectFailure, 391 audio_ids[0], 392 "something invalid"))); 393 394 // Test with empty mandatory audio sourceID. 395 EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult( 396 GenerateGetUserMediaWithMandatorySourceID( 397 kGetUserMediaAndExpectFailure, 398 "", 399 video_ids[0]))); 400 } 401 402 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 403 GetUserMediaWithInvalidOptionalSourceID) { 404 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 405 406 std::vector<std::string> audio_ids; 407 std::vector<std::string> video_ids; 408 GetInputDevices(&audio_ids, &video_ids); 409 410 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 411 412 // Test with invalid optional audio sourceID. 413 NavigateToURL(shell(), url); 414 EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult( 415 GenerateGetUserMediaWithOptionalSourceID( 416 kGetUserMediaAndStop, 417 "something invalid", 418 video_ids[0]))); 419 420 // Test with invalid optional video sourceID. 421 EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult( 422 GenerateGetUserMediaWithOptionalSourceID( 423 kGetUserMediaAndStop, 424 audio_ids[0], 425 "something invalid"))); 426 427 // Test with empty optional audio sourceID. 428 EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult( 429 GenerateGetUserMediaWithOptionalSourceID( 430 kGetUserMediaAndStop, 431 "", 432 video_ids[0]))); 433 } 434 435 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) { 436 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 437 438 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 439 NavigateToURL(shell(), url); 440 441 ExecuteJavascriptAndWaitForOk( 442 "twoGetUserMediaAndStop({video: true, audio: true});"); 443 } 444 445 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 446 TwoGetUserMediaWithEqualConstraints) { 447 std::string constraints1 = "{video: true, audio: true}"; 448 const std::string& constraints2 = constraints1; 449 std::string expected_result = "w=640:h=480-w=640:h=480"; 450 451 RunTwoGetTwoGetUserMediaWithDifferentContraints(constraints1, constraints2, 452 expected_result); 453 } 454 455 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 456 TwoGetUserMediaWithSecondVideoCropped) { 457 std::string constraints1 = "{video: true}"; 458 std::string constraints2 = "{video: {mandatory: {maxHeight: 360}}}"; 459 std::string expected_result = "w=640:h=480-w=640:h=360"; 460 RunTwoGetTwoGetUserMediaWithDifferentContraints(constraints1, constraints2, 461 expected_result); 462 } 463 464 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 465 TwoGetUserMediaWithFirstHdSecondVga) { 466 std::string constraints1 = 467 "{video: {mandatory: {minWidth:1280 , minHeight: 720}}}"; 468 std::string constraints2 = 469 "{video: {mandatory: {maxWidth:640 , maxHeight: 480}}}"; 470 std::string expected_result = "w=1280:h=720-w=640:h=480"; 471 RunTwoGetTwoGetUserMediaWithDifferentContraints(constraints1, constraints2, 472 expected_result); 473 } 474 475 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 476 GetUserMediaWithTooHighVideoConstraintsValues) { 477 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 478 479 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 480 481 int large_value = 99999; 482 std::string call = GenerateGetUserMediaCall(kGetUserMediaAndExpectFailure, 483 large_value, 484 large_value, 485 large_value, 486 large_value, 487 large_value, 488 large_value); 489 NavigateToURL(shell(), url); 490 491 // TODO(perkj): A proper error code should be returned by gUM. 492 EXPECT_EQ("TrackStartError", ExecuteJavascriptAndReturnResult(call)); 493 } 494 495 // This test will make a simple getUserMedia page, verify that video is playing 496 // in a simple local <video>, and for a couple of seconds, collect some 497 // performance traces from VideoCaptureController colorspace conversion and 498 // potential resizing. 499 IN_PROC_BROWSER_TEST_P( 500 WebRtcGetUserMediaBrowserTest, 501 TraceVideoCaptureControllerPerformanceDuringGetUserMedia) { 502 RunGetUserMediaAndCollectMeasures( 503 10, 504 "VideoCaptureController::OnIncomingCapturedData", 505 "VideoCaptureController"); 506 } 507 508 // This test calls getUserMedia and checks for aspect ratio behavior. 509 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 510 TestGetUserMediaAspectRatio4To3) { 511 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 512 513 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 514 515 std::string constraints_4_3 = GenerateGetUserMediaCall( 516 kGetUserMediaAndAnalyseAndStop, 640, 640, 480, 480, 10, 30); 517 518 NavigateToURL(shell(), url); 519 ASSERT_EQ("w=640:h=480", 520 ExecuteJavascriptAndReturnResult(constraints_4_3)); 521 } 522 523 // This test calls getUserMedia and checks for aspect ratio behavior. 524 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 525 TestGetUserMediaAspectRatio16To9) { 526 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 527 528 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 529 530 std::string constraints_16_9 = GenerateGetUserMediaCall( 531 kGetUserMediaAndAnalyseAndStop, 640, 640, 360, 360, 10, 30); 532 533 NavigateToURL(shell(), url); 534 ASSERT_EQ("w=640:h=360", 535 ExecuteJavascriptAndReturnResult(constraints_16_9)); 536 } 537 538 // This test calls getUserMedia and checks for aspect ratio behavior. 539 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, 540 TestGetUserMediaAspectRatio1To1) { 541 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 542 543 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 544 545 std::string constraints_1_1 = GenerateGetUserMediaCall( 546 kGetUserMediaAndAnalyseAndStop, 320, 320, 320, 320, 10, 30); 547 548 NavigateToURL(shell(), url); 549 ASSERT_EQ("w=320:h=320", 550 ExecuteJavascriptAndReturnResult(constraints_1_1)); 551 } 552 553 namespace { 554 555 struct UserMediaSizes { 556 int min_width; 557 int max_width; 558 int min_height; 559 int max_height; 560 int min_frame_rate; 561 int max_frame_rate; 562 }; 563 564 } // namespace 565 566 class WebRtcConstraintsBrowserTest 567 : public WebRtcContentBrowserTest, 568 public testing::WithParamInterface<UserMediaSizes> { 569 public: 570 WebRtcConstraintsBrowserTest() : user_media_(GetParam()) {} 571 const UserMediaSizes& user_media() const { return user_media_; } 572 573 private: 574 UserMediaSizes user_media_; 575 }; 576 577 // This test calls getUserMedia in sequence with different constraints. 578 IN_PROC_BROWSER_TEST_P(WebRtcConstraintsBrowserTest, GetUserMediaConstraints) { 579 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 580 581 GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); 582 583 std::string call = GenerateGetUserMediaCall(kGetUserMediaAndStop, 584 user_media().min_width, 585 user_media().max_width, 586 user_media().min_height, 587 user_media().max_height, 588 user_media().min_frame_rate, 589 user_media().max_frame_rate); 590 DVLOG(1) << "Calling getUserMedia: " << call; 591 NavigateToURL(shell(), url); 592 ExecuteJavascriptAndWaitForOk(call); 593 } 594 595 static const UserMediaSizes kAllUserMediaSizes[] = { 596 {320, 320, 180, 180, 10, 30}, 597 {320, 320, 240, 240, 10, 30}, 598 {640, 640, 360, 360, 10, 30}, 599 {640, 640, 480, 480, 10, 30}, 600 {960, 960, 720, 720, 10, 30}, 601 {1280, 1280, 720, 720, 10, 30}}; 602 603 INSTANTIATE_TEST_CASE_P(UserMedia, 604 WebRtcConstraintsBrowserTest, 605 testing::ValuesIn(kAllUserMediaSizes)); 606 607 } // namespace content 608