123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- // Copyright 2017 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 <stddef.h>
- #include <memory>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/run_loop.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/test_message_loop.h"
- #include "components/ukm/test_ukm_recorder.h"
- #include "media/mojo/services/media_metrics_provider.h"
- #include "media/mojo/services/watch_time_recorder.h"
- #include "mojo/public/cpp/bindings/remote.h"
- #include "services/metrics/public/cpp/ukm_builders.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "url/gurl.h"
- using UkmEntry = ukm::builders::Media_WebMediaPlayerState;
- namespace media {
- constexpr char kTestOrigin[] = "https://test.google.com/";
- class MediaMetricsProviderTest : public testing::Test {
- public:
- MediaMetricsProviderTest() { ResetMetricRecorders(); }
- MediaMetricsProviderTest(const MediaMetricsProviderTest&) = delete;
- MediaMetricsProviderTest& operator=(const MediaMetricsProviderTest&) = delete;
- ~MediaMetricsProviderTest() override { base::RunLoop().RunUntilIdle(); }
- void Initialize(bool is_mse,
- bool is_incognito,
- bool is_top_frame,
- const std::string& origin,
- mojom::MediaURLScheme scheme,
- mojom::MediaStreamType media_stream_type =
- mojom::MediaStreamType::kNone) {
- source_id_ = test_recorder_->GetNewSourceID();
- test_recorder_->UpdateSourceURL(source_id_, GURL(origin));
- MediaMetricsProvider::Create(
- (is_incognito ? MediaMetricsProvider::BrowsingMode::kIncognito
- : MediaMetricsProvider::BrowsingMode::kNormal),
- (is_top_frame ? MediaMetricsProvider::FrameStatus::kTopFrame
- : MediaMetricsProvider::FrameStatus::kNotTopFrame),
- GetSourceId(), learning::FeatureValue(0),
- VideoDecodePerfHistory::SaveCallback(),
- MediaMetricsProvider::GetLearningSessionCallback(),
- base::BindRepeating(
- &MediaMetricsProviderTest::GetRecordAggregateWatchTimeCallback,
- base::Unretained(this)),
- base::BindRepeating(&MediaMetricsProviderTest::IsShuttingDown,
- base::Unretained(this)),
- provider_.BindNewPipeAndPassReceiver());
- provider_->Initialize(is_mse, scheme, media_stream_type);
- }
- ukm::SourceId GetSourceId() { return source_id_; }
- MediaMetricsProvider::RecordAggregateWatchTimeCallback
- GetRecordAggregateWatchTimeCallback() {
- return base::NullCallback();
- }
- MOCK_METHOD(bool, IsShuttingDown, ());
- void ResetMetricRecorders() {
- // Ensure cleared global before attempting to create a new TestUkmReporter.
- test_recorder_.reset();
- test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
- }
- protected:
- base::TestMessageLoop message_loop_;
- std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_;
- ukm::SourceId source_id_;
- mojo::Remote<mojom::MediaMetricsProvider> provider_;
- };
- #define EXPECT_UKM(name, value) \
- test_recorder_->ExpectEntryMetric(entry, name, value)
- #define EXPECT_NO_UKM(name) \
- EXPECT_FALSE(test_recorder_->EntryHasMetric(entry, name))
- #define EXPECT_HAS_UKM(name) \
- EXPECT_TRUE(test_recorder_->EntryHasMetric(entry, name));
- TEST_F(MediaMetricsProviderTest, TestUkm) {
- Initialize(true, false, true, kTestOrigin, mojom::MediaURLScheme::kHttp);
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- {
- const auto& entries =
- test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
- EXPECT_EQ(1u, entries.size());
- for (const auto* entry : entries) {
- test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
- EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
- EXPECT_UKM(UkmEntry::kIsTopFrameName, true);
- EXPECT_UKM(UkmEntry::kIsEMEName, false);
- EXPECT_UKM(UkmEntry::kKeySystemName, 0);
- EXPECT_UKM(UkmEntry::kIsHardwareSecureName, false);
- EXPECT_UKM(UkmEntry::kIsMSEName, true);
- EXPECT_UKM(UkmEntry::kFinalPipelineStatusName, PIPELINE_OK);
- // This is an MSE playback so the URL scheme should not be set.
- EXPECT_NO_UKM(UkmEntry::kURLSchemeName);
- // This is an MSE playback so no container is available.
- EXPECT_NO_UKM(UkmEntry::kContainerNameName);
- EXPECT_NO_UKM(UkmEntry::kTimeToMetadataName);
- EXPECT_NO_UKM(UkmEntry::kTimeToFirstFrameName);
- EXPECT_NO_UKM(UkmEntry::kTimeToPlayReadyName);
- }
- }
- // Now try one with different values and optional parameters set.
- const std::string kTestOrigin2 = "https://test2.google.com/";
- const std::string kClearKeyKeySystem = "org.w3.clearkey";
- const base::TimeDelta kMetadataTime = base::Seconds(1);
- const base::TimeDelta kFirstFrameTime = base::Seconds(2);
- const base::TimeDelta kPlayReadyTime = base::Seconds(3);
- ResetMetricRecorders();
- Initialize(false, false, false, kTestOrigin2, mojom::MediaURLScheme::kHttps);
- provider_->SetIsEME();
- provider_->SetKeySystem(kClearKeyKeySystem);
- provider_->SetIsHardwareSecure();
- provider_->SetAudioPipelineInfo(
- {false, false, AudioDecoderType::kMojo, EncryptionType::kClear});
- provider_->SetVideoPipelineInfo(
- {false, false, VideoDecoderType::kMojo, EncryptionType::kEncrypted});
- provider_->SetTimeToMetadata(kMetadataTime);
- provider_->SetTimeToFirstFrame(kFirstFrameTime);
- provider_->SetTimeToPlayReady(kPlayReadyTime);
- provider_->SetContainerName(container_names::CONTAINER_MOV);
- provider_->OnError(PIPELINE_ERROR_DECODE);
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- {
- const auto& entries =
- test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
- EXPECT_EQ(1u, entries.size());
- for (const auto* entry : entries) {
- test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin2));
- EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
- EXPECT_UKM(UkmEntry::kIsTopFrameName, false);
- EXPECT_UKM(UkmEntry::kIsEMEName, true);
- EXPECT_UKM(UkmEntry::kKeySystemName, 1);
- EXPECT_UKM(UkmEntry::kIsHardwareSecureName, true);
- EXPECT_UKM(UkmEntry::kAudioEncryptionTypeName,
- static_cast<int64_t>(EncryptionType::kClear));
- EXPECT_UKM(UkmEntry::kVideoEncryptionTypeName,
- static_cast<int64_t>(EncryptionType::kEncrypted));
- EXPECT_UKM(UkmEntry::kIsMSEName, false);
- EXPECT_UKM(UkmEntry::kURLSchemeName,
- static_cast<int64_t>(mojom::MediaURLScheme::kHttps));
- EXPECT_UKM(UkmEntry::kFinalPipelineStatusName, PIPELINE_ERROR_DECODE);
- EXPECT_UKM(UkmEntry::kTimeToMetadataName, kMetadataTime.InMilliseconds());
- EXPECT_UKM(UkmEntry::kTimeToFirstFrameName,
- kFirstFrameTime.InMilliseconds());
- EXPECT_UKM(UkmEntry::kTimeToPlayReadyName,
- kPlayReadyTime.InMilliseconds());
- EXPECT_UKM(UkmEntry::kContainerNameName, container_names::CONTAINER_MOV);
- }
- }
- }
- TEST_F(MediaMetricsProviderTest, TestUkmMediaStream) {
- Initialize(true, false, true, kTestOrigin, mojom::MediaURLScheme::kMissing,
- mojom::MediaStreamType::kRemote);
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- {
- const auto& entries =
- test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
- EXPECT_EQ(0u, entries.size());
- }
- // Now try one with different values and optional parameters set.
- const std::string kTestOrigin2 = "https://test2.google.com/";
- const base::TimeDelta kMetadataTime = base::Seconds(1);
- const base::TimeDelta kFirstFrameTime = base::Seconds(2);
- const base::TimeDelta kPlayReadyTime = base::Seconds(3);
- ResetMetricRecorders();
- Initialize(false, false, false, kTestOrigin2, mojom::MediaURLScheme::kMissing,
- mojom::MediaStreamType::kLocalDeviceCapture);
- provider_->SetIsEME();
- provider_->SetTimeToMetadata(kMetadataTime);
- provider_->SetTimeToFirstFrame(kFirstFrameTime);
- provider_->SetTimeToPlayReady(kPlayReadyTime);
- provider_->SetContainerName(container_names::CONTAINER_MOV);
- provider_->OnError(PIPELINE_ERROR_DECODE);
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- {
- const auto& entries =
- test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
- EXPECT_EQ(0u, entries.size());
- }
- }
- TEST_F(MediaMetricsProviderTest, TestPipelineUMA) {
- base::HistogramTester histogram_tester;
- Initialize(false, false, false, kTestOrigin, mojom::MediaURLScheme::kHttps);
- provider_->SetAudioPipelineInfo(
- {false, false, AudioDecoderType::kMojo, EncryptionType::kClear});
- provider_->SetVideoPipelineInfo(
- {false, false, VideoDecoderType::kMojo, EncryptionType::kEncrypted});
- provider_->SetHasAudio(AudioCodec::kVorbis);
- provider_->SetHasVideo(VideoCodec::kVP9);
- provider_->SetHasPlayed();
- provider_->SetHaveEnough();
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectBucketCount("Media.PipelineStatus.AudioVideo.VP9.SW",
- PIPELINE_OK, 1);
- histogram_tester.ExpectBucketCount("Media.VideoDecoderFallback", false, 1);
- histogram_tester.ExpectBucketCount("Media.HasEverPlayed", true, 1);
- }
- TEST_F(MediaMetricsProviderTest, TestPipelineUMAMediaStream) {
- base::HistogramTester histogram_tester;
- Initialize(false, false, false, kTestOrigin, mojom::MediaURLScheme::kHttps,
- mojom::MediaStreamType::kRemote);
- provider_->SetAudioPipelineInfo(
- {false, false, AudioDecoderType::kMojo, EncryptionType::kClear});
- provider_->SetVideoPipelineInfo(
- {false, false, VideoDecoderType::kMojo, EncryptionType::kEncrypted});
- provider_->SetHasAudio(AudioCodec::kVorbis);
- provider_->SetHasVideo(VideoCodec::kVP9);
- provider_->SetHasPlayed();
- provider_->SetHaveEnough();
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectBucketCount("Media.PipelineStatus.AudioVideo.VP9.SW",
- PIPELINE_OK, 0);
- histogram_tester.ExpectBucketCount("Media.VideoDecoderFallback", false, 0);
- histogram_tester.ExpectBucketCount("Media.HasEverPlayed", true, 0);
- }
- TEST_F(MediaMetricsProviderTest, TestPipelineUMANoAudioWithEme) {
- base::HistogramTester histogram_tester;
- Initialize(false, false, false, kTestOrigin, mojom::MediaURLScheme::kHttps);
- provider_->SetIsEME();
- provider_->SetVideoPipelineInfo(
- {true, true, VideoDecoderType::kMojo, EncryptionType::kEncrypted});
- provider_->SetHasVideo(VideoCodec::kAV1);
- provider_->SetHasPlayed();
- provider_->SetHaveEnough();
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectBucketCount("Media.PipelineStatus.VideoOnly",
- PIPELINE_OK, 1);
- histogram_tester.ExpectBucketCount("Media.VideoDecoderFallback", false, 1);
- histogram_tester.ExpectBucketCount("Media.HasEverPlayed", true, 1);
- histogram_tester.ExpectBucketCount("Media.EME.IsIncognito", false, 1);
- }
- TEST_F(MediaMetricsProviderTest, TestPipelineUMADecoderFallback) {
- base::HistogramTester histogram_tester;
- Initialize(false, false, false, kTestOrigin, mojom::MediaURLScheme::kHttps);
- provider_->SetIsEME();
- provider_->SetAudioPipelineInfo(
- {false, false, AudioDecoderType::kMojo, EncryptionType::kClear});
- provider_->SetVideoPipelineInfo(
- {true, false, VideoDecoderType::kD3D11, EncryptionType::kEncrypted});
- provider_->SetHasVideo(VideoCodec::kVP9);
- provider_->SetHasAudio(AudioCodec::kVorbis);
- provider_->SetHasPlayed();
- provider_->SetHaveEnough();
- provider_->SetVideoPipelineInfo({true, false, VideoDecoderType::kFFmpeg});
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectBucketCount("Media.PipelineStatus.AudioVideo.VP9.HW",
- PIPELINE_OK, 1);
- histogram_tester.ExpectBucketCount("Media.VideoDecoderFallback", true, 1);
- histogram_tester.ExpectBucketCount("Media.HasEverPlayed", true, 1);
- }
- TEST_F(MediaMetricsProviderTest, TestPipelineUMARendererType) {
- base::HistogramTester histogram_tester;
- Initialize(false, false, false, kTestOrigin, mojom::MediaURLScheme::kHttps);
- provider_->SetIsEME();
- provider_->SetRendererType(RendererType::kMediaFoundation);
- provider_->SetHasVideo(VideoCodec::kVP9);
- provider_->SetHasAudio(AudioCodec::kVorbis);
- provider_->SetHasPlayed();
- provider_->SetHaveEnough();
- provider_.reset();
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectBucketCount(
- "Media.PipelineStatus.AudioVideo.VP9.MediaFoundationRenderer",
- PIPELINE_OK, 1);
- }
- // Note: Tests for various Acquire* methods are contained with the unittests for
- // their respective classes.
- #undef EXPECT_UKM
- #undef EXPECT_NO_UKM
- #undef EXPECT_HAS_UKM
- } // namespace media
|