Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/media/media_stream_capture_indicator.h" | 5 #include "chrome/browser/media/media_stream_capture_indicator.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
| 9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/app/chrome_command_ids.h" | 10 #include "chrome/app/chrome_command_ids.h" |
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 12 #include "chrome/browser/extensions/extension_service.h" | |
| 13 #include "chrome/browser/profiles/profile.h" | |
| 12 #include "chrome/browser/status_icons/status_icon.h" | 14 #include "chrome/browser/status_icons/status_icon.h" |
| 13 #include "chrome/browser/status_icons/status_tray.h" | 15 #include "chrome/browser/status_icons/status_tray.h" |
| 14 #include "chrome/browser/tab_contents/tab_util.h" | 16 #include "chrome/browser/tab_contents/tab_util.h" |
| 15 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 16 #include "content/public/browser/content_browser_client.h" | 18 #include "content/public/browser/content_browser_client.h" |
| 17 #include "content/public/browser/render_view_host.h" | 19 #include "content/public/browser/render_view_host.h" |
| 18 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
| 19 #include "content/public/browser/web_contents_delegate.h" | 21 #include "content/public/browser/web_contents_delegate.h" |
| 20 #include "grit/chromium_strings.h" | 22 #include "grit/chromium_strings.h" |
| 21 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
| 22 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
| 23 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
| 24 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
| 25 #include "ui/base/resource/resource_bundle.h" | 27 #include "ui/base/resource/resource_bundle.h" |
| 26 | 28 |
| 27 using content::BrowserThread; | 29 using content::BrowserThread; |
| 28 using content::WebContents; | 30 using content::WebContents; |
| 29 | 31 |
| 32 namespace { | |
| 33 | |
| 34 const extensions::Extension* GetExtension(int render_process_id, | |
| 35 int render_view_id) { | |
| 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 37 | |
| 38 WebContents* web_contents = tab_util::GetWebContentsByID( | |
| 39 render_process_id, render_view_id); | |
| 40 if (!web_contents) | |
| 41 return NULL; | |
| 42 | |
| 43 Profile* profile = | |
| 44 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
| 45 ExtensionService* extensions = | |
| 46 !profile ? NULL : profile->GetExtensionService(); | |
|
scherkus (not reviewing)
2012/07/31 02:14:12
this tertiary-operator-ness is hurting my eyes --
Evan Stade
2012/07/31 23:19:29
Done.
| |
| 47 return !extensions ? NULL : | |
| 48 extensions->extensions()->GetExtensionOrAppByURL( | |
| 49 ExtensionURLInfo(web_contents->GetURL())); | |
| 50 } | |
| 51 | |
| 52 // Gets the security originator of the tab. It returns a string with no '/' | |
| 53 // at the end to display in the UI. | |
| 54 string16 GetSecurityOrigin(int render_process_id, int render_view_id) { | |
| 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 56 WebContents* tab_content = tab_util::GetWebContentsByID( | |
| 57 render_process_id, render_view_id); | |
| 58 if (!tab_content) | |
| 59 return string16(); | |
| 60 | |
| 61 std::string security_origin = tab_content->GetURL().GetOrigin().spec(); | |
| 62 | |
| 63 // Remove the last character if it is a '/'. | |
| 64 if (!security_origin.empty()) { | |
| 65 std::string::iterator it = security_origin.end() - 1; | |
| 66 if (*it == '/') | |
| 67 security_origin.erase(it); | |
| 68 } | |
| 69 | |
| 70 return UTF8ToUTF16(security_origin); | |
| 71 } | |
| 72 | |
| 73 string16 GetTitle(int render_process_id, int render_view_id) { | |
| 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 75 | |
| 76 const extensions::Extension* extension = | |
| 77 GetExtension(render_process_id, render_view_id); | |
| 78 if (extension) | |
| 79 return UTF8ToUTF16(extension->name()); | |
| 80 | |
| 81 WebContents* tab_content = tab_util::GetWebContentsByID( | |
| 82 render_process_id, render_view_id); | |
| 83 if (!tab_content) | |
| 84 return string16(); | |
| 85 | |
| 86 string16 tab_title = tab_content->GetTitle(); | |
| 87 | |
| 88 if (tab_title.empty()) { | |
| 89 // If the page's title is empty use its security originator. | |
| 90 tab_title = GetSecurityOrigin(render_process_id, render_view_id); | |
| 91 } else { | |
| 92 // If the page's title matches its URL, use its security originator. | |
| 93 std::string languages = | |
| 94 content::GetContentClient()->browser()->GetAcceptLangs( | |
| 95 tab_content->GetBrowserContext()); | |
| 96 if (tab_title == net::FormatUrl(tab_content->GetURL(), languages)) | |
| 97 tab_title = GetSecurityOrigin(render_process_id, render_view_id); | |
| 98 } | |
| 99 | |
| 100 return tab_title; | |
| 101 } | |
| 102 | |
| 103 } // namespace | |
| 104 | |
| 30 MediaStreamCaptureIndicator::TabEquals::TabEquals(int render_process_id, | 105 MediaStreamCaptureIndicator::TabEquals::TabEquals(int render_process_id, |
| 31 int render_view_id) | 106 int render_view_id) |
| 32 : render_process_id_(render_process_id), | 107 : render_process_id_(render_process_id), |
| 33 render_view_id_(render_view_id) {} | 108 render_view_id_(render_view_id) {} |
| 34 | 109 |
| 35 bool MediaStreamCaptureIndicator::TabEquals::operator() ( | 110 bool MediaStreamCaptureIndicator::TabEquals::operator() ( |
| 36 const MediaStreamCaptureIndicator::CaptureDeviceTab& tab) { | 111 const MediaStreamCaptureIndicator::CaptureDeviceTab& tab) { |
| 37 return (render_process_id_ == tab.render_process_id && | 112 return (render_process_id_ == tab.render_process_id && |
| 38 render_view_id_ == tab.render_view_id); | 113 render_view_id_ == tab.render_view_id); |
| 39 } | 114 } |
| 40 | 115 |
| 41 MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() | 116 MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() |
| 42 : status_icon_(NULL), | 117 : status_icon_(NULL), |
| 43 mic_image_(NULL), | 118 mic_image_(NULL), |
| 44 camera_image_(NULL), | 119 camera_image_(NULL), |
| 45 balloon_image_(NULL) { | 120 balloon_image_(NULL), |
| 121 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), | |
| 122 image_load_index_(-1), | |
| 123 pending_message_id_(0) { | |
| 46 } | 124 } |
| 47 | 125 |
| 48 MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { | 126 MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { |
| 49 // The user is responsible for cleaning up by closing all the opened devices. | 127 // The user is responsible for cleaning up by closing all the opened devices. |
| 50 DCHECK(tabs_.empty()); | 128 DCHECK(tabs_.empty()); |
| 51 } | 129 } |
| 52 | 130 |
| 53 bool MediaStreamCaptureIndicator::IsCommandIdChecked( | 131 bool MediaStreamCaptureIndicator::IsCommandIdChecked( |
| 54 int command_id) const { | 132 int command_id) const { |
| 55 NOTIMPLEMENTED() << "There are no checked items in the MediaStream menu."; | 133 NOTIMPLEMENTED() << "There are no checked items in the MediaStream menu."; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 } | 249 } |
| 172 DCHECK(mic_image_); | 250 DCHECK(mic_image_); |
| 173 DCHECK(camera_image_); | 251 DCHECK(camera_image_); |
| 174 DCHECK(balloon_image_); | 252 DCHECK(balloon_image_); |
| 175 } | 253 } |
| 176 | 254 |
| 177 void MediaStreamCaptureIndicator::ShowBalloon( | 255 void MediaStreamCaptureIndicator::ShowBalloon( |
| 178 int render_process_id, | 256 int render_process_id, |
| 179 int render_view_id, | 257 int render_view_id, |
| 180 bool audio, | 258 bool audio, |
| 181 bool video) const { | 259 bool video) { |
| 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 183 DCHECK(audio || video); | 261 DCHECK(audio || video); |
| 184 string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | |
| 185 | 262 |
| 186 int message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_AUDIO_AND_VIDEO; | 263 int message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_AUDIO_AND_VIDEO; |
| 187 if (audio && !video) | 264 if (audio && !video) |
| 188 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_AUDIO_ONLY; | 265 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_AUDIO_ONLY; |
| 189 else if (!audio && video) | 266 else if (!audio && video) |
| 190 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_VIDEO_ONLY; | 267 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_BALLOON_BODY_VIDEO_ONLY; |
| 191 | 268 |
| 192 string16 body = l10n_util::GetStringFUTF16( | 269 const extensions::Extension* extension = |
| 193 message_id, GetSecurityOrigin(render_process_id, render_view_id)); | 270 GetExtension(render_process_id, render_view_id); |
| 271 if (extension) { | |
| 272 pending_message_id_ = message_id; | |
| 273 pending_extension_name_ = extension->name(); | |
|
no longer working on chromium
2012/07/31 08:24:37
can we simply store the 10n_util::GetStringFUTF16(
Evan Stade
2012/07/31 23:19:29
Done.
| |
| 274 return ShowBalloonForExtension(extension); | |
| 275 } | |
| 194 | 276 |
| 277 string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | |
| 278 string16 body = l10n_util::GetStringFUTF16(message_id, | |
| 279 GetSecurityOrigin(render_process_id, render_view_id)); | |
| 195 status_icon_->DisplayBalloon(*balloon_image_, title, body); | 280 status_icon_->DisplayBalloon(*balloon_image_, title, body); |
| 196 } | 281 } |
| 197 | 282 |
| 283 void MediaStreamCaptureIndicator::ShowBalloonForExtension( | |
| 284 const extensions::Extension* extension) { | |
| 285 image_load_index_++; | |
|
no longer working on chromium
2012/07/31 08:24:37
++image_load_index_;
Evan Stade
2012/07/31 23:19:29
Done.
| |
| 286 tracker_.LoadImage( | |
| 287 extension, | |
| 288 extension->GetIconResource(32, ExtensionIconSet::MATCH_BIGGER), | |
| 289 gfx::Size(32, 32), | |
| 290 ImageLoadingTracker::CACHE); | |
| 291 } | |
| 292 | |
| 293 void MediaStreamCaptureIndicator::OnImageLoaded( | |
| 294 const gfx::Image& image, | |
| 295 const std::string& extension_id, | |
|
no longer working on chromium
2012/07/31 08:24:37
What is the difference between extension_id and ex
Evan Stade
2012/07/31 23:19:29
name is a display string, extension_id() is a hash
| |
| 296 int index) { | |
| 297 if (index != image_load_index_) | |
|
scherkus (not reviewing)
2012/07/31 02:14:12
is this to prevent displaying older images that ma
no longer working on chromium
2012/07/31 08:24:37
are we skipping showing the balloon when the new S
Evan Stade
2012/07/31 23:19:29
yes
| |
| 298 return; | |
| 299 | |
| 300 status_icon_->DisplayBalloon( | |
| 301 !image.IsEmpty() ? *image.ToImageSkia() : | |
| 302 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 303 IDR_APP_DEFAULT_ICON), | |
| 304 string16(), | |
| 305 l10n_util::GetStringFUTF16(pending_message_id_, | |
| 306 UTF8ToUTF16(pending_extension_name_))); | |
| 307 } | |
| 308 | |
| 198 void MediaStreamCaptureIndicator::Hide() { | 309 void MediaStreamCaptureIndicator::Hide() { |
| 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 200 if (!status_icon_) | 311 if (!status_icon_) |
| 201 return; | 312 return; |
| 202 | 313 |
| 203 // If there is no browser process, we should not do anything. | 314 // If there is no browser process, we should not do anything. |
| 204 if (!g_browser_process) | 315 if (!g_browser_process) |
| 205 return; | 316 return; |
| 206 | 317 |
| 207 StatusTray* status_tray = g_browser_process->status_tray(); | 318 StatusTray* status_tray = g_browser_process->status_tray(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 // Remove the tab if all the devices have been closed. | 439 // Remove the tab if all the devices have been closed. |
| 329 if (iter->audio_ref_count == 0 && iter->video_ref_count == 0) | 440 if (iter->audio_ref_count == 0 && iter->video_ref_count == 0) |
| 330 tabs_.erase(iter); | 441 tabs_.erase(iter); |
| 331 | 442 |
| 332 if (tabs_.empty()) | 443 if (tabs_.empty()) |
| 333 Hide(); | 444 Hide(); |
| 334 else | 445 else |
| 335 UpdateStatusTrayIconContextMenu(); | 446 UpdateStatusTrayIconContextMenu(); |
| 336 } | 447 } |
| 337 | 448 |
| 338 string16 MediaStreamCaptureIndicator::GetTitle(int render_process_id, | |
| 339 int render_view_id) const { | |
| 340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 341 WebContents* tab_content = tab_util::GetWebContentsByID( | |
| 342 render_process_id, render_view_id); | |
| 343 if (!tab_content) | |
| 344 return string16(); | |
| 345 | |
| 346 string16 tab_title = tab_content->GetTitle(); | |
| 347 | |
| 348 if (tab_title.empty()) { | |
| 349 // If the page's title is empty use its security originator. | |
| 350 tab_title = GetSecurityOrigin(render_process_id, render_view_id); | |
| 351 } else { | |
| 352 // If the page's title matches its URL, use its security originator. | |
| 353 std::string languages = | |
| 354 content::GetContentClient()->browser()->GetAcceptLangs( | |
| 355 tab_content->GetBrowserContext()); | |
| 356 if (tab_title == net::FormatUrl(tab_content->GetURL(), languages)) | |
| 357 tab_title = GetSecurityOrigin(render_process_id, render_view_id); | |
| 358 } | |
| 359 | |
| 360 return tab_title; | |
| 361 } | |
| 362 | |
| 363 string16 MediaStreamCaptureIndicator::GetSecurityOrigin( | |
| 364 int render_process_id, int render_view_id) const { | |
| 365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 366 WebContents* tab_content = tab_util::GetWebContentsByID( | |
| 367 render_process_id, render_view_id); | |
| 368 if (!tab_content) | |
| 369 return string16(); | |
| 370 | |
| 371 std::string security_origin = tab_content->GetURL().GetOrigin().spec(); | |
| 372 | |
| 373 // Remove the last character if it is a '/'. | |
| 374 if (!security_origin.empty()) { | |
| 375 std::string::iterator it = security_origin.end() - 1; | |
| 376 if (*it == '/') | |
| 377 security_origin.erase(it); | |
| 378 } | |
| 379 | |
| 380 return UTF8ToUTF16(security_origin); | |
| 381 } | |
| OLD | NEW |