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. | |
sandersd (OOO until July 31)
2016/02/27 00:22:20
Please comment on which thread methods run on such
DaleCurtis
2016/02/27 00:55:23
Added a comment below about how calls might trigge
| |
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 base::AutoReset<bool> scoper(&idle_cleanup_running_, true); | |
164 | |
165 const base::TimeTicks now = tick_clock_->NowTicks(); | |
166 for (const auto& kv : idle_delegate_map_) { | |
167 if (now - kv.second > idle_timeout_) | |
168 id_map_.Lookup(kv.first)->OnHidden(true); | |
sandersd (OOO until July 31)
2016/02/27 00:22:20
I'm going to keep commenting that this is the wron
DaleCurtis
2016/02/27 00:55:23
Ignoring per offline discussion.
| |
169 } | |
170 | |
171 // Take care of any removals that happened during the above iteration. | |
172 for (auto it = idle_delegate_map_.begin(); it != idle_delegate_map_.end();) { | |
173 if (it->second.is_null()) | |
174 it = idle_delegate_map_.erase(it); | |
sandersd (OOO until July 31)
2016/02/27 00:22:20
It looks like this can race with line 153.
DaleCurtis
2016/02/27 00:55:23
Ignoring per offline discussion.
| |
175 else | |
176 ++it; | |
177 } | |
178 | |
179 // Shutdown the timer if no delegates are left. | |
180 if (idle_delegate_map_.empty()) | |
181 idle_cleanup_timer_.Stop(); | |
182 } | |
183 | |
108 } // namespace media | 184 } // namespace media |
OLD | NEW |