| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/command_line.h" |
| #include "base/file_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/values.h" |
| #include "content/browser/media/webrtc_internals.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "content/test/webrtc_content_browsertest_base.h" |
| #include "media/audio/audio_manager.h" |
| #include "media/base/media_switches.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #endif |
| |
| #if defined (OS_ANDROID) || defined(THREAD_SANITIZER) |
| // Just do the bare minimum of audio checking on Android and under TSAN since |
| // it's a bit sensitive to device performance. |
| static const char kUseLenientAudioChecking[] = "true"; |
| #else |
| static const char kUseLenientAudioChecking[] = "false"; |
| #endif |
| |
| namespace content { |
| |
| class WebRtcBrowserTest : public WebRtcContentBrowserTest, |
| public testing::WithParamInterface<bool> { |
| public: |
| WebRtcBrowserTest() {} |
| virtual ~WebRtcBrowserTest() {} |
| |
| virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| WebRtcContentBrowserTest::SetUpCommandLine(command_line); |
| |
| bool enable_audio_track_processing = GetParam(); |
| if (!enable_audio_track_processing) |
| command_line->AppendSwitch(switches::kDisableAudioTrackProcessing); |
| } |
| |
| // Convenience function since most peerconnection-call.html tests just load |
| // the page, kick off some javascript and wait for the title to change to OK. |
| void MakeTypicalPeerConnectionCall(const std::string& javascript) { |
| ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| |
| GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); |
| NavigateToURL(shell(), url); |
| |
| DisableOpusIfOnAndroid(); |
| ExecuteJavascriptAndWaitForOk(javascript); |
| } |
| |
| // Convenience method for making calls that detect if audio os playing (which |
| // has some special prerequisites, such that there needs to be an audio output |
| // device on the executing machine). |
| void MakeAudioDetectingPeerConnectionCall(const std::string& javascript) { |
| if (!media::AudioManager::Get()->HasAudioOutputDevices()) { |
| // Bots with no output devices will force the audio code into a state |
| // where it doesn't manage to set either the low or high latency path. |
| // This test will compute useless values in that case, so skip running on |
| // such bots (see crbug.com/326338). |
| LOG(INFO) << "Missing output devices: skipping test..."; |
| return; |
| } |
| |
| ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kUseFakeDeviceForMediaStream)) |
| << "Must run with fake devices since the test will explicitly look " |
| << "for the fake device signal."; |
| |
| MakeTypicalPeerConnectionCall(javascript); |
| } |
| |
| void DisableOpusIfOnAndroid() { |
| #if defined(OS_ANDROID) |
| // Always force iSAC 16K on Android for now (Opus is broken). |
| EXPECT_EQ("isac-forced", |
| ExecuteJavascriptAndReturnResult("forceIsac16KInSdp();")); |
| #endif |
| } |
| }; |
| |
| static const bool kRunTestsWithFlag[] = { false, true }; |
| INSTANTIATE_TEST_CASE_P(WebRtcBrowserTests, |
| WebRtcBrowserTest, |
| testing::ValuesIn(kRunTestsWithFlag)); |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CanSetupDefaultVideoCall DISABLED_CanSetupDefaultVideoCall |
| #else |
| #define MAYBE_CanSetupDefaultVideoCall CanSetupDefaultVideoCall |
| #endif |
| |
| // These tests will make a complete PeerConnection-based call and verify that |
| // video is playing for the call. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupDefaultVideoCall) { |
| MakeTypicalPeerConnectionCall( |
| "callAndExpectResolution({video: true}, 640, 480);"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CanSetupVideoCallWith1To1AspecRatio) { |
| const std::string javascript = |
| "callAndExpectResolution({video: {mandatory: {minWidth: 320," |
| " maxWidth: 320, minHeight: 320, maxHeight: 320}}}, 320, 320);"; |
| MakeTypicalPeerConnectionCall(javascript); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| CanSetupVideoCallWith16To9AspecRatio) { |
| const std::string javascript = |
| "callAndExpectResolution({video: {mandatory: {minWidth: 640," |
| " maxWidth: 640, minAspectRatio: 1.777}}}, 640, 360);"; |
| MakeTypicalPeerConnectionCall(javascript); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| CanSetupVideoCallWith4To3AspecRatio) { |
| const std::string javascript = |
| "callAndExpectResolution({video: {mandatory: {minWidth: 960," |
| "maxAspectRatio: 1.333}}}, 960, 720);"; |
| MakeTypicalPeerConnectionCall(javascript); |
| } |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux, see http://crbug.com/240376 |
| #define MAYBE_CanSetupAudioAndVideoCall DISABLED_CanSetupAudioAndVideoCall |
| #else |
| #define MAYBE_CanSetupAudioAndVideoCall CanSetupAudioAndVideoCall |
| #endif |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) { |
| MakeTypicalPeerConnectionCall("call({video: true, audio: true});"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) { |
| MakeTypicalPeerConnectionCall("callAndSendDtmf(\'123,abc\');"); |
| } |
| |
| // TODO(phoglund): this test fails because the peer connection state will be |
| // stable in the second negotiation round rather than have-local-offer. |
| // http://crbug.com/293125. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) { |
| const char* kJavascript = |
| "callEmptyThenAddOneStreamAndRenegotiate({video: true, audio: true});"; |
| MakeTypicalPeerConnectionCall(kJavascript); |
| } |
| |
| // Below 2 test will make a complete PeerConnection-based call between pc1 and |
| // pc2, and then use the remote stream to setup a call between pc3 and pc4, and |
| // then verify that video is received on pc3 and pc4. |
| // The stream sent from pc3 to pc4 is the stream received on pc1. |
| // The stream sent from pc4 to pc3 is cloned from stream the stream received |
| // on pc2. |
| // Flaky on win xp. http://crbug.com/304775 |
| #if defined(OS_WIN) |
| #define MAYBE_CanForwardRemoteStream DISABLED_CanForwardRemoteStream |
| #define MAYBE_CanForwardRemoteStream720p DISABLED_CanForwardRemoteStream720p |
| #else |
| #define MAYBE_CanForwardRemoteStream CanForwardRemoteStream |
| // Flaky on TSAN v2. http://crbug.com/373637 |
| #if defined(THREAD_SANITIZER) |
| #define MAYBE_CanForwardRemoteStream720p DISABLED_CanForwardRemoteStream720p |
| #else |
| #define MAYBE_CanForwardRemoteStream720p CanForwardRemoteStream720p |
| #endif |
| #endif |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream) { |
| #if defined (OS_ANDROID) |
| // This test fails on Nexus 5 devices. |
| // TODO(henrika): see http://crbug.com/362437 and http://crbug.com/359389 |
| // for details. |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kDisableWebRtcHWDecoding); |
| #endif |
| MakeTypicalPeerConnectionCall( |
| "callAndForwardRemoteStream({video: true, audio: false});"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream720p) { |
| #if defined (OS_ANDROID) |
| // This test fails on Nexus 5 devices. |
| // TODO(henrika): see http://crbug.com/362437 and http://crbug.com/359389 |
| // for details. |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kDisableWebRtcHWDecoding); |
| #endif |
| const std::string javascript = GenerateGetUserMediaCall( |
| "callAndForwardRemoteStream", 1280, 1280, 720, 720, 10, 30); |
| MakeTypicalPeerConnectionCall(javascript); |
| } |
| |
| // This test will make a complete PeerConnection-based call but remove the |
| // MSID and bundle attribute from the initial offer to verify that |
| // video is playing for the call even if the initiating client don't support |
| // MSID. http://tools.ietf.org/html/draft-alvestrand-rtcweb-msid-02 |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux, see http://crbug.com/240373 |
| #define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle\ |
| DISABLED_CanSetupAudioAndVideoCallWithoutMsidAndBundle |
| #else |
| #define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle\ |
| CanSetupAudioAndVideoCallWithoutMsidAndBundle |
| #endif |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) { |
| MakeTypicalPeerConnectionCall("callWithoutMsidAndBundle();"); |
| } |
| |
| // This test will modify the SDP offer to an unsupported codec, which should |
| // cause SetLocalDescription to fail. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateUnsupportedVideoCodec) { |
| MakeTypicalPeerConnectionCall("negotiateUnsupportedVideoCodec();"); |
| } |
| |
| // This test will modify the SDP offer to use no encryption, which should |
| // cause SetLocalDescription to fail. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateNonCryptoCall) { |
| MakeTypicalPeerConnectionCall("negotiateNonCryptoCall();"); |
| } |
| |
| // This test can negotiate an SDP offer that includes a b=AS:xx to control |
| // the bandwidth for audio and video |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateOfferWithBLine) { |
| MakeTypicalPeerConnectionCall("negotiateOfferWithBLine();"); |
| } |
| |
| // This test will make a complete PeerConnection-based call using legacy SDP |
| // settings: GIce, external SDES, and no BUNDLE. |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux, see http://crbug.com/240373 |
| #define MAYBE_CanSetupLegacyCall DISABLED_CanSetupLegacyCall |
| #else |
| #define MAYBE_CanSetupLegacyCall CanSetupLegacyCall |
| #endif |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupLegacyCall) { |
| MakeTypicalPeerConnectionCall("callWithLegacySdp();"); |
| } |
| |
| // This test will make a PeerConnection-based call and test an unreliable text |
| // dataChannel. |
| // TODO(mallinath) - Remove this test after rtp based data channel is disabled. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallWithDataOnly) { |
| MakeTypicalPeerConnectionCall("callWithDataOnly();"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallWithSctpDataOnly) { |
| MakeTypicalPeerConnectionCall("callWithSctpDataOnly();"); |
| } |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithDataAndMedia DISABLED_CallWithDataAndMedia |
| #else |
| #define MAYBE_CallWithDataAndMedia CallWithDataAndMedia |
| #endif |
| |
| // This test will make a PeerConnection-based call and test an unreliable text |
| // dataChannel and audio and video tracks. |
| // TODO(mallinath) - Remove this test after rtp based data channel is disabled. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, DISABLED_CallWithDataAndMedia) { |
| MakeTypicalPeerConnectionCall("callWithDataAndMedia();"); |
| } |
| |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithSctpDataAndMedia DISABLED_CallWithSctpDataAndMedia |
| #else |
| #define MAYBE_CallWithSctpDataAndMedia CallWithSctpDataAndMedia |
| #endif |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| MAYBE_CallWithSctpDataAndMedia) { |
| MakeTypicalPeerConnectionCall("callWithSctpDataAndMedia();"); |
| } |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithDataAndLaterAddMedia DISABLED_CallWithDataAndLaterAddMedia |
| #else |
| // Temporarily disable the test on all platforms. http://crbug.com/293252 |
| #define MAYBE_CallWithDataAndLaterAddMedia DISABLED_CallWithDataAndLaterAddMedia |
| #endif |
| |
| // This test will make a PeerConnection-based call and test an unreliable text |
| // dataChannel and later add an audio and video track. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithDataAndLaterAddMedia) { |
| MakeTypicalPeerConnectionCall("callWithDataAndLaterAddMedia();"); |
| } |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithNewVideoMediaStream DISABLED_CallWithNewVideoMediaStream |
| #else |
| #define MAYBE_CallWithNewVideoMediaStream CallWithNewVideoMediaStream |
| #endif |
| |
| // This test will make a PeerConnection-based call and send a new Video |
| // MediaStream that has been created based on a MediaStream created with |
| // getUserMedia. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithNewVideoMediaStream) { |
| MakeTypicalPeerConnectionCall("callWithNewVideoMediaStream();"); |
| } |
| |
| // This test will make a PeerConnection-based call and send a new Video |
| // MediaStream that has been created based on a MediaStream created with |
| // getUserMedia. When video is flowing, the VideoTrack is removed and an |
| // AudioTrack is added instead. |
| // TODO(phoglund): This test is manual since not all buildbots has an audio |
| // input. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_CallAndModifyStream) { |
| MakeTypicalPeerConnectionCall( |
| "callWithNewVideoMediaStreamLaterSwitchToAudio();"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, AddTwoMediaStreamsToOnePC) { |
| MakeTypicalPeerConnectionCall("addTwoMediaStreamsToOneConnection();"); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| EstablishAudioVideoCallAndEnsureAudioIsPlaying) { |
| MakeAudioDetectingPeerConnectionCall(base::StringPrintf( |
| "callAndEnsureAudioIsPlaying(%s, {audio:true, video:true});", |
| kUseLenientAudioChecking)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| EstablishAudioOnlyCallAndEnsureAudioIsPlaying) { |
| MakeAudioDetectingPeerConnectionCall(base::StringPrintf( |
| "callAndEnsureAudioIsPlaying(%s, {audio:true});", |
| kUseLenientAudioChecking)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| EstablishAudioVideoCallAndVerifyMutingWorks) { |
| MakeAudioDetectingPeerConnectionCall(base::StringPrintf( |
| "callAndEnsureAudioTrackMutingWorks(%s);", kUseLenientAudioChecking)); |
| } |
| |
| // Flaky on TSAN v2: http://crbug.com/373637 |
| #if defined(THREAD_SANITIZER) |
| #define MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks\ |
| DISABLED_EstablishAudioVideoCallAndVerifyUnmutingWorks |
| #else |
| #define MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks\ |
| EstablishAudioVideoCallAndVerifyUnmutingWorks |
| #endif |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks) { |
| MakeAudioDetectingPeerConnectionCall(base::StringPrintf( |
| "callAndEnsureAudioTrackUnmutingWorks(%s);", kUseLenientAudioChecking)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) { |
| MakeTypicalPeerConnectionCall("callAndEnsureVideoTrackMutingWorks();"); |
| } |
| |
| #if defined(OS_WIN) |
| #define IntToStringType base::IntToString16 |
| #else |
| #define IntToStringType base::IntToString |
| #endif |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithAecDump DISABLED_CallWithAecDump |
| #else |
| #define MAYBE_CallWithAecDump CallWithAecDump |
| #endif |
| |
| // This tests will make a complete PeerConnection-based call, verify that |
| // video is playing for the call, and verify that a non-empty AEC dump file |
| // exists. The AEC dump is enabled through webrtc-internals. The HTML and |
| // Javascript is bypassed since it would trigger a file picker dialog. Instead, |
| // the dialog callback FileSelected() is invoked directly. In fact, there's |
| // never a webrtc-internals page opened at all since that's not needed. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithAecDump) { |
| ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| |
| // We must navigate somewhere first so that the render process is created. |
| NavigateToURL(shell(), GURL("")); |
| |
| base::FilePath dump_file; |
| ASSERT_TRUE(CreateTemporaryFile(&dump_file)); |
| |
| // This fakes the behavior of another open tab with webrtc-internals, and |
| // enabling AEC dump in that tab. |
| WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL); |
| |
| GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); |
| NavigateToURL(shell(), url); |
| DisableOpusIfOnAndroid(); |
| ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});"); |
| |
| // Get the ID for the render process host. There should only be one. |
| RenderProcessHost::iterator it( |
| content::RenderProcessHost::AllHostsIterator()); |
| int render_process_host_id = it.GetCurrentValue()->GetID(); |
| EXPECT_GE(render_process_host_id, 0); |
| |
| // Add file extensions that we expect to be added. |
| static const int kExpectedConsumerId = 0; |
| dump_file = dump_file.AddExtension(IntToStringType(render_process_host_id)) |
| .AddExtension(IntToStringType(kExpectedConsumerId)); |
| |
| EXPECT_TRUE(base::PathExists(dump_file)); |
| int64 file_size = 0; |
| EXPECT_TRUE(base::GetFileSize(dump_file, &file_size)); |
| EXPECT_GT(file_size, 0); |
| |
| base::DeleteFile(dump_file, false); |
| } |
| |
| // TODO(grunell): Add test for multiple dumps when re-use of |
| // MediaStreamAudioProcessor in AudioCapturer has been removed. |
| |
| #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) |
| // Timing out on ARM linux bot: http://crbug.com/238490 |
| #define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled |
| #else |
| #define MAYBE_CallWithAecDumpEnabledThenDisabled CallWithAecDumpEnabledThenDisabled |
| #endif |
| |
| // As above, but enable and disable dump before starting a call. The file should |
| // be created, but should be empty. |
| IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, |
| MAYBE_CallWithAecDumpEnabledThenDisabled) { |
| ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| |
| // We must navigate somewhere first so that the render process is created. |
| NavigateToURL(shell(), GURL("")); |
| |
| base::FilePath dump_file; |
| ASSERT_TRUE(CreateTemporaryFile(&dump_file)); |
| |
| // This fakes the behavior of another open tab with webrtc-internals, and |
| // enabling AEC dump in that tab, then disabling it. |
| WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL); |
| WebRTCInternals::GetInstance()->DisableAecDump(); |
| |
| GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); |
| NavigateToURL(shell(), url); |
| DisableOpusIfOnAndroid(); |
| ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});"); |
| |
| EXPECT_TRUE(base::PathExists(dump_file)); |
| int64 file_size = 0; |
| EXPECT_TRUE(base::GetFileSize(dump_file, &file_size)); |
| EXPECT_EQ(0, file_size); |
| |
| base::DeleteFile(dump_file, false); |
| } |
| |
| } // namespace content |