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

Side by Side Diff: content/browser/media/session/media_session_impl.cc

Issue 2798083002: Record user interactions with MediaSession by action type (Closed)
Patch Set: addressed style nits 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/session/media_session_impl.h" 5 #include "content/browser/media/session/media_session_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include "content/browser/media/session/audio_focus_delegate.h" 8 #include "content/browser/media/session/audio_focus_delegate.h"
9 #include "content/browser/media/session/media_session_controller.h" 9 #include "content/browser/media/session/media_session_controller.h"
10 #include "content/browser/media/session/media_session_player_observer.h" 10 #include "content/browser/media/session/media_session_player_observer.h"
11 #include "content/browser/media/session/media_session_service_impl.h" 11 #include "content/browser/media/session/media_session_service_impl.h"
12 #include "content/browser/web_contents/web_contents_impl.h" 12 #include "content/browser/web_contents/web_contents_impl.h"
13 #include "content/public/browser/media_session.h" 13 #include "content/public/browser/media_session.h"
14 #include "content/public/browser/media_session_observer.h" 14 #include "content/public/browser/media_session_observer.h"
15 #include "content/public/browser/navigation_handle.h" 15 #include "content/public/browser/navigation_handle.h"
16 #include "content/public/browser/web_contents.h" 16 #include "content/public/browser/web_contents.h"
17 #include "media/base/media_content_type.h" 17 #include "media/base/media_content_type.h"
18 #include "third_party/WebKit/public/platform/modules/mediasession/media_session. mojom.h"
18 19
19 #if defined(OS_ANDROID) 20 #if defined(OS_ANDROID)
20 #include "content/browser/media/session/media_session_android.h" 21 #include "content/browser/media/session/media_session_android.h"
21 #endif // defined(OS_ANDROID) 22 #endif // defined(OS_ANDROID)
22 23
23 namespace content { 24 namespace content {
24 25
26 using MediaSessionUserAction = MediaSessionUmaHelper::MediaSessionUserAction;
27
25 namespace { 28 namespace {
26 29
27 const double kDefaultVolumeMultiplier = 1.0; 30 const double kDefaultVolumeMultiplier = 1.0;
28 const double kDuckingVolumeMultiplier = 0.2; 31 const double kDuckingVolumeMultiplier = 0.2;
29 32
30 using MapRenderFrameHostToDepth = std::map<RenderFrameHost*, size_t>; 33 using MapRenderFrameHostToDepth = std::map<RenderFrameHost*, size_t>;
31 34
32 size_t ComputeFrameDepth(RenderFrameHost* rfh, 35 size_t ComputeFrameDepth(RenderFrameHost* rfh,
33 MapRenderFrameHostToDepth* map_rfh_to_depth) { 36 MapRenderFrameHostToDepth* map_rfh_to_depth) {
34 DCHECK(rfh); 37 DCHECK(rfh);
35 size_t depth = 0; 38 size_t depth = 0;
36 RenderFrameHost* current_frame = rfh; 39 RenderFrameHost* current_frame = rfh;
37 while (current_frame) { 40 while (current_frame) {
38 auto it = map_rfh_to_depth->find(current_frame); 41 auto it = map_rfh_to_depth->find(current_frame);
39 if (it != map_rfh_to_depth->end()) { 42 if (it != map_rfh_to_depth->end()) {
40 depth += it->second; 43 depth += it->second;
41 break; 44 break;
42 } 45 }
43 ++depth; 46 ++depth;
44 current_frame = current_frame->GetParent(); 47 current_frame = current_frame->GetParent();
45 } 48 }
46 (*map_rfh_to_depth)[rfh] = depth; 49 (*map_rfh_to_depth)[rfh] = depth;
47 return depth; 50 return depth;
48 } 51 }
49 52
53 MediaSessionUserAction MediaSessionActionToUserAction(
54 blink::mojom::MediaSessionAction action) {
55 switch (action) {
56 case blink::mojom::MediaSessionAction::PLAY:
57 return MediaSessionUserAction::Play;
58 case blink::mojom::MediaSessionAction::PAUSE:
59 return MediaSessionUserAction::Pause;
60 case blink::mojom::MediaSessionAction::PREVIOUS_TRACK:
61 return MediaSessionUserAction::PreviousTrack;
62 case blink::mojom::MediaSessionAction::NEXT_TRACK:
63 return MediaSessionUserAction::NextTrack;
64 case blink::mojom::MediaSessionAction::SEEK_BACKWARD:
65 return MediaSessionUserAction::SeekBackward;
66 case blink::mojom::MediaSessionAction::SEEK_FORWARD:
67 return MediaSessionUserAction::SeekForward;
68 }
69 NOTREACHED();
70 return MediaSessionUserAction::Count;
71 }
72
50 } // anonymous namespace 73 } // anonymous namespace
51 74
52 using MediaSessionSuspendedSource = 75 using MediaSessionSuspendedSource =
53 MediaSessionUmaHelper::MediaSessionSuspendedSource; 76 MediaSessionUmaHelper::MediaSessionSuspendedSource;
54 77
55 DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSessionImpl); 78 DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSessionImpl);
56 79
57 MediaSessionImpl::PlayerIdentifier::PlayerIdentifier( 80 MediaSessionImpl::PlayerIdentifier::PlayerIdentifier(
58 MediaSessionPlayerObserver* observer, 81 MediaSessionPlayerObserver* observer,
59 int player_id) 82 int player_id)
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 326 }
304 327
305 // Otherwise, suspend the session. 328 // Otherwise, suspend the session.
306 DCHECK(IsActive()); 329 DCHECK(IsActive());
307 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); 330 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
308 } 331 }
309 332
310 void MediaSessionImpl::Resume(SuspendType suspend_type) { 333 void MediaSessionImpl::Resume(SuspendType suspend_type) {
311 DCHECK(IsSuspended()); 334 DCHECK(IsSuspended());
312 335
336 if (suspend_type == SuspendType::UI) {
337 MediaSessionUmaHelper::RecordMediaSessionUserAction(
338 MediaSessionUmaHelper::MediaSessionUserAction::PlayDefault);
339 }
340
313 // When the resume requests comes from another source than system, audio focus 341 // When the resume requests comes from another source than system, audio focus
314 // must be requested. 342 // must be requested.
315 if (suspend_type != SuspendType::SYSTEM) { 343 if (suspend_type != SuspendType::SYSTEM) {
316 // Request audio focus again in case we lost it because another app started 344 // Request audio focus again in case we lost it because another app started
317 // playing while the playback was paused. 345 // playing while the playback was paused.
318 State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_) 346 State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_)
319 ? State::ACTIVE 347 ? State::ACTIVE
320 : State::INACTIVE; 348 : State::INACTIVE;
321 SetAudioFocusState(audio_focus_state); 349 SetAudioFocusState(audio_focus_state);
322 350
323 if (audio_focus_state_ != State::ACTIVE) 351 if (audio_focus_state_ != State::ACTIVE)
324 return; 352 return;
325 } 353 }
326 354
327 OnResumeInternal(suspend_type); 355 OnResumeInternal(suspend_type);
328 } 356 }
329 357
330 void MediaSessionImpl::Suspend(SuspendType suspend_type) { 358 void MediaSessionImpl::Suspend(SuspendType suspend_type) {
331 if (!IsActive()) 359 if (!IsActive())
332 return; 360 return;
333 361
362 if (suspend_type == SuspendType::UI) {
363 MediaSessionUmaHelper::RecordMediaSessionUserAction(
364 MediaSessionUserAction::PauseDefault);
365 }
366
334 OnSuspendInternal(suspend_type, State::SUSPENDED); 367 OnSuspendInternal(suspend_type, State::SUSPENDED);
335 } 368 }
336 369
337 void MediaSessionImpl::Stop(SuspendType suspend_type) { 370 void MediaSessionImpl::Stop(SuspendType suspend_type) {
338 DCHECK(audio_focus_state_ != State::INACTIVE); 371 DCHECK(audio_focus_state_ != State::INACTIVE);
339 DCHECK(suspend_type != SuspendType::CONTENT); 372 DCHECK(suspend_type != SuspendType::CONTENT);
340 DCHECK(!HasPepper()); 373 DCHECK(!HasPepper());
341 374
375 if (suspend_type == SuspendType::UI) {
376 MediaSessionUmaHelper::RecordMediaSessionUserAction(
377 MediaSessionUmaHelper::MediaSessionUserAction::StopDefault);
378 }
379
342 // TODO(mlamouri): merge the logic between UI and SYSTEM. 380 // TODO(mlamouri): merge the logic between UI and SYSTEM.
343 if (suspend_type == SuspendType::SYSTEM) { 381 if (suspend_type == SuspendType::SYSTEM) {
344 OnSuspendInternal(suspend_type, State::INACTIVE); 382 OnSuspendInternal(suspend_type, State::INACTIVE);
345 return; 383 return;
346 } 384 }
347 385
348 if (audio_focus_state_ != State::SUSPENDED) 386 if (audio_focus_state_ != State::SUSPENDED)
349 OnSuspendInternal(suspend_type, State::SUSPENDED); 387 OnSuspendInternal(suspend_type, State::SUSPENDED);
350 388
351 DCHECK(audio_focus_state_ == State::SUSPENDED); 389 DCHECK(audio_focus_state_ == State::SUSPENDED);
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 void MediaSessionImpl::OnMediaSessionActionsChanged( 666 void MediaSessionImpl::OnMediaSessionActionsChanged(
629 MediaSessionServiceImpl* service) { 667 MediaSessionServiceImpl* service) {
630 if (service != routed_service_) 668 if (service != routed_service_)
631 return; 669 return;
632 670
633 NotifyMediaSessionActionsChange(routed_service_->actions()); 671 NotifyMediaSessionActionsChange(routed_service_->actions());
634 } 672 }
635 673
636 void MediaSessionImpl::DidReceiveAction( 674 void MediaSessionImpl::DidReceiveAction(
637 blink::mojom::MediaSessionAction action) { 675 blink::mojom::MediaSessionAction action) {
676 MediaSessionUmaHelper::RecordMediaSessionUserAction(
677 MediaSessionActionToUserAction(action));
678
638 // Pause all players in non-routed frames if the action is PAUSE. 679 // Pause all players in non-routed frames if the action is PAUSE.
639 // 680 //
640 // This is the default PAUSE action handler per Media Session API spec. The 681 // This is the default PAUSE action handler per Media Session API spec. The
641 // reason for pausing all players in all other sessions is to avoid the 682 // reason for pausing all players in all other sessions is to avoid the
642 // players in other frames keep the session active so that the UI will always 683 // players in other frames keep the session active so that the UI will always
643 // show the pause button but it does not pause anything (as the routed frame 684 // show the pause button but it does not pause anything (as the routed frame
644 // already pauses when responding to the PAUSE action while other frames does 685 // already pauses when responding to the PAUSE action while other frames does
645 // not). 686 // not).
646 // 687 //
647 // TODO(zqzhang): Currently, this might not work well on desktop as Pepper and 688 // TODO(zqzhang): Currently, this might not work well on desktop as Pepper and
648 // OneShot players are not really suspended, so that the session is still 689 // OneShot players are not really suspended, so that the session is still
649 // active after this. See https://crbug.com/619084 and 690 // active after this. See https://crbug.com/619084 and
650 // https://crbug.com/596516. 691 // https://crbug.com/596516.
651 if (blink::mojom::MediaSessionAction::PAUSE == action) { 692 if (blink::mojom::MediaSessionAction::PAUSE == action) {
652 RenderFrameHost* rfh_of_routed_service = 693 RenderFrameHost* rfh_of_routed_service =
653 routed_service_ ? routed_service_->GetRenderFrameHost() : nullptr; 694 routed_service_ ? routed_service_->GetRenderFrameHost() : nullptr;
654 for (const auto& player : normal_players_) { 695 for (const auto& player : normal_players_) {
655 if (player.observer->GetRenderFrameHost() != rfh_of_routed_service) 696 if (player.observer->render_frame_host() != rfh_of_routed_service)
656 player.observer->OnSuspend(player.player_id); 697 player.observer->OnSuspend(player.player_id);
657 } 698 }
658 for (const auto& player : pepper_players_) { 699 for (const auto& player : pepper_players_) {
659 if (player.observer->GetRenderFrameHost() != rfh_of_routed_service) { 700 if (player.observer->render_frame_host() != rfh_of_routed_service) {
660 player.observer->OnSetVolumeMultiplier(player.player_id, 701 player.observer->OnSetVolumeMultiplier(player.player_id,
661 kDuckingVolumeMultiplier); 702 kDuckingVolumeMultiplier);
662 } 703 }
663 } 704 }
664 for (const auto& player : one_shot_players_) { 705 for (const auto& player : one_shot_players_) {
665 if (player.observer->GetRenderFrameHost() != rfh_of_routed_service) 706 if (player.observer->render_frame_host() != rfh_of_routed_service)
666 player.observer->OnSuspend(player.player_id); 707 player.observer->OnSuspend(player.player_id);
667 } 708 }
668 } 709 }
669 710
670 if (!routed_service_) 711 if (!routed_service_)
671 return; 712 return;
672 713
673 routed_service_->GetClient()->DidReceiveAction(action); 714 routed_service_->GetClient()->DidReceiveAction(action);
674 } 715 }
675 716
(...skipping 13 matching lines...) Expand all
689 } 730 }
690 } 731 }
691 732
692 MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() { 733 MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() {
693 // The service selection strategy is: select a frame that has a playing/paused 734 // The service selection strategy is: select a frame that has a playing/paused
694 // player and has a corresponding MediaSessionService and return the 735 // player and has a corresponding MediaSessionService and return the
695 // corresponding MediaSessionService. If multiple frames satisfy the criteria, 736 // corresponding MediaSessionService. If multiple frames satisfy the criteria,
696 // prefer the top-most frame. 737 // prefer the top-most frame.
697 std::set<RenderFrameHost*> frames; 738 std::set<RenderFrameHost*> frames;
698 for (const auto& player : normal_players_) { 739 for (const auto& player : normal_players_) {
699 RenderFrameHost* frame = player.observer->GetRenderFrameHost(); 740 RenderFrameHost* frame = player.observer->render_frame_host();
700 if (frame) 741 if (frame)
701 frames.insert(frame); 742 frames.insert(frame);
702 } 743 }
703 744
704 for (const auto& player : one_shot_players_) { 745 for (const auto& player : one_shot_players_) {
705 RenderFrameHost* frame = player.observer->GetRenderFrameHost(); 746 RenderFrameHost* frame = player.observer->render_frame_host();
706 if (frame) 747 if (frame)
707 frames.insert(frame); 748 frames.insert(frame);
708 } 749 }
709 750
710 for (const auto& player : pepper_players_) { 751 for (const auto& player : pepper_players_) {
711 RenderFrameHost* frame = player.observer->GetRenderFrameHost(); 752 RenderFrameHost* frame = player.observer->render_frame_host();
712 if (frame) 753 if (frame)
713 frames.insert(frame); 754 frames.insert(frame);
714 } 755 }
715 756
716 RenderFrameHost* best_frame = nullptr; 757 RenderFrameHost* best_frame = nullptr;
717 size_t min_depth = std::numeric_limits<size_t>::max(); 758 size_t min_depth = std::numeric_limits<size_t>::max();
718 std::map<RenderFrameHost*, size_t> map_rfh_to_depth; 759 std::map<RenderFrameHost*, size_t> map_rfh_to_depth;
719 760
720 for (RenderFrameHost* frame : frames) { 761 for (RenderFrameHost* frame : frames) {
721 size_t depth = ComputeFrameDepth(frame, &map_rfh_to_depth); 762 size_t depth = ComputeFrameDepth(frame, &map_rfh_to_depth);
722 if (depth >= min_depth) 763 if (depth >= min_depth)
723 continue; 764 continue;
724 if (!IsServiceActiveForRenderFrameHost(frame)) 765 if (!IsServiceActiveForRenderFrameHost(frame))
725 continue; 766 continue;
726 best_frame = frame; 767 best_frame = frame;
727 min_depth = depth; 768 min_depth = depth;
728 } 769 }
729 770
730 return best_frame ? services_[best_frame] : nullptr; 771 return best_frame ? services_[best_frame] : nullptr;
731 } 772 }
732 773
733 } // namespace content 774 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698