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

Side by Side Diff: content/browser/media/media_internals_unittest.cc

Issue 2780533004: Start recording background video watch time. (Closed)
Patch Set: Fix copy-init issues. Created 3 years, 8 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/media_internals.cc ('k') | media/base/media_log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/media/media_internals.h" 5 #include "content/browser/media/media_internals.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/run_loop.h" 12 #include "base/run_loop.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/test/histogram_tester.h"
16 #include "base/test/test_message_loop.h"
17 #include "base/threading/thread_task_runner_handle.h"
15 #include "build/build_config.h" 18 #include "build/build_config.h"
16 #include "content/public/test/test_browser_thread_bundle.h" 19 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "media/base/audio_parameters.h" 20 #include "media/base/audio_parameters.h"
18 #include "media/base/channel_layout.h" 21 #include "media/base/channel_layout.h"
22 #include "media/base/media_log.h"
23 #include "media/blink/watch_time_reporter.h"
24 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/geometry/size.h" 26 #include "ui/gfx/geometry/size.h"
21 27
22 namespace { 28 namespace {
23 const int kTestComponentID = 0; 29 const int kTestComponentID = 0;
24 const char kTestDeviceID[] = "test-device-id"; 30 const char kTestDeviceID[] = "test-device-id";
25 31
26 // This class encapsulates a MediaInternals reference. It also has some useful 32 // This class encapsulates a MediaInternals reference. It also has some useful
27 // methods to receive a callback, deserialize its associated data and expect 33 // methods to receive a callback, deserialize its associated data and expect
28 // integer/string values. 34 // integer/string values.
29 class MediaInternalsTestBase { 35 class MediaInternalsTestBase {
30 public: 36 public:
31 MediaInternalsTestBase() 37 MediaInternalsTestBase()
32 : media_internals_(content::MediaInternals::GetInstance()) { 38 : media_internals_(content::MediaInternals::GetInstance()) {}
33 }
34 virtual ~MediaInternalsTestBase() {} 39 virtual ~MediaInternalsTestBase() {}
35 40
36 protected: 41 protected:
37 // Extracts and deserializes the JSON update data; merges into |update_data_|. 42 // Extracts and deserializes the JSON update data; merges into |update_data_|.
38 void UpdateCallbackImpl(const base::string16& update) { 43 void UpdateCallbackImpl(const base::string16& update) {
39 // Each update string looks like "<JavaScript Function Name>({<JSON>});" 44 // Each update string looks like "<JavaScript Function Name>({<JSON>});"
40 // or for video capabilities: "<JavaScript Function Name>([{<JSON>}]);". 45 // or for video capabilities: "<JavaScript Function Name>([{<JSON>}]);".
41 // In the second case we will be able to extract the dictionary if it is the 46 // In the second case we will be able to extract the dictionary if it is the
42 // only member of the list. 47 // only member of the list.
43 // To use the JSON reader we need to strip out the JS function name and (). 48 // To use the JSON reader we need to strip out the JS function name and ().
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID); 303 audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID);
299 base::RunLoop().RunUntilIdle(); 304 base::RunLoop().RunUntilIdle();
300 ExpectStatus("created"); 305 ExpectStatus("created");
301 306
302 audio_log_->OnClosed(kTestComponentID); 307 audio_log_->OnClosed(kTestComponentID);
303 base::RunLoop().RunUntilIdle(); 308 base::RunLoop().RunUntilIdle();
304 ExpectStatus("closed"); 309 ExpectStatus("closed");
305 } 310 }
306 311
307 INSTANTIATE_TEST_CASE_P( 312 INSTANTIATE_TEST_CASE_P(
308 MediaInternalsAudioLogTest, MediaInternalsAudioLogTest, testing::Values( 313 MediaInternalsAudioLogTest,
309 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, 314 MediaInternalsAudioLogTest,
310 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER, 315 testing::Values(media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
311 media::AudioLogFactory::AUDIO_OUTPUT_STREAM)); 316 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
317 media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
318
319 class DirectMediaLog : public media::MediaLog {
320 public:
321 explicit DirectMediaLog(int render_process_id)
322 : render_process_id_(render_process_id),
323 internals_(content::MediaInternals::GetInstance()) {}
324
325 void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {
326 std::vector<media::MediaLogEvent> events(1, *event);
327 internals_->OnMediaEvents(render_process_id_, events);
328 }
329
330 private:
331 ~DirectMediaLog() override {}
332
333 const int render_process_id_;
334 MediaInternals* const internals_;
335
336 DISALLOW_COPY_AND_ASSIGN(DirectMediaLog);
337 };
338
339 class MediaInternalsWatchTimeTest : public testing::Test,
340 public MediaInternalsTestBase {
341 public:
342 MediaInternalsWatchTimeTest()
343 : render_process_id_(0),
344 internals_(content::MediaInternals::GetInstance()),
345 media_log_(new DirectMediaLog(render_process_id_)),
346 histogram_tester_(new base::HistogramTester()),
347 watch_time_keys_(media::MediaLog::GetWatchTimeKeys()),
348 watch_time_power_keys_(media::MediaLog::GetWatchTimePowerKeys()) {}
349
350 void Initialize(bool has_audio,
351 bool has_video,
352 bool is_mse,
353 bool is_encrypted) {
354 wtr_.reset(new media::WatchTimeReporter(
355 has_audio, has_video, is_mse, is_encrypted, true, media_log_,
356 gfx::Size(800, 600),
357 base::Bind(&MediaInternalsWatchTimeTest::GetCurrentMediaTime,
358 base::Unretained(this))));
359 wtr_->set_reporting_interval_for_testing();
360 }
361
362 void CycleWatchTimeReporter() {
363 base::RunLoop run_loop;
364 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
365 run_loop.QuitClosure());
366 run_loop.Run();
367 }
368
369 void ExpectWatchTime(const std::vector<base::StringPiece>& keys,
370 base::TimeDelta value) {
371 for (auto key : watch_time_keys_) {
372 auto it = std::find(keys.begin(), keys.end(), key);
373 if (it == keys.end()) {
374 histogram_tester_->ExpectTotalCount(key.as_string(), 0);
375 } else {
376 histogram_tester_->ExpectUniqueSample(key.as_string(),
377 value.InMilliseconds(), 1);
378 }
379 }
380 }
381
382 void ResetHistogramTester() {
383 histogram_tester_.reset(new base::HistogramTester());
384 }
385
386 MOCK_METHOD0(GetCurrentMediaTime, base::TimeDelta());
387
388 protected:
389 const int render_process_id_;
390 MediaInternals* const internals_;
391 scoped_refptr<DirectMediaLog> media_log_;
392 std::unique_ptr<base::HistogramTester> histogram_tester_;
393 std::unique_ptr<media::WatchTimeReporter> wtr_;
394 const base::flat_set<base::StringPiece> watch_time_keys_;
395 const base::flat_set<base::StringPiece> watch_time_power_keys_;
396
397 DISALLOW_COPY_AND_ASSIGN(MediaInternalsWatchTimeTest);
398 };
399
400 TEST_F(MediaInternalsWatchTimeTest, BasicAudio) {
401 constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
402 constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
403 EXPECT_CALL(*this, GetCurrentMediaTime())
404 .WillOnce(testing::Return(base::TimeDelta()))
405 .WillOnce(testing::Return(kWatchTimeEarly))
406 .WillRepeatedly(testing::Return(kWatchTimeLate));
407 Initialize(true, false, true, true);
408 wtr_->OnPlaying();
409
410 // No log should have been generated yet since the message loop has not had
411 // any chance to pump.
412 CycleWatchTimeReporter();
413 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
414
415 CycleWatchTimeReporter();
416 wtr_.reset();
417
418 ExpectWatchTime(
419 {media::MediaLog::kWatchTimeAudioAll, media::MediaLog::kWatchTimeAudioMse,
420 media::MediaLog::kWatchTimeAudioEme, media::MediaLog::kWatchTimeAudioAc,
421 media::MediaLog::kWatchTimeAudioEmbeddedExperience},
422 kWatchTimeLate);
423 }
424
425 TEST_F(MediaInternalsWatchTimeTest, BasicVideo) {
426 constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
427 constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
428 EXPECT_CALL(*this, GetCurrentMediaTime())
429 .WillOnce(testing::Return(base::TimeDelta()))
430 .WillOnce(testing::Return(kWatchTimeEarly))
431 .WillRepeatedly(testing::Return(kWatchTimeLate));
432 Initialize(true, true, false, true);
433 wtr_->OnPlaying();
434
435 // No log should have been generated yet since the message loop has not had
436 // any chance to pump.
437 CycleWatchTimeReporter();
438 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
439
440 CycleWatchTimeReporter();
441 wtr_.reset();
442
443 ExpectWatchTime({media::MediaLog::kWatchTimeAudioVideoAll,
444 media::MediaLog::kWatchTimeAudioVideoSrc,
445 media::MediaLog::kWatchTimeAudioVideoEme,
446 media::MediaLog::kWatchTimeAudioVideoAc,
447 media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience},
448 kWatchTimeLate);
449 }
450
451 TEST_F(MediaInternalsWatchTimeTest, BasicPower) {
452 constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
453 constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
454 constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
455 EXPECT_CALL(*this, GetCurrentMediaTime())
456 .WillOnce(testing::Return(base::TimeDelta()))
457 .WillOnce(testing::Return(kWatchTime1))
458 .WillOnce(testing::Return(kWatchTime2))
459 .WillOnce(testing::Return(kWatchTime2))
460 .WillRepeatedly(testing::Return(kWatchTime3));
461
462 Initialize(true, true, false, true);
463 wtr_->OnPlaying();
464 wtr_->set_is_on_battery_power_for_testing(true);
465
466 // No log should have been generated yet since the message loop has not had
467 // any chance to pump.
468 CycleWatchTimeReporter();
469 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
470
471 CycleWatchTimeReporter();
472
473 // Transition back to AC power, this should generate AC watch time as well.
474 wtr_->OnPowerStateChangeForTesting(false);
475 CycleWatchTimeReporter();
476
477 // This should finalize the power watch time on battery.
478 ExpectWatchTime({media::MediaLog::kWatchTimeAudioVideoBattery}, kWatchTime2);
479 ResetHistogramTester();
480 wtr_.reset();
481
482 std::vector<base::StringPiece> normal_keys = {
483 media::MediaLog::kWatchTimeAudioVideoAll,
484 media::MediaLog::kWatchTimeAudioVideoSrc,
485 media::MediaLog::kWatchTimeAudioVideoEme,
486 media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience};
487
488 for (auto key : watch_time_keys_) {
489 if (key == media::MediaLog::kWatchTimeAudioVideoAc) {
490 histogram_tester_->ExpectUniqueSample(
491 key.as_string(), (kWatchTime3 - kWatchTime2).InMilliseconds(), 1);
492 continue;
493 }
494
495 auto it = std::find(normal_keys.begin(), normal_keys.end(), key);
496 if (it == normal_keys.end()) {
497 histogram_tester_->ExpectTotalCount(key.as_string(), 0);
498 } else {
499 histogram_tester_->ExpectUniqueSample(key.as_string(),
500 kWatchTime3.InMilliseconds(), 1);
501 }
502 }
503 }
504
505 TEST_F(MediaInternalsWatchTimeTest, BasicHidden) {
506 constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
507 constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
508 EXPECT_CALL(*this, GetCurrentMediaTime())
509 .WillOnce(testing::Return(base::TimeDelta()))
510 .WillOnce(testing::Return(kWatchTimeEarly))
511 .WillRepeatedly(testing::Return(kWatchTimeLate));
512 Initialize(true, true, false, true);
513 wtr_->OnHidden();
514 wtr_->OnPlaying();
515
516 // No log should have been generated yet since the message loop has not had
517 // any chance to pump.
518 CycleWatchTimeReporter();
519 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
520
521 CycleWatchTimeReporter();
522 wtr_.reset();
523
524 ExpectWatchTime(
525 {media::MediaLog::kWatchTimeAudioVideoBackgroundAll,
526 media::MediaLog::kWatchTimeAudioVideoBackgroundSrc,
527 media::MediaLog::kWatchTimeAudioVideoBackgroundEme,
528 media::MediaLog::kWatchTimeAudioVideoBackgroundAc,
529 media::MediaLog::kWatchTimeAudioVideoBackgroundEmbeddedExperience},
530 kWatchTimeLate);
531 }
532
533 TEST_F(MediaInternalsWatchTimeTest, PlayerDestructionFinalizes) {
534 constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
535 constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
536 EXPECT_CALL(*this, GetCurrentMediaTime())
537 .WillOnce(testing::Return(base::TimeDelta()))
538 .WillOnce(testing::Return(kWatchTimeEarly))
539 .WillRepeatedly(testing::Return(kWatchTimeLate));
540 Initialize(true, true, false, true);
541 wtr_->OnPlaying();
542
543 // No log should have been generated yet since the message loop has not had
544 // any chance to pump.
545 CycleWatchTimeReporter();
546 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
547
548 CycleWatchTimeReporter();
549
550 media_log_->AddEvent(
551 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
552
553 ExpectWatchTime({media::MediaLog::kWatchTimeAudioVideoAll,
554 media::MediaLog::kWatchTimeAudioVideoSrc,
555 media::MediaLog::kWatchTimeAudioVideoEme,
556 media::MediaLog::kWatchTimeAudioVideoAc,
557 media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience},
558 kWatchTimeLate);
559 }
560
561 TEST_F(MediaInternalsWatchTimeTest, ProcessDestructionFinalizes) {
562 constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
563 constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
564 EXPECT_CALL(*this, GetCurrentMediaTime())
565 .WillOnce(testing::Return(base::TimeDelta()))
566 .WillOnce(testing::Return(kWatchTimeEarly))
567 .WillRepeatedly(testing::Return(kWatchTimeLate));
568 Initialize(true, true, false, true);
569 wtr_->OnPlaying();
570
571 // No log should have been generated yet since the message loop has not had
572 // any chance to pump.
573 CycleWatchTimeReporter();
574 ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
575
576 CycleWatchTimeReporter();
577
578 internals_->OnProcessTerminatedForTesting(render_process_id_);
579 ExpectWatchTime({media::MediaLog::kWatchTimeAudioVideoAll,
580 media::MediaLog::kWatchTimeAudioVideoSrc,
581 media::MediaLog::kWatchTimeAudioVideoEme,
582 media::MediaLog::kWatchTimeAudioVideoAc,
583 media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience},
584 kWatchTimeLate);
585 }
312 586
313 } // namespace content 587 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/media_internals.cc ('k') | media/base/media_log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698