| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 } | 107 } |
| 108 | 108 |
| 109 bool IsCapturingAudio() const { return audio_ref_count_ > 0; } | 109 bool IsCapturingAudio() const { return audio_ref_count_ > 0; } |
| 110 bool IsCapturingVideo() const { return video_ref_count_ > 0; } | 110 bool IsCapturingVideo() const { return video_ref_count_ > 0; } |
| 111 bool IsMirroring() const { return mirroring_ref_count_ > 0; } | 111 bool IsMirroring() const { return mirroring_ref_count_ > 0; } |
| 112 | 112 |
| 113 std::unique_ptr<content::MediaStreamUI> RegisterMediaStream( | 113 std::unique_ptr<content::MediaStreamUI> RegisterMediaStream( |
| 114 const content::MediaStreamDevices& devices); | 114 const content::MediaStreamDevices& devices); |
| 115 | 115 |
| 116 // Increment ref-counts up based on the type of each device provided. | 116 // Increment ref-counts up based on the type of each device provided. |
| 117 void AddDevices(const content::MediaStreamDevices& devices); | 117 void AddDevices(const content::MediaStreamDevices& devices, |
| 118 const base::Closure& close_callback); |
| 118 | 119 |
| 119 // Decrement ref-counts up based on the type of each device provided. | 120 // Decrement ref-counts up based on the type of each device provided. |
| 120 void RemoveDevices(const content::MediaStreamDevices& devices); | 121 void RemoveDevices(const content::MediaStreamDevices& devices); |
| 121 | 122 |
| 123 // Helper to call |stop_callback_|. |
| 124 void NotifyStopped(); |
| 125 |
| 122 private: | 126 private: |
| 123 // content::WebContentsObserver overrides. | 127 // content::WebContentsObserver overrides. |
| 124 void WebContentsDestroyed() override { | 128 void WebContentsDestroyed() override { |
| 125 indicator_->UnregisterWebContents(web_contents()); | 129 indicator_->UnregisterWebContents(web_contents()); |
| 126 } | 130 } |
| 131 bool IsMirroringType(content::MediaStreamType type); |
| 127 | 132 |
| 128 scoped_refptr<MediaStreamCaptureIndicator> indicator_; | 133 scoped_refptr<MediaStreamCaptureIndicator> indicator_; |
| 129 int audio_ref_count_; | 134 int audio_ref_count_; |
| 130 int video_ref_count_; | 135 int video_ref_count_; |
| 131 int mirroring_ref_count_; | 136 int mirroring_ref_count_; |
| 132 | 137 |
| 138 base::Closure stop_callback_; |
| 133 base::WeakPtrFactory<WebContentsDeviceUsage> weak_factory_; | 139 base::WeakPtrFactory<WebContentsDeviceUsage> weak_factory_; |
| 134 | 140 |
| 135 DISALLOW_COPY_AND_ASSIGN(WebContentsDeviceUsage); | 141 DISALLOW_COPY_AND_ASSIGN(WebContentsDeviceUsage); |
| 136 }; | 142 }; |
| 137 | 143 |
| 138 // Implements MediaStreamUI interface. Instances of this class are created for | 144 // Implements MediaStreamUI interface. Instances of this class are created for |
| 139 // each MediaStream and their ownership is passed to MediaStream implementation | 145 // each MediaStream and their ownership is passed to MediaStream implementation |
| 140 // in the content layer. Each UIDelegate keeps a weak pointer to the | 146 // in the content layer. Each UIDelegate keeps a weak pointer to the |
| 141 // corresponding WebContentsDeviceUsage object to deliver updates about state of | 147 // corresponding WebContentsDeviceUsage object to deliver updates about state of |
| 142 // the stream. | 148 // the stream. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 154 if (started_ && device_usage_.get()) | 160 if (started_ && device_usage_.get()) |
| 155 device_usage_->RemoveDevices(devices_); | 161 device_usage_->RemoveDevices(devices_); |
| 156 } | 162 } |
| 157 | 163 |
| 158 private: | 164 private: |
| 159 // content::MediaStreamUI interface. | 165 // content::MediaStreamUI interface. |
| 160 gfx::NativeViewId OnStarted(const base::Closure& close_callback) override { | 166 gfx::NativeViewId OnStarted(const base::Closure& close_callback) override { |
| 161 DCHECK(!started_); | 167 DCHECK(!started_); |
| 162 started_ = true; | 168 started_ = true; |
| 163 if (device_usage_.get()) | 169 if (device_usage_.get()) |
| 164 device_usage_->AddDevices(devices_); | 170 device_usage_->AddDevices(devices_, close_callback); |
| 165 return 0; | 171 return 0; |
| 166 } | 172 } |
| 167 | 173 |
| 168 base::WeakPtr<WebContentsDeviceUsage> device_usage_; | 174 base::WeakPtr<WebContentsDeviceUsage> device_usage_; |
| 169 content::MediaStreamDevices devices_; | 175 content::MediaStreamDevices devices_; |
| 170 bool started_; | 176 bool started_; |
| 171 | 177 |
| 172 DISALLOW_COPY_AND_ASSIGN(UIDelegate); | 178 DISALLOW_COPY_AND_ASSIGN(UIDelegate); |
| 173 }; | 179 }; |
| 174 | 180 |
| 175 std::unique_ptr<content::MediaStreamUI> | 181 std::unique_ptr<content::MediaStreamUI> |
| 176 MediaStreamCaptureIndicator::WebContentsDeviceUsage::RegisterMediaStream( | 182 MediaStreamCaptureIndicator::WebContentsDeviceUsage::RegisterMediaStream( |
| 177 const content::MediaStreamDevices& devices) { | 183 const content::MediaStreamDevices& devices) { |
| 178 return base::WrapUnique(new UIDelegate(weak_factory_.GetWeakPtr(), devices)); | 184 return base::WrapUnique(new UIDelegate(weak_factory_.GetWeakPtr(), devices)); |
| 179 } | 185 } |
| 180 | 186 |
| 181 void MediaStreamCaptureIndicator::WebContentsDeviceUsage::AddDevices( | 187 void MediaStreamCaptureIndicator::WebContentsDeviceUsage::AddDevices( |
| 182 const content::MediaStreamDevices& devices) { | 188 const content::MediaStreamDevices& devices, |
| 189 const base::Closure& close_callback) { |
| 183 for (content::MediaStreamDevices::const_iterator it = devices.begin(); | 190 for (content::MediaStreamDevices::const_iterator it = devices.begin(); |
| 184 it != devices.end(); ++it) { | 191 it != devices.end(); ++it) { |
| 185 if (it->type == content::MEDIA_TAB_AUDIO_CAPTURE || | 192 if (IsMirroringType(it->type)) { |
| 186 it->type == content::MEDIA_TAB_VIDEO_CAPTURE) { | |
| 187 ++mirroring_ref_count_; | 193 ++mirroring_ref_count_; |
| 188 } else if (content::IsAudioInputMediaType(it->type)) { | 194 } else if (content::IsAudioInputMediaType(it->type)) { |
| 189 ++audio_ref_count_; | 195 ++audio_ref_count_; |
| 190 } else if (content::IsVideoMediaType(it->type)) { | 196 } else if (content::IsVideoMediaType(it->type)) { |
| 191 ++video_ref_count_; | 197 ++video_ref_count_; |
| 192 } else { | 198 } else { |
| 193 NOTIMPLEMENTED(); | 199 NOTIMPLEMENTED(); |
| 194 } | 200 } |
| 195 } | 201 } |
| 196 | 202 |
| 197 if (web_contents()) | 203 if (web_contents()) { |
| 204 stop_callback_ = close_callback; |
| 198 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); | 205 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); |
| 206 } |
| 199 | 207 |
| 200 indicator_->UpdateNotificationUserInterface(); | 208 indicator_->UpdateNotificationUserInterface(); |
| 201 } | 209 } |
| 202 | 210 |
| 203 void MediaStreamCaptureIndicator::WebContentsDeviceUsage::RemoveDevices( | 211 void MediaStreamCaptureIndicator::WebContentsDeviceUsage::RemoveDevices( |
| 204 const content::MediaStreamDevices& devices) { | 212 const content::MediaStreamDevices& devices) { |
| 205 for (content::MediaStreamDevices::const_iterator it = devices.begin(); | 213 for (content::MediaStreamDevices::const_iterator it = devices.begin(); |
| 206 it != devices.end(); ++it) { | 214 it != devices.end(); ++it) { |
| 207 if (it->type == content::MEDIA_TAB_AUDIO_CAPTURE || | 215 if (IsMirroringType(it->type)) { |
| 208 it->type == content::MEDIA_TAB_VIDEO_CAPTURE) { | |
| 209 --mirroring_ref_count_; | 216 --mirroring_ref_count_; |
| 210 } else if (content::IsAudioInputMediaType(it->type)) { | 217 } else if (content::IsAudioInputMediaType(it->type)) { |
| 211 --audio_ref_count_; | 218 --audio_ref_count_; |
| 212 } else if (content::IsVideoMediaType(it->type)) { | 219 } else if (content::IsVideoMediaType(it->type)) { |
| 213 --video_ref_count_; | 220 --video_ref_count_; |
| 214 } else { | 221 } else { |
| 215 NOTIMPLEMENTED(); | 222 NOTIMPLEMENTED(); |
| 216 } | 223 } |
| 217 } | 224 } |
| 218 | 225 |
| 219 DCHECK_GE(audio_ref_count_, 0); | 226 DCHECK_GE(audio_ref_count_, 0); |
| 220 DCHECK_GE(video_ref_count_, 0); | 227 DCHECK_GE(video_ref_count_, 0); |
| 221 DCHECK_GE(mirroring_ref_count_, 0); | 228 DCHECK_GE(mirroring_ref_count_, 0); |
| 222 | 229 |
| 223 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); | 230 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); |
| 224 indicator_->UpdateNotificationUserInterface(); | 231 indicator_->UpdateNotificationUserInterface(); |
| 225 } | 232 } |
| 226 | 233 |
| 234 void MediaStreamCaptureIndicator::WebContentsDeviceUsage::NotifyStopped() { |
| 235 if (!stop_callback_.is_null()) { |
| 236 base::Closure callback = stop_callback_; |
| 237 stop_callback_.Reset(); |
| 238 callback.Run(); |
| 239 } |
| 240 } |
| 241 |
| 242 bool MediaStreamCaptureIndicator::WebContentsDeviceUsage::IsMirroringType( |
| 243 content::MediaStreamType type) { |
| 244 #if defined(OS_ANDROID) |
| 245 return type == content::MEDIA_TAB_AUDIO_CAPTURE || |
| 246 type == content::MEDIA_TAB_VIDEO_CAPTURE || |
| 247 type == content::MEDIA_DESKTOP_VIDEO_CAPTURE; |
| 248 #else |
| 249 return type == content::MEDIA_TAB_AUDIO_CAPTURE || |
| 250 type == content::MEDIA_TAB_VIDEO_CAPTURE; |
| 251 #endif |
| 252 } |
| 253 |
| 227 MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() | 254 MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() |
| 228 : status_icon_(NULL), | 255 : status_icon_(NULL), |
| 229 mic_image_(NULL), | 256 mic_image_(NULL), |
| 230 camera_image_(NULL) { | 257 camera_image_(NULL) { |
| 231 } | 258 } |
| 232 | 259 |
| 233 MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { | 260 MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { |
| 234 // The user is responsible for cleaning up by reporting the closure of any | 261 // The user is responsible for cleaning up by reporting the closure of any |
| 235 // opened devices. However, there exists a race condition at shutdown: The UI | 262 // opened devices. However, there exists a race condition at shutdown: The UI |
| 236 // thread may be stopped before CaptureDevicesClosed() posts the task to | 263 // thread may be stopped before CaptureDevicesClosed() posts the task to |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 } | 317 } |
| 291 | 318 |
| 292 bool MediaStreamCaptureIndicator::IsBeingMirrored( | 319 bool MediaStreamCaptureIndicator::IsBeingMirrored( |
| 293 content::WebContents* web_contents) const { | 320 content::WebContents* web_contents) const { |
| 294 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 321 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 295 | 322 |
| 296 WebContentsDeviceUsage* usage = usage_map_.get(web_contents); | 323 WebContentsDeviceUsage* usage = usage_map_.get(web_contents); |
| 297 return usage && usage->IsMirroring(); | 324 return usage && usage->IsMirroring(); |
| 298 } | 325 } |
| 299 | 326 |
| 327 void MediaStreamCaptureIndicator::NotifyStopped( |
| 328 content::WebContents* web_contents) const { |
| 329 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 330 |
| 331 WebContentsDeviceUsage* usage = usage_map_.get(web_contents); |
| 332 if (usage) |
| 333 usage->NotifyStopped(); |
| 334 } |
| 335 |
| 300 void MediaStreamCaptureIndicator::UnregisterWebContents( | 336 void MediaStreamCaptureIndicator::UnregisterWebContents( |
| 301 WebContents* web_contents) { | 337 WebContents* web_contents) { |
| 302 usage_map_.erase(web_contents); | 338 usage_map_.erase(web_contents); |
| 303 UpdateNotificationUserInterface(); | 339 UpdateNotificationUserInterface(); |
| 304 } | 340 } |
| 305 | 341 |
| 306 void MediaStreamCaptureIndicator::MaybeCreateStatusTrayIcon(bool audio, | 342 void MediaStreamCaptureIndicator::MaybeCreateStatusTrayIcon(bool audio, |
| 307 bool video) { | 343 bool video) { |
| 308 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 344 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 309 | 345 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 } else if (audio && !video) { | 468 } else if (audio && !video) { |
| 433 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY; | 469 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY; |
| 434 *image = *mic_image_; | 470 *image = *mic_image_; |
| 435 } else if (!audio && video) { | 471 } else if (!audio && video) { |
| 436 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY; | 472 message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY; |
| 437 *image = *camera_image_; | 473 *image = *camera_image_; |
| 438 } | 474 } |
| 439 | 475 |
| 440 *tool_tip = l10n_util::GetStringUTF16(message_id); | 476 *tool_tip = l10n_util::GetStringUTF16(message_id); |
| 441 } | 477 } |
| OLD | NEW |