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

Side by Side Diff: content/renderer/media/renderer_webmediaplayer_delegate.cc

Issue 1739473003: Suspend idle WebMediaPlayer instances after some time. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: NON_EXPORTED_BASE. Created 4 years, 10 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/renderer/media/renderer_webmediaplayer_delegate.h" 5 #include "content/renderer/media/renderer_webmediaplayer_delegate.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/auto_reset.h"
9 #include "content/common/media/media_player_delegate_messages.h" 10 #include "content/common/media/media_player_delegate_messages.h"
10 #include "content/public/renderer/render_frame.h" 11 #include "content/public/renderer/render_frame.h"
11 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" 12 #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
12 13
13 namespace media { 14 namespace media {
14 15
15 RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate( 16 RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate(
16 content::RenderFrame* render_frame) 17 content::RenderFrame* render_frame)
17 : RenderFrameObserver(render_frame) {} 18 : RenderFrameObserver(render_frame),
19 default_tick_clock_(new base::DefaultTickClock()),
20 tick_clock_(default_tick_clock_.get()) {
21 #if defined(OS_ANDROID)
22 // On Android the idle cleanup timer is enabled by default.
23 // TODO(dalecurtis): Eventually this should be enabled on all platforms.
24 idle_cleanup_enabled_ = true;
25 idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5);
26 idle_timeout_ = base::TimeDelta::FromSeconds(15);
27 #endif
28 }
18 29
19 RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {} 30 RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {}
20 31
21 int RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) { 32 int RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) {
22 return id_map_.Add(observer); 33 const int delegate_id = id_map_.Add(observer);
34 AddIdleDelegate(delegate_id);
35 return delegate_id;
23 } 36 }
24 37
25 void RendererWebMediaPlayerDelegate::RemoveObserver(int delegate_id) { 38 void RendererWebMediaPlayerDelegate::RemoveObserver(int delegate_id) {
26 DCHECK(id_map_.Lookup(delegate_id)); 39 DCHECK(id_map_.Lookup(delegate_id));
27 id_map_.Remove(delegate_id); 40 id_map_.Remove(delegate_id);
41 RemoveIdleDelegate(delegate_id);
28 } 42 }
29 43
30 void RendererWebMediaPlayerDelegate::DidPlay(int delegate_id, 44 void RendererWebMediaPlayerDelegate::DidPlay(int delegate_id,
31 bool has_video, 45 bool has_video,
32 bool has_audio, 46 bool has_audio,
33 bool is_remote, 47 bool is_remote,
34 base::TimeDelta duration) { 48 base::TimeDelta duration) {
35 DCHECK(id_map_.Lookup(delegate_id)); 49 DCHECK(id_map_.Lookup(delegate_id));
36 has_played_media_ = true; 50 has_played_media_ = true;
51 RemoveIdleDelegate(delegate_id);
37 Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying( 52 Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying(
38 routing_id(), delegate_id, has_video, has_audio, is_remote, duration)); 53 routing_id(), delegate_id, has_video, has_audio, is_remote, duration));
39 } 54 }
40 55
41 void RendererWebMediaPlayerDelegate::DidPause(int delegate_id, 56 void RendererWebMediaPlayerDelegate::DidPause(int delegate_id,
42 bool reached_end_of_stream) { 57 bool reached_end_of_stream) {
43 DCHECK(id_map_.Lookup(delegate_id)); 58 DCHECK(id_map_.Lookup(delegate_id));
59 AddIdleDelegate(delegate_id);
44 Send(new MediaPlayerDelegateHostMsg_OnMediaPaused(routing_id(), delegate_id, 60 Send(new MediaPlayerDelegateHostMsg_OnMediaPaused(routing_id(), delegate_id,
45 reached_end_of_stream)); 61 reached_end_of_stream));
46 } 62 }
47 63
48 void RendererWebMediaPlayerDelegate::PlayerGone(int delegate_id) { 64 void RendererWebMediaPlayerDelegate::PlayerGone(int delegate_id) {
49 DCHECK(id_map_.Lookup(delegate_id)); 65 DCHECK(id_map_.Lookup(delegate_id));
66 RemoveIdleDelegate(delegate_id);
50 Send(new MediaPlayerDelegateHostMsg_OnMediaDestroyed(routing_id(), 67 Send(new MediaPlayerDelegateHostMsg_OnMediaDestroyed(routing_id(),
51 delegate_id)); 68 delegate_id));
52 } 69 }
53 70
54 bool RendererWebMediaPlayerDelegate::IsHidden() { 71 bool RendererWebMediaPlayerDelegate::IsHidden() {
55 return render_frame()->IsHidden(); 72 return render_frame()->IsHidden();
56 } 73 }
57 74
58 void RendererWebMediaPlayerDelegate::WasHidden() { 75 void RendererWebMediaPlayerDelegate::WasHidden() {
59 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance()) 76 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
60 it.GetCurrentValue()->OnHidden(false); 77 it.GetCurrentValue()->OnHidden(false);
61 } 78 }
62 79
63 void RendererWebMediaPlayerDelegate::WasShown() { 80 void RendererWebMediaPlayerDelegate::WasShown() {
64 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance()) 81 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
65 it.GetCurrentValue()->OnShown(); 82 it.GetCurrentValue()->OnShown();
66 } 83 }
67 84
68 bool RendererWebMediaPlayerDelegate::OnMessageReceived( 85 bool RendererWebMediaPlayerDelegate::OnMessageReceived(
69 const IPC::Message& msg) { 86 const IPC::Message& msg) {
70 bool handled = true; 87 bool handled = true;
71 IPC_BEGIN_MESSAGE_MAP(RendererWebMediaPlayerDelegate, msg) 88 IPC_BEGIN_MESSAGE_MAP(RendererWebMediaPlayerDelegate, msg)
72 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Pause, OnMediaDelegatePause) 89 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Pause, OnMediaDelegatePause)
73 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Play, OnMediaDelegatePlay) 90 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Play, OnMediaDelegatePlay)
74 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_SuspendAllMediaPlayers, 91 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_SuspendAllMediaPlayers,
75 OnMediaDelegateSuspendAllMediaPlayers) 92 OnMediaDelegateSuspendAllMediaPlayers)
76 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_UpdateVolumeMultiplier, 93 IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_UpdateVolumeMultiplier,
77 OnMediaDelegateVolumeMultiplierUpdate) 94 OnMediaDelegateVolumeMultiplierUpdate)
78 IPC_MESSAGE_UNHANDLED(handled = false) 95 IPC_MESSAGE_UNHANDLED(handled = false)
79 IPC_END_MESSAGE_MAP() 96 IPC_END_MESSAGE_MAP()
80 return handled; 97 return handled;
81 } 98 }
82 99
100 void RendererWebMediaPlayerDelegate::EnableInstantIdleCleanupForTesting(
101 base::TimeDelta idle_timeout,
102 base::TickClock* tick_clock) {
103 idle_cleanup_enabled_ = true;
104 idle_cleanup_interval_ = base::TimeDelta();
105 idle_timeout_ = idle_timeout;
106 tick_clock_ = tick_clock;
107 }
108
83 void RendererWebMediaPlayerDelegate::OnMediaDelegatePause(int delegate_id) { 109 void RendererWebMediaPlayerDelegate::OnMediaDelegatePause(int delegate_id) {
84 Observer* observer = id_map_.Lookup(delegate_id); 110 Observer* observer = id_map_.Lookup(delegate_id);
85 if (observer) 111 if (observer)
86 observer->OnPause(); 112 observer->OnPause();
87 } 113 }
88 114
89 void RendererWebMediaPlayerDelegate::OnMediaDelegatePlay(int delegate_id) { 115 void RendererWebMediaPlayerDelegate::OnMediaDelegatePlay(int delegate_id) {
90 Observer* observer = id_map_.Lookup(delegate_id); 116 Observer* observer = id_map_.Lookup(delegate_id);
91 if (observer) 117 if (observer)
92 observer->OnPlay(); 118 observer->OnPlay();
93 } 119 }
94 120
95 void RendererWebMediaPlayerDelegate::OnMediaDelegateSuspendAllMediaPlayers() { 121 void RendererWebMediaPlayerDelegate::OnMediaDelegateSuspendAllMediaPlayers() {
96 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance()) 122 for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
97 it.GetCurrentValue()->OnHidden(true); 123 it.GetCurrentValue()->OnHidden(true);
98 } 124 }
99 125
100 void RendererWebMediaPlayerDelegate::OnMediaDelegateVolumeMultiplierUpdate( 126 void RendererWebMediaPlayerDelegate::OnMediaDelegateVolumeMultiplierUpdate(
101 int delegate_id, 127 int delegate_id,
102 double multiplier) { 128 double multiplier) {
103 Observer* observer = id_map_.Lookup(delegate_id); 129 Observer* observer = id_map_.Lookup(delegate_id);
104 if (observer) 130 if (observer)
105 observer->OnVolumeMultiplierUpdate(multiplier); 131 observer->OnVolumeMultiplierUpdate(multiplier);
106 } 132 }
107 133
134 void RendererWebMediaPlayerDelegate::AddIdleDelegate(int delegate_id) {
135 if (!idle_cleanup_enabled_)
136 return;
137
138 idle_delegate_map_[delegate_id] = tick_clock_->NowTicks();
139 if (!idle_cleanup_timer_.IsRunning()) {
140 idle_cleanup_timer_.Start(
141 FROM_HERE, idle_cleanup_interval_, this,
142 &RendererWebMediaPlayerDelegate::CleanupIdleDelegates);
143 }
144 }
145
146 void RendererWebMediaPlayerDelegate::RemoveIdleDelegate(int delegate_id) {
147 if (!idle_cleanup_enabled_)
148 return;
149
150 // To avoid invalidating the iterator, just mark the delegate for deletion
151 // using a sentinel value of an empty TimeTicks.
152 if (idle_cleanup_running_) {
153 idle_delegate_map_[delegate_id] = base::TimeTicks();
154 return;
155 }
156
157 idle_delegate_map_.erase(delegate_id);
158 if (idle_delegate_map_.empty())
159 idle_cleanup_timer_.Stop();
160 }
161
162 void RendererWebMediaPlayerDelegate::CleanupIdleDelegates() {
163 // Iterate over the delegates and suspend the idle ones. Note: The call to
164 // OnHidden() can trigger calls into RemoveIdleDelegate(), so for iterator
165 // validity we set |idle_cleanup_running_| to true and defer deletions.
166 base::AutoReset<bool> scoper(&idle_cleanup_running_, true);
167 const base::TimeTicks now = tick_clock_->NowTicks();
168 for (const auto& kv : idle_delegate_map_) {
169 if (now - kv.second > idle_timeout_)
170 id_map_.Lookup(kv.first)->OnHidden(true);
171 }
172
173 // Take care of any removals that happened during the above iteration.
174 for (auto it = idle_delegate_map_.begin(); it != idle_delegate_map_.end();) {
175 if (it->second.is_null())
176 it = idle_delegate_map_.erase(it);
177 else
178 ++it;
179 }
180
181 // Shutdown the timer if no delegates are left.
182 if (idle_delegate_map_.empty())
183 idle_cleanup_timer_.Stop();
184 }
185
108 } // namespace media 186 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698