| // Copyright 2020 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/task/thread_pool/thread_pool_instance.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/lite_video/lite_video_switches.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/metrics/content/subprocess_metrics_provider.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "media/base/media_switches.h" |
| #include "media/base/test_data_util.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| #include "url/url_util.h" |
| |
| namespace { |
| |
| // Retries fetching |histogram_name| until it contains at least |count| samples. |
| void RetryForHistogramUntilCountReached( |
| const base::HistogramTester& histogram_tester, |
| const std::string& histogram_name, |
| size_t count) { |
| while (true) { |
| base::ThreadPoolInstance::Get()->FlushForTesting(); |
| base::RunLoop().RunUntilIdle(); |
| |
| content::FetchHistogramsFromChildProcesses(); |
| metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); |
| |
| const std::vector<base::Bucket> buckets = |
| histogram_tester.GetAllSamples(histogram_name); |
| size_t total_count = 0; |
| for (const auto& bucket : buckets) { |
| total_count += bucket.count; |
| } |
| if (total_count >= count) { |
| break; |
| } |
| } |
| } |
| |
| class LiteVideoBrowserTest : public InProcessBrowserTest { |
| public: |
| explicit LiteVideoBrowserTest(bool enable_lite_mode = true, |
| bool enable_lite_video_feature = true) |
| : enable_lite_mode_(enable_lite_mode) { |
| std::vector<base::Feature> enabled_features; |
| if (enable_lite_video_feature) |
| enabled_features.push_back(features::kLiteVideo); |
| |
| std::vector<base::Feature> disabled_features = { |
| // Disable fallback after decode error to avoid unexpected test pass on |
| // the fallback path. |
| media::kFallbackAfterDecodeError, |
| |
| // Disable out of process audio on Linux due to process spawn |
| // failures. http://crbug.com/986021 |
| features::kAudioServiceOutOfProcess, |
| }; |
| |
| scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); |
| } |
| |
| ~LiteVideoBrowserTest() override = default; |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| command_line->AppendSwitchASCII( |
| switches::kAutoplayPolicy, |
| switches::autoplay::kNoUserGestureRequiredPolicy); |
| if (enable_lite_mode_) |
| command_line->AppendSwitch("enable-spdy-proxy-auth"); |
| command_line->AppendSwitch( |
| lite_video::switches::kLiteVideoForceOverrideDecision); |
| } |
| |
| void SetUp() override { |
| http_server_.ServeFilesFromSourceDirectory(media::GetTestDataPath()); |
| ASSERT_TRUE(http_server_.Start()); |
| InProcessBrowserTest::SetUp(); |
| } |
| |
| void TestMSEPlayback(const std::string& media_file, |
| const std::string& segment_duration, |
| const std::string& segment_fetch_delay_before_end, |
| bool has_subframe_video) { |
| base::StringPairs query_params; |
| std::string media_files = media_file; |
| // Add few media segments, separated by ';' |
| media_files += ";" + media_file + "?id=1"; |
| media_files += ";" + media_file + "?id=2"; |
| media_files += ";" + media_file + "?id=3"; |
| media_files += ";" + media_file + "?id=4"; |
| query_params.emplace_back("mediaFile", media_files); |
| query_params.emplace_back("mediaType", |
| media::GetMimeTypeForFile(media_file)); |
| query_params.emplace_back("MSESegmentDurationMS", segment_duration); |
| query_params.emplace_back("MSESegmentFetchDelayBeforeEndMS", |
| segment_fetch_delay_before_end); |
| RunMediaTestPage( |
| has_subframe_video ? "multi_frame_mse_player.html" : "mse_player.html", |
| query_params, base::ASCIIToUTF16(media::kEnded)); |
| } |
| |
| // Runs a html page with a list of URL query parameters. |
| // The test starts a local http test server to load the test page |
| void RunMediaTestPage(const std::string& html_page, |
| const base::StringPairs& query_params, |
| const base::string16& expected_title) { |
| std::string query = media::GetURLQueryString(query_params); |
| content::TitleWatcher title_watcher( |
| browser()->tab_strip_model()->GetActiveWebContents(), expected_title); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL( |
| browser(), http_server_.GetURL("/" + html_page + "?" + query))); |
| EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| } |
| |
| const base::HistogramTester& histogram_tester() { return histogram_tester_; } |
| |
| private: |
| bool enable_lite_mode_; // Whether LiteMode is enabled. |
| base::test::ScopedFeatureList scoped_feature_list_; |
| net::EmbeddedTestServer http_server_; |
| base::HistogramTester histogram_tester_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LiteVideoBrowserTest); |
| }; |
| // Fails occasionally on ChromeOS, MacOS, Win. http://crbug.com/1111570 |
| // Need to make tests more reliable but feature only targeted |
| // for Android. Currently there are potential race conditions |
| // on throttle timing and counts |
| #if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS) |
| #define DISABLE_ON_WIN_MAC_CHROMEOS(x) DISABLED_##x |
| #else |
| #define DISABLE_ON_WIN_MAC_CHROMEOS(x) x |
| #endif |
| |
| IN_PROC_BROWSER_TEST_F(LiteVideoBrowserTest, |
| DISABLE_ON_WIN_MAC_CHROMEOS(SimplePlayback)) { |
| TestMSEPlayback("bear-vp9.webm", "2000", "2000", false); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "Media.VideoHeight.Initial.MSE", 1); |
| |
| histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); |
| |
| // Verify that at least 1 request was throttled. There will be 5 requests |
| // made and the hint is available. |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "LiteVideo.URLLoader.ThrottleLatency", 1); |
| } |
| |
| class LiteVideoWithLiteModeDisabledBrowserTest : public LiteVideoBrowserTest { |
| public: |
| LiteVideoWithLiteModeDisabledBrowserTest() |
| : LiteVideoBrowserTest(false /*enable_lite_mode*/, |
| true /*enable_lite_video_feature*/) {} |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(LiteVideoWithLiteModeDisabledBrowserTest, |
| VideoThrottleDisabled) { |
| TestMSEPlayback("bear-vp9.webm", "2000", "2000", false); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "Media.VideoHeight.Initial.MSE", 1); |
| |
| histogram_tester().ExpectTotalCount("LiteVideo.HintAgent.HasHint", 0); |
| histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LiteVideoBrowserTest, |
| MSEPlaybackStalledDueToBufferUnderflow) { |
| TestMSEPlayback("bear-vp9.webm", "2700", "500", false); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "Media.VideoHeight.Initial.MSE", 1); |
| |
| histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); |
| // Verify some responses were throttled and some video stalls were |
| // encountered. |
| EXPECT_GE(1U, histogram_tester() |
| .GetAllSamples("LiteVideo.URLLoader.ThrottleLatency") |
| .size()); |
| EXPECT_GE(1U, histogram_tester() |
| .GetAllSamples("LiteVideo.HintsAgent.StopThrottling") |
| .size()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LiteVideoBrowserTest, |
| MSEPlaybackStalledDueToBufferUnderflow_WithSubframe) { |
| TestMSEPlayback("bear-vp9.webm", "2700", "500", true); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "Media.VideoHeight.Initial.MSE", 1); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "LiteVideo.HintAgent.HasHint", 2); |
| histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 2); |
| // Verify some responses were throttled and some video stalls were |
| // encountered. |
| EXPECT_GE(2U, histogram_tester() |
| .GetAllSamples("LiteVideo.URLLoader.ThrottleLatency") |
| .size()); |
| EXPECT_GE(2U, histogram_tester() |
| .GetAllSamples("LiteVideo.HintsAgent.StopThrottling") |
| .size()); |
| } |
| |
| class LiteVideoAndLiteModeDisabledBrowserTest : public LiteVideoBrowserTest { |
| public: |
| LiteVideoAndLiteModeDisabledBrowserTest() |
| : LiteVideoBrowserTest(false /*enable_lite_mode*/, |
| false /*enable_lite_video_feature*/) {} |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(LiteVideoAndLiteModeDisabledBrowserTest, |
| VideoThrottleDisabled) { |
| TestMSEPlayback("bear-vp9.webm", "2000", "2000", false); |
| |
| RetryForHistogramUntilCountReached(histogram_tester(), |
| "Media.VideoHeight.Initial.MSE", 1); |
| |
| histogram_tester().ExpectTotalCount("LiteVideo.HintAgent.HasHint", 0); |
| histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 0); |
| } |
| |
| } // namespace |