OLD | NEW |
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 |
OLD | NEW |