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

Side by Side Diff: chrome/browser/media/media_stream_capture_indicator.cc

Issue 10168008: Show camera and microphone status indicators. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed the rest of the comments from MAD and Nico Created 8 years, 7 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 | Annotate | Revision Log
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698