OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/media/media_stream_capture_indicator.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/utf_string_conversions.h" | |
9 #include "chrome/app/chrome_command_ids.h" | |
10 #include "chrome/browser/browser_process.h" | |
11 #include "chrome/browser/status_icons/status_icon.h" | |
12 #include "chrome/browser/status_icons/status_tray.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 #include "grit/chromium_strings.h" | |
15 #include "grit/generated_resources.h" | |
16 #include "grit/theme_resources.h" | |
17 #include "ui/base/l10n/l10n_util.h" | |
18 #include "ui/base/resource/resource_bundle.h" | |
19 | |
20 using content::BrowserThread; | |
21 | |
22 MediaStreamCaptureIndicator::UserEquals::UserEquals( | |
23 int render_process_id, | |
24 int render_view_id, | |
25 const std::string& url, | |
26 content::MediaStreamDeviceType type) | |
27 : render_process_id_(render_process_id), | |
28 render_view_id_(render_view_id), | |
29 url_(url), | |
30 type_(type) {} | |
31 | |
32 MediaStreamCaptureIndicator::UserEquals::UserEquals(int render_process_id, | |
33 int render_view_id, | |
34 const std::string& url) | |
35 : render_process_id_(render_process_id), | |
36 render_view_id_(render_view_id), | |
37 url_(url), | |
38 type_(content::MEDIA_STREAM_DEVICE_TYPE_NO_SERVICE) {} | |
39 | |
40 bool MediaStreamCaptureIndicator::UserEquals::operator() ( | |
41 const MediaStreamCaptureIndicator::CaptureDeviceUser& user) { | |
42 if (type_ == content::MEDIA_STREAM_DEVICE_TYPE_NO_SERVICE) { | |
43 return (render_process_id_ == user.render_process_id && | |
44 render_view_id_ == user.render_view_id && | |
45 url_ == user.url); | |
46 } else { | |
47 return (render_process_id_ == user.render_process_id && | |
48 render_view_id_ == user.render_view_id && | |
49 url_ == user.url && | |
50 type_ == user.type); | |
51 } | |
52 } | |
53 | |
54 MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() | |
55 : status_icon_(NULL) { | |
56 } | |
57 | |
58 MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { | |
59 // The user is responsible for cleaning up by closing all the opened devices. | |
60 DCHECK(users_.empty()); | |
61 } | |
62 | |
63 bool MediaStreamCaptureIndicator::IsCommandIdChecked( | |
64 int command_id) const { | |
65 NOTIMPLEMENTED() << "There are no checked items in the MediaStream menu."; | |
66 return false; | |
67 } | |
68 | |
69 bool MediaStreamCaptureIndicator::IsCommandIdEnabled( | |
70 int command_id) const { | |
71 return command_id != IDC_MinimumLabelValue; | |
72 } | |
73 | |
74 bool MediaStreamCaptureIndicator::GetAcceleratorForCommandId( | |
75 int command_id, ui::Accelerator* accelerator) { | |
76 // No accelerators for status icon context menu. | |
77 return false; | |
78 } | |
79 | |
80 void MediaStreamCaptureIndicator::ExecuteCommand(int command_id) { | |
81 // TODO(xians) : Implement all the following execute command function. | |
82 switch (command_id) { | |
83 case IDC_MEDIA_STREAM_DEVICE_STATUS_TRAY: | |
84 break; | |
85 case IDC_MEDIA_CONTEXT_MEDIA_STREAM_CAPTURE_LIST: | |
86 break; | |
87 default: | |
88 NOTREACHED(); | |
89 break; | |
90 } | |
91 } | |
92 | |
93 void MediaStreamCaptureIndicator::CaptureDevicesOpened( | |
94 int render_process_id, | |
95 int render_view_id, | |
96 const std::string& url, | |
97 const content::MediaStreamDevices& devices) { | |
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
99 DCHECK(!url.empty()); | |
100 DCHECK(!devices.empty()); | |
101 | |
102 BrowserThread::PostTask( | |
103 BrowserThread::UI, FROM_HERE, | |
104 base::Bind(&MediaStreamCaptureIndicator::DoDevicesOpenedOnUIThread, | |
105 this, render_process_id, render_view_id, url, devices)); | |
106 } | |
107 | |
108 void MediaStreamCaptureIndicator::CaptureDevicesClosed( | |
109 int render_process_id, | |
110 int render_view_id, | |
111 const std::string& url, | |
112 const content::MediaStreamDevices& devices) { | |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
114 DCHECK(!url.empty()); | |
115 DCHECK(!devices.empty()); | |
116 | |
117 BrowserThread::PostTask( | |
118 BrowserThread::UI, FROM_HERE, | |
119 base::Bind(&MediaStreamCaptureIndicator::DoDevicesClosedOnUIThread, | |
120 this, render_process_id, render_view_id, url, devices)); | |
121 } | |
122 | |
123 void MediaStreamCaptureIndicator::DoDevicesOpenedOnUIThread( | |
124 int render_process_id, | |
125 int render_view_id, | |
126 const std::string& url, | |
127 const content::MediaStreamDevices& devices) { | |
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
129 | |
130 CreateStatusTray(); | |
131 | |
132 // If we don't have a status icon or one could not be created successfully, | |
133 // then no need to continue. | |
134 if (!status_icon_) | |
135 return; | |
136 | |
137 AddCaptureDeviceUser(render_process_id, render_view_id, url, devices); | |
138 | |
139 ShowBalloon(url); | |
140 } | |
141 | |
142 void MediaStreamCaptureIndicator::DoDevicesClosedOnUIThread( | |
143 int render_process_id, | |
144 int render_view_id, | |
145 const std::string& url, | |
146 const content::MediaStreamDevices& devices) { | |
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
148 if (!status_icon_) | |
149 return; | |
150 | |
151 DCHECK(!users_.empty()); | |
152 RemoveCaptureDeviceUser(render_process_id, render_view_id, url, devices); | |
153 | |
154 if (users_.empty()) | |
155 Hide(); | |
156 } | |
157 | |
158 void MediaStreamCaptureIndicator::CreateStatusTray() { | |
159 if (status_icon_) | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
DCHECK(...on UI thread ...)
no longer working on chromium
2012/04/30 13:12:54
From Mad: Nit: You already DCHECKed on that in the
| |
160 return; | |
161 | |
162 // If there is no browser process, we should not create the status tray. | |
163 if (!g_browser_process) | |
164 return; | |
165 | |
166 StatusTray* status_tray = g_browser_process->status_tray(); | |
167 if (!status_tray) | |
168 return; | |
169 | |
170 status_icon_ = status_tray->CreateStatusIcon(); | |
171 | |
172 status_icon_->SetToolTip(l10n_util::GetStringUTF16( | |
173 IDS_MEDIA_STREAM_STATUS_TRAY_TOOLTIP)); | |
174 | |
175 EnsureStatusTrayIcon(); | |
176 DCHECK(!icon_image_.empty()); | |
177 | |
178 status_icon_->SetImage(icon_image_); | |
179 } | |
180 | |
181 void MediaStreamCaptureIndicator::EnsureStatusTrayIcon() { | |
182 if (icon_image_.empty()) { | |
183 icon_image_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed( | |
184 IDR_MEDIA_STREAM_CAPTURE_LED); | |
185 } | |
186 } | |
187 | |
188 void MediaStreamCaptureIndicator::ShowBalloon( | |
189 const std::string& url) { | |
190 string16 title = l10n_util::GetStringUTF16( | |
191 IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_TITLE); | |
192 | |
193 string16 message = l10n_util::GetStringFUTF16( | |
194 IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY, ASCIIToUTF16(url)); | |
195 | |
196 status_icon_->DisplayBalloon(icon_image_, title, message); | |
197 } | |
198 | |
199 void MediaStreamCaptureIndicator::Hide() { | |
200 if (!status_icon_) | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
missing thread dcheck since this method accesses v
no longer working on chromium
2012/04/30 13:12:54
See my answers above.
| |
201 return; | |
202 | |
203 // If there is no browser process, we should not do anything. | |
204 if (!g_browser_process) | |
205 return; | |
206 | |
207 StatusTray* status_tray = g_browser_process->status_tray(); | |
208 if (status_tray != NULL) { | |
209 status_tray->RemoveStatusIcon(status_icon_); | |
210 status_icon_ = NULL; | |
211 } | |
212 } | |
213 | |
214 void MediaStreamCaptureIndicator::UpdateStatusTrayIconContextMenu() { | |
215 scoped_ptr<ui::SimpleMenuModel> menu(new ui::SimpleMenuModel(this)); | |
216 menu->AddItem(IDC_MEDIA_STREAM_DEVICE_STATUS_TRAY, | |
217 l10n_util::GetStringUTF16(IDS_MEDIA_STREAM_STATUS_TRAY_TITLE)); | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
I don't think a menu should have a title.
no longer working on chromium
2012/04/30 13:12:54
Done, I changed it to IDS_MEDIA_STREAM_STATUS_TRAY
| |
218 menu->AddSeparator(); | |
219 | |
220 for (CaptureDeviceUserList::iterator iter = users_.begin(); | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
missing thread dcheck for users_
no longer working on chromium
2012/04/30 13:12:54
See my answer in other comments.
| |
221 iter != users_.end(); ++iter) { | |
222 // Search backward to see if the user information has been added. | |
223 CaptureDeviceUserList::iterator iter_backward = std::find_if( | |
224 users_.begin(), iter, UserEquals(iter->render_process_id, | |
225 iter->render_view_id, | |
226 iter->url)); | |
227 // Do nothing if the user information has been added to the menu. | |
228 if (iter_backward != iter) | |
229 continue; | |
230 | |
231 int command_id = IDC_MEDIA_CONTEXT_MEDIA_STREAM_CAPTURE_LIST; | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
nit: no need for these two temporaries
no longer working on chromium
2012/04/30 13:12:54
Done.
| |
232 int message_id = IDS_MEDIA_STREAM_STATUS_TRAY_ITEM; | |
233 string16 message = l10n_util::GetStringFUTF16(message_id, | |
234 ASCIIToUTF16(iter->url)); | |
235 menu->AddItem(command_id, message); | |
236 menu->AddSeparator(); | |
237 } | |
238 | |
239 // The icon will take the ownership of the passed context menu. | |
240 status_icon_->SetContextMenu(menu.release()); | |
241 } | |
242 | |
243 void MediaStreamCaptureIndicator::AddCaptureDeviceUser( | |
244 int render_process_id, | |
245 int render_view_id, | |
246 const std::string& url, | |
247 const content::MediaStreamDevices& devices) { | |
248 content::MediaStreamDevices::const_iterator dev = devices.begin(); | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
missing thread dcheck in this function
no longer working on chromium
2012/04/30 13:12:54
See my answer in other comments.
| |
249 for (; dev != devices.end(); ++dev) { | |
250 DCHECK(dev->type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE || | |
251 dev->type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); | |
252 users_.push_back(CaptureDeviceUser(render_process_id, | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
do we need to first check if we've already got thi
no longer working on chromium
2012/04/30 13:12:54
Not for the current solution, we save the informat
| |
253 render_view_id, | |
254 url, | |
255 dev->type)); | |
256 } | |
257 | |
258 UpdateStatusTrayIconContextMenu(); | |
259 } | |
260 | |
261 void MediaStreamCaptureIndicator::RemoveCaptureDeviceUser( | |
262 int render_process_id, | |
263 int render_view_id, | |
264 const std::string& url, | |
265 const content::MediaStreamDevices& devices) { | |
266 content::MediaStreamDevices::const_iterator dev = devices.begin(); | |
267 for (; dev != devices.end(); ++dev) { | |
268 CaptureDeviceUserList::iterator iter = std::find_if( | |
269 users_.begin(), users_.end(), UserEquals(render_process_id, | |
tommi (sloooow) - chröme
2012/04/30 10:57:07
missing thread dcheck for users_
no longer working on chromium
2012/04/30 13:12:54
See answer in other comments.
| |
270 render_view_id, | |
271 url, | |
272 dev->type)); | |
273 if (iter != users_.end()) { | |
274 users_.erase(iter); | |
275 } else { | |
276 DLOG(ERROR) << "Failed to find MediaStream host " << url | |
277 << " for device " << dev->name | |
278 << " for type " << dev->type; | |
279 } | |
280 } | |
281 | |
282 if (!users_.empty()) | |
283 UpdateStatusTrayIconContextMenu(); | |
284 } | |
OLD | NEW |