| 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 "content/browser/renderer_host/media/media_stream_manager.h" | 5 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 for (const chromeos::AudioDevice& device : devices) { | 148 for (const chromeos::AudioDevice& device : devices) { |
| 149 if (device.type == chromeos::AUDIO_TYPE_HOTWORD) { | 149 if (device.type == chromeos::AUDIO_TYPE_HOTWORD) { |
| 150 DCHECK(device.is_input); | 150 DCHECK(device.is_input); |
| 151 *effects |= media::AudioParameters::HOTWORD; | 151 *effects |= media::AudioParameters::HOTWORD; |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 #endif | 154 #endif |
| 155 } | 155 } |
| 156 } | 156 } |
| 157 | 157 |
| 158 // Clears the MediaStreamDevice.name from all devices in |devices|. | |
| 159 void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) { | |
| 160 for (content::StreamDeviceInfo& device_info : *devices) | |
| 161 device_info.device.name.clear(); | |
| 162 } | |
| 163 | |
| 164 bool CalledOnIOThread() { | 158 bool CalledOnIOThread() { |
| 165 // Check if this function call is on the IO thread, except for unittests where | 159 // Check if this function call is on the IO thread, except for unittests where |
| 166 // an IO thread might not have been created. | 160 // an IO thread might not have been created. |
| 167 return BrowserThread::CurrentlyOn(BrowserThread::IO) || | 161 return BrowserThread::CurrentlyOn(BrowserThread::IO) || |
| 168 !BrowserThread::IsMessageLoopValid(BrowserThread::IO); | 162 !BrowserThread::IsMessageLoopValid(BrowserThread::IO); |
| 169 } | 163 } |
| 170 | 164 |
| 171 bool GetDeviceIDFromHMAC(const std::string& salt, | 165 bool GetDeviceIDFromHMAC(const std::string& salt, |
| 172 const url::Origin& security_origin, | 166 const url::Origin& security_origin, |
| 173 const std::string& hmac_device_id, | 167 const std::string& hmac_device_id, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 186 } | 180 } |
| 187 return false; | 181 return false; |
| 188 } | 182 } |
| 189 | 183 |
| 190 MediaStreamType ConvertToMediaStreamType(MediaDeviceType type) { | 184 MediaStreamType ConvertToMediaStreamType(MediaDeviceType type) { |
| 191 switch (type) { | 185 switch (type) { |
| 192 case MEDIA_DEVICE_TYPE_AUDIO_INPUT: | 186 case MEDIA_DEVICE_TYPE_AUDIO_INPUT: |
| 193 return MEDIA_DEVICE_AUDIO_CAPTURE; | 187 return MEDIA_DEVICE_AUDIO_CAPTURE; |
| 194 case MEDIA_DEVICE_TYPE_VIDEO_INPUT: | 188 case MEDIA_DEVICE_TYPE_VIDEO_INPUT: |
| 195 return MEDIA_DEVICE_VIDEO_CAPTURE; | 189 return MEDIA_DEVICE_VIDEO_CAPTURE; |
| 196 case MEDIA_DEVICE_TYPE_AUDIO_OUTPUT: | |
| 197 return MEDIA_DEVICE_AUDIO_OUTPUT; | |
| 198 default: | 190 default: |
| 199 NOTREACHED(); | 191 NOTREACHED(); |
| 200 } | 192 } |
| 201 | 193 |
| 202 return MEDIA_NO_SERVICE; | 194 return MEDIA_NO_SERVICE; |
| 203 } | 195 } |
| 204 | 196 |
| 205 MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) { | 197 MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) { |
| 206 switch (stream_type) { | 198 switch (stream_type) { |
| 207 case MEDIA_DEVICE_AUDIO_CAPTURE: | 199 case MEDIA_DEVICE_AUDIO_CAPTURE: |
| 208 return MEDIA_DEVICE_TYPE_AUDIO_INPUT; | 200 return MEDIA_DEVICE_TYPE_AUDIO_INPUT; |
| 209 case MEDIA_DEVICE_VIDEO_CAPTURE: | 201 case MEDIA_DEVICE_VIDEO_CAPTURE: |
| 210 return MEDIA_DEVICE_TYPE_VIDEO_INPUT; | 202 return MEDIA_DEVICE_TYPE_VIDEO_INPUT; |
| 211 case MEDIA_DEVICE_AUDIO_OUTPUT: | |
| 212 return MEDIA_DEVICE_TYPE_AUDIO_OUTPUT; | |
| 213 default: | 203 default: |
| 214 NOTREACHED(); | 204 NOTREACHED(); |
| 215 } | 205 } |
| 216 | 206 |
| 217 return NUM_MEDIA_DEVICE_TYPES; | 207 return NUM_MEDIA_DEVICE_TYPES; |
| 218 } | 208 } |
| 219 | 209 |
| 220 StreamDeviceInfoArray ConvertToStreamDeviceInfoArray( | |
| 221 MediaStreamType stream_type, | |
| 222 const MediaDeviceInfoArray& device_infos) { | |
| 223 StreamDeviceInfoArray stream_devices; | |
| 224 for (const auto& info : device_infos) { | |
| 225 stream_devices.emplace_back(stream_type, info.label, info.device_id, | |
| 226 info.group_id); | |
| 227 } | |
| 228 | |
| 229 return stream_devices; | |
| 230 } | |
| 231 | |
| 232 MediaStreamDevices ConvertToMediaStreamDevices( | 210 MediaStreamDevices ConvertToMediaStreamDevices( |
| 233 MediaStreamType stream_type, | 211 MediaStreamType stream_type, |
| 234 const MediaDeviceInfoArray& device_infos) { | 212 const MediaDeviceInfoArray& device_infos) { |
| 235 MediaStreamDevices devices; | 213 MediaStreamDevices devices; |
| 236 for (const auto& info : device_infos) { | 214 for (const auto& info : device_infos) { |
| 237 devices.emplace_back(stream_type, info.device_id, info.label, | 215 devices.emplace_back(stream_type, info.device_id, info.label); |
| 238 info.group_id); | |
| 239 } | 216 } |
| 240 | 217 |
| 241 return devices; | 218 return devices; |
| 242 } | 219 } |
| 243 | 220 |
| 244 } // namespace | 221 } // namespace |
| 245 | 222 |
| 246 | 223 |
| 247 // MediaStreamManager::DeviceRequest represents a request to either enumerate | 224 // MediaStreamManager::DeviceRequest represents a request to either enumerate |
| 248 // available devices or open one or more devices. | 225 // available devices or open one or more devices. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 273 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED), | 250 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED), |
| 274 audio_type_(MEDIA_NO_SERVICE), | 251 audio_type_(MEDIA_NO_SERVICE), |
| 275 video_type_(MEDIA_NO_SERVICE), | 252 video_type_(MEDIA_NO_SERVICE), |
| 276 target_process_id_(-1), | 253 target_process_id_(-1), |
| 277 target_frame_id_(-1) {} | 254 target_frame_id_(-1) {} |
| 278 | 255 |
| 279 ~DeviceRequest() {} | 256 ~DeviceRequest() {} |
| 280 | 257 |
| 281 void SetAudioType(MediaStreamType audio_type) { | 258 void SetAudioType(MediaStreamType audio_type) { |
| 282 DCHECK(IsAudioInputMediaType(audio_type) || | 259 DCHECK(IsAudioInputMediaType(audio_type) || |
| 283 audio_type == MEDIA_DEVICE_AUDIO_OUTPUT || | |
| 284 audio_type == MEDIA_NO_SERVICE); | 260 audio_type == MEDIA_NO_SERVICE); |
| 285 audio_type_ = audio_type; | 261 audio_type_ = audio_type; |
| 286 } | 262 } |
| 287 | 263 |
| 288 MediaStreamType audio_type() const { return audio_type_; } | 264 MediaStreamType audio_type() const { return audio_type_; } |
| 289 | 265 |
| 290 void SetVideoType(MediaStreamType video_type) { | 266 void SetVideoType(MediaStreamType video_type) { |
| 291 DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE); | 267 DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE); |
| 292 video_type_ = video_type; | 268 video_type_ = video_type; |
| 293 } | 269 } |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // MediaStreamManager, but power_monitor may be NULL in unit tests. | 428 // MediaStreamManager, but power_monitor may be NULL in unit tests. |
| 453 if (power_monitor) | 429 if (power_monitor) |
| 454 power_monitor->AddObserver(this); | 430 power_monitor->AddObserver(this); |
| 455 } | 431 } |
| 456 | 432 |
| 457 MediaStreamManager::~MediaStreamManager() { | 433 MediaStreamManager::~MediaStreamManager() { |
| 458 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO)); | 434 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO)); |
| 459 DVLOG(1) << "~MediaStreamManager"; | 435 DVLOG(1) << "~MediaStreamManager"; |
| 460 DCHECK(requests_.empty()); | 436 DCHECK(requests_.empty()); |
| 461 DCHECK(!device_task_runner_.get()); | 437 DCHECK(!device_task_runner_.get()); |
| 462 DCHECK(device_change_subscribers_.empty()); | |
| 463 | 438 |
| 464 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | 439 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); |
| 465 // The PowerMonitor instance owned by BrowserMainLoops always outlives the | 440 // The PowerMonitor instance owned by BrowserMainLoops always outlives the |
| 466 // MediaStreamManager, but it may be NULL in unit tests. | 441 // MediaStreamManager, but it may be NULL in unit tests. |
| 467 if (power_monitor) | 442 if (power_monitor) |
| 468 power_monitor->RemoveObserver(this); | 443 power_monitor->RemoveObserver(this); |
| 469 } | 444 } |
| 470 | 445 |
| 471 VideoCaptureManager* MediaStreamManager::video_capture_manager() { | 446 VideoCaptureManager* MediaStreamManager::video_capture_manager() { |
| 472 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 447 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 void MediaStreamManager::CancelRequest(const std::string& label) { | 552 void MediaStreamManager::CancelRequest(const std::string& label) { |
| 578 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 553 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 579 DVLOG(1) << "CancelRequest({label = " << label << "})"; | 554 DVLOG(1) << "CancelRequest({label = " << label << "})"; |
| 580 DeviceRequest* request = FindRequest(label); | 555 DeviceRequest* request = FindRequest(label); |
| 581 if (!request) { | 556 if (!request) { |
| 582 // The request does not exist. | 557 // The request does not exist. |
| 583 LOG(ERROR) << "The request with label = " << label << " does not exist."; | 558 LOG(ERROR) << "The request with label = " << label << " does not exist."; |
| 584 return; | 559 return; |
| 585 } | 560 } |
| 586 | 561 |
| 587 if (request->request_type == MEDIA_ENUMERATE_DEVICES) { | |
| 588 // It isn't an ideal use of "CancelRequest" to make it a requirement | |
| 589 // for enumeration requests to be deleted via "CancelRequest" _after_ | |
| 590 // the request has been successfully fulfilled. | |
| 591 // See note in FinalizeEnumerateDevices for a recommendation on how | |
| 592 // we should refactor this. | |
| 593 DeleteRequest(label); | |
| 594 return; | |
| 595 } | |
| 596 | |
| 597 // This is a request for opening one or more devices. | 562 // This is a request for opening one or more devices. |
| 598 for (const StreamDeviceInfo& device_info : request->devices) { | 563 for (const StreamDeviceInfo& device_info : request->devices) { |
| 599 const MediaRequestState state = request->state(device_info.device.type); | 564 const MediaRequestState state = request->state(device_info.device.type); |
| 600 // If we have not yet requested the device to be opened - just ignore it. | 565 // If we have not yet requested the device to be opened - just ignore it. |
| 601 if (state != MEDIA_REQUEST_STATE_OPENING && | 566 if (state != MEDIA_REQUEST_STATE_OPENING && |
| 602 state != MEDIA_REQUEST_STATE_DONE) { | 567 state != MEDIA_REQUEST_STATE_DONE) { |
| 603 continue; | 568 continue; |
| 604 } | 569 } |
| 605 // Stop the opening/opened devices of the requests. | 570 // Stop the opening/opened devices of the requests. |
| 606 CloseDevice(device_info.device.type, device_info.session_id); | 571 CloseDevice(device_info.device.type, device_info.session_id); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 if (device_info.session_id == session_id && | 682 if (device_info.session_id == session_id && |
| 718 device_info.device.type == type) { | 683 device_info.device.type == type) { |
| 719 // Notify observers that this device is being closed. | 684 // Notify observers that this device is being closed. |
| 720 // Note that only one device per type can be opened. | 685 // Note that only one device per type can be opened. |
| 721 request->SetState(type, MEDIA_REQUEST_STATE_CLOSING); | 686 request->SetState(type, MEDIA_REQUEST_STATE_CLOSING); |
| 722 } | 687 } |
| 723 } | 688 } |
| 724 } | 689 } |
| 725 } | 690 } |
| 726 | 691 |
| 727 std::string MediaStreamManager::EnumerateDevices( | |
| 728 MediaStreamRequester* requester, | |
| 729 int render_process_id, | |
| 730 int render_frame_id, | |
| 731 const std::string& salt, | |
| 732 int page_request_id, | |
| 733 MediaStreamType type, | |
| 734 const url::Origin& security_origin) { | |
| 735 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 736 DCHECK(requester); | |
| 737 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || | |
| 738 type == MEDIA_DEVICE_VIDEO_CAPTURE || | |
| 739 type == MEDIA_DEVICE_AUDIO_OUTPUT); | |
| 740 | |
| 741 DeviceRequest* request = | |
| 742 new DeviceRequest(requester, render_process_id, render_frame_id, | |
| 743 page_request_id, security_origin, | |
| 744 false, // user gesture | |
| 745 MEDIA_ENUMERATE_DEVICES, StreamControls(), salt); | |
| 746 if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT) | |
| 747 request->SetAudioType(type); | |
| 748 else if (IsVideoMediaType(type)) | |
| 749 request->SetVideoType(type); | |
| 750 | |
| 751 const std::string& label = AddRequest(request); | |
| 752 // Post a task and handle the request asynchronously. The reason is that the | |
| 753 // requester won't have a label for the request until this function returns | |
| 754 // and thus can not handle a response. Using base::Unretained is safe since | |
| 755 // MediaStreamManager is deleted on the UI thread, after the IO thread has | |
| 756 // been stopped. | |
| 757 BrowserThread::PostTask( | |
| 758 BrowserThread::IO, FROM_HERE, | |
| 759 base::Bind(&MediaStreamManager::DoEnumerateDevices, | |
| 760 base::Unretained(this), label)); | |
| 761 return label; | |
| 762 } | |
| 763 | |
| 764 void MediaStreamManager::DoEnumerateDevices(const std::string& label) { | |
| 765 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 766 DeviceRequest* request = FindRequest(label); | |
| 767 if (!request) | |
| 768 return; // This can happen if the request has been canceled. | |
| 769 | |
| 770 if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) { | |
| 771 DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type()); | |
| 772 request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED); | |
| 773 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate; | |
| 774 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true; | |
| 775 media_devices_manager_->EnumerateDevices( | |
| 776 devices_to_enumerate, | |
| 777 base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated, | |
| 778 base::Unretained(this), label)); | |
| 779 return; | |
| 780 } | |
| 781 | |
| 782 StartEnumeration(request, label); | |
| 783 DVLOG(1) << "Enumerate Devices ({label = " << label << "})"; | |
| 784 } | |
| 785 | |
| 786 void MediaStreamManager::AudioOutputDevicesEnumerated( | |
| 787 const std::string& label, | |
| 788 const MediaDeviceEnumeration& enumeration) { | |
| 789 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 790 | |
| 791 DeviceRequest* request = FindRequest(label); | |
| 792 if (!request) | |
| 793 return; | |
| 794 | |
| 795 DCHECK_EQ(MEDIA_DEVICE_AUDIO_OUTPUT, request->audio_type()); | |
| 796 DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED, | |
| 797 request->state(MEDIA_DEVICE_AUDIO_OUTPUT)); | |
| 798 DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type); | |
| 799 DCHECK(!request->ui_proxy.get()); | |
| 800 StreamDeviceInfoArray device_infos = ConvertToStreamDeviceInfoArray( | |
| 801 MEDIA_DEVICE_AUDIO_OUTPUT, enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]); | |
| 802 request->devices = device_infos; | |
| 803 FinalizeEnumerateDevices(label, request); | |
| 804 } | |
| 805 | |
| 806 void MediaStreamManager::OpenDevice(MediaStreamRequester* requester, | 692 void MediaStreamManager::OpenDevice(MediaStreamRequester* requester, |
| 807 int render_process_id, | 693 int render_process_id, |
| 808 int render_frame_id, | 694 int render_frame_id, |
| 809 const std::string& salt, | 695 const std::string& salt, |
| 810 int page_request_id, | 696 int page_request_id, |
| 811 const std::string& device_id, | 697 const std::string& device_id, |
| 812 MediaStreamType type, | 698 MediaStreamType type, |
| 813 const url::Origin& security_origin) { | 699 const url::Origin& security_origin) { |
| 814 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 700 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 815 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || | 701 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 } else { | 832 } else { |
| 947 NOTREACHED(); | 833 NOTREACHED(); |
| 948 } | 834 } |
| 949 return false; | 835 return false; |
| 950 } | 836 } |
| 951 | 837 |
| 952 void MediaStreamManager::TranslateDeviceIdToSourceId( | 838 void MediaStreamManager::TranslateDeviceIdToSourceId( |
| 953 DeviceRequest* request, | 839 DeviceRequest* request, |
| 954 MediaStreamDevice* device) { | 840 MediaStreamDevice* device) { |
| 955 if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || | 841 if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || |
| 956 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT || | |
| 957 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) { | 842 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) { |
| 958 device->id = GetHMACForMediaDeviceID(request->salt, | 843 device->id = GetHMACForMediaDeviceID(request->salt, |
| 959 request->security_origin, device->id); | 844 request->security_origin, device->id); |
| 960 if (!device->group_id.empty()) | |
| 961 device->group_id = GetHMACForMediaDeviceID( | |
| 962 request->salt, request->security_origin, device->group_id); | |
| 963 } | 845 } |
| 964 } | 846 } |
| 965 | 847 |
| 966 void MediaStreamManager::StartEnumeration(DeviceRequest* request, | 848 void MediaStreamManager::StartEnumeration(DeviceRequest* request, |
| 967 const std::string& label) { | 849 const std::string& label) { |
| 968 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 850 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 969 | 851 |
| 970 // Start monitoring the devices when doing the first enumeration. | 852 // Start monitoring the devices when doing the first enumeration. |
| 971 media_devices_manager_->StartMonitoring(); | 853 media_devices_manager_->StartMonitoring(); |
| 972 | 854 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 | 954 |
| 1073 // If using the fake UI, it will just auto-select from the available devices. | 955 // If using the fake UI, it will just auto-select from the available devices. |
| 1074 // The fake UI doesn't work for desktop sharing requests since we can't see | 956 // The fake UI doesn't work for desktop sharing requests since we can't see |
| 1075 // its devices from here; always use the real UI for such requests. | 957 // its devices from here; always use the real UI for such requests. |
| 1076 if (use_fake_ui_ && request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) { | 958 if (use_fake_ui_ && request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) { |
| 1077 if (!fake_ui_) | 959 if (!fake_ui_) |
| 1078 fake_ui_.reset(new FakeMediaStreamUIProxy()); | 960 fake_ui_.reset(new FakeMediaStreamUIProxy()); |
| 1079 | 961 |
| 1080 MediaStreamDevices devices; | 962 MediaStreamDevices devices; |
| 1081 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) { | 963 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) { |
| 1082 devices.emplace_back(audio_type, info.device_id, info.label, | 964 devices.emplace_back(audio_type, info.device_id, info.label); |
| 1083 info.group_id); | |
| 1084 } | 965 } |
| 1085 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) { | 966 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) { |
| 1086 devices.emplace_back(video_type, info.device_id, info.label, | 967 devices.emplace_back(video_type, info.device_id, info.label); |
| 1087 info.group_id); | |
| 1088 } | 968 } |
| 1089 | 969 |
| 1090 fake_ui_->SetAvailableDevices(devices); | 970 fake_ui_->SetAvailableDevices(devices); |
| 1091 | 971 |
| 1092 request->ui_proxy = std::move(fake_ui_); | 972 request->ui_proxy = std::move(fake_ui_); |
| 1093 } else { | 973 } else { |
| 1094 request->ui_proxy = MediaStreamUIProxy::Create(); | 974 request->ui_proxy = MediaStreamUIProxy::Create(); |
| 1095 } | 975 } |
| 1096 | 976 |
| 1097 request->ui_proxy->RequestAccess( | 977 request->ui_proxy->RequestAccess( |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 } | 1211 } |
| 1332 | 1212 |
| 1333 void MediaStreamManager::FinalizeOpenDevice(const std::string& label, | 1213 void MediaStreamManager::FinalizeOpenDevice(const std::string& label, |
| 1334 DeviceRequest* request) { | 1214 DeviceRequest* request) { |
| 1335 const StreamDeviceInfoArray& requested_devices = request->devices; | 1215 const StreamDeviceInfoArray& requested_devices = request->devices; |
| 1336 request->requester->DeviceOpened(request->requesting_frame_id, | 1216 request->requester->DeviceOpened(request->requesting_frame_id, |
| 1337 request->page_request_id, | 1217 request->page_request_id, |
| 1338 label, requested_devices.front()); | 1218 label, requested_devices.front()); |
| 1339 } | 1219 } |
| 1340 | 1220 |
| 1341 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, | |
| 1342 DeviceRequest* request) { | |
| 1343 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1344 DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES); | |
| 1345 DCHECK(((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || | |
| 1346 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) && | |
| 1347 request->video_type() == MEDIA_NO_SERVICE) || | |
| 1348 (request->audio_type() == MEDIA_NO_SERVICE && | |
| 1349 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE)); | |
| 1350 | |
| 1351 for (StreamDeviceInfo& device_info : request->devices) | |
| 1352 TranslateDeviceIdToSourceId(request, &device_info.device); | |
| 1353 | |
| 1354 if (use_fake_ui_) { | |
| 1355 if (!fake_ui_) | |
| 1356 fake_ui_.reset(new FakeMediaStreamUIProxy()); | |
| 1357 request->ui_proxy = std::move(fake_ui_); | |
| 1358 } else { | |
| 1359 DCHECK(!request->ui_proxy); | |
| 1360 request->ui_proxy = MediaStreamUIProxy::Create(); | |
| 1361 } | |
| 1362 | |
| 1363 // Output label permissions are based on input permission. | |
| 1364 const MediaStreamType type = | |
| 1365 request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || | |
| 1366 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT | |
| 1367 ? MEDIA_DEVICE_AUDIO_CAPTURE | |
| 1368 : MEDIA_DEVICE_VIDEO_CAPTURE; | |
| 1369 | |
| 1370 request->ui_proxy->CheckAccess( | |
| 1371 request->security_origin, | |
| 1372 type, | |
| 1373 request->requesting_process_id, | |
| 1374 request->requesting_frame_id, | |
| 1375 base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse, | |
| 1376 base::Unretained(this), | |
| 1377 label)); | |
| 1378 } | |
| 1379 | |
| 1380 void MediaStreamManager::HandleCheckMediaAccessResponse( | |
| 1381 const std::string& label, | |
| 1382 bool have_access) { | |
| 1383 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1384 | |
| 1385 DeviceRequest* request = FindRequest(label); | |
| 1386 if (!request) { | |
| 1387 // This can happen if the request was cancelled. | |
| 1388 DVLOG(1) << "The request with label " << label << " does not exist."; | |
| 1389 return; | |
| 1390 } | |
| 1391 | |
| 1392 if (!have_access) | |
| 1393 ClearDeviceLabels(&request->devices); | |
| 1394 | |
| 1395 request->requester->DevicesEnumerated( | |
| 1396 request->requesting_frame_id, | |
| 1397 request->page_request_id, | |
| 1398 label, | |
| 1399 request->devices); | |
| 1400 | |
| 1401 // TODO(guidou): | |
| 1402 // Ideally enumeration requests should be deleted once they have been served | |
| 1403 // (as any request). However, this implementation mixes requests and | |
| 1404 // notifications together so enumeration requests are kept open by some | |
| 1405 // implementations (only Pepper?) and enumerations are done again when | |
| 1406 // device notifications are fired. | |
| 1407 // Implementations that just want to request the device list and be done | |
| 1408 // (e.g. DeviceRequestMessageFilter), they must (confusingly) call | |
| 1409 // CancelRequest() after the request has been fulfilled. This is not | |
| 1410 // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest) | |
| 1411 // and can lead to subtle bugs (requests not deleted at all deleted too | |
| 1412 // early). | |
| 1413 // | |
| 1414 // Basically, it is not clear that using requests as an additional layer on | |
| 1415 // top of device notifications is necessary or good. | |
| 1416 // | |
| 1417 // To add to this, MediaStreamManager currently relies on the external | |
| 1418 // implementations of MediaStreamRequester to delete enumeration requests via | |
| 1419 // CancelRequest and e.g. DeviceRequestMessageFilter does this. However the | |
| 1420 // Pepper implementation does not seem to to this at all (and from what I can | |
| 1421 // see, it is the only implementation that uses an enumeration request as a | |
| 1422 // notification mechanism). | |
| 1423 // | |
| 1424 // We should decouple notifications from enumeration requests and once that | |
| 1425 // has been done, remove the requirement to call CancelRequest() to delete | |
| 1426 // enumeration requests and uncomment the following line: | |
| 1427 // | |
| 1428 // DeleteRequest(label); | |
| 1429 } | |
| 1430 | |
| 1431 void MediaStreamManager::FinalizeMediaAccessRequest( | 1221 void MediaStreamManager::FinalizeMediaAccessRequest( |
| 1432 const std::string& label, | 1222 const std::string& label, |
| 1433 DeviceRequest* request, | 1223 DeviceRequest* request, |
| 1434 const MediaStreamDevices& devices) { | 1224 const MediaStreamDevices& devices) { |
| 1435 if (!request->callback.is_null()) | 1225 if (!request->callback.is_null()) |
| 1436 request->callback.Run(devices, std::move(request->ui_proxy)); | 1226 request->callback.Run(devices, std::move(request->ui_proxy)); |
| 1437 | 1227 |
| 1438 // Delete the request since it is done. | 1228 // Delete the request since it is done. |
| 1439 DeleteRequest(label); | 1229 DeleteRequest(label); |
| 1440 } | 1230 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 const MediaDeviceEnumeration& enumeration) { | 1378 const MediaDeviceEnumeration& enumeration) { |
| 1589 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1379 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1590 | 1380 |
| 1591 DeviceRequest* request = FindRequest(label); | 1381 DeviceRequest* request = FindRequest(label); |
| 1592 if (!request) | 1382 if (!request) |
| 1593 return; | 1383 return; |
| 1594 | 1384 |
| 1595 bool requested[] = {requested_audio_input, requested_video_input}; | 1385 bool requested[] = {requested_audio_input, requested_video_input}; |
| 1596 MediaStreamType stream_types[] = {MEDIA_DEVICE_AUDIO_CAPTURE, | 1386 MediaStreamType stream_types[] = {MEDIA_DEVICE_AUDIO_CAPTURE, |
| 1597 MEDIA_DEVICE_VIDEO_CAPTURE}; | 1387 MEDIA_DEVICE_VIDEO_CAPTURE}; |
| 1598 MediaDeviceType device_types[] = {MEDIA_DEVICE_TYPE_AUDIO_INPUT, | |
| 1599 MEDIA_DEVICE_TYPE_VIDEO_INPUT}; | |
| 1600 | |
| 1601 for (size_t i = 0; i < arraysize(requested); ++i) { | 1388 for (size_t i = 0; i < arraysize(requested); ++i) { |
| 1602 if (!requested[i]) | 1389 if (!requested[i]) |
| 1603 continue; | 1390 continue; |
| 1604 | 1391 |
| 1605 DCHECK(request->audio_type() == stream_types[i] || | 1392 DCHECK(request->audio_type() == stream_types[i] || |
| 1606 request->video_type() == stream_types[i]); | 1393 request->video_type() == stream_types[i]); |
| 1607 if (request->state(stream_types[i]) == MEDIA_REQUEST_STATE_REQUESTED) { | 1394 if (request->state(stream_types[i]) == MEDIA_REQUEST_STATE_REQUESTED) { |
| 1608 if (request->request_type == MEDIA_ENUMERATE_DEVICES) { | |
| 1609 // MEDIA_ENUMERATE_DEVICES requests are always for a single type, so it | |
| 1610 // is OK to ignore any remaining iteration in this loop. | |
| 1611 ProcessEnumerationRequest(label, request, stream_types[i], | |
| 1612 enumeration[device_types[i]]); | |
| 1613 return; | |
| 1614 } | |
| 1615 // Not a MEDIA_ENUMERATE_DEVICES request. | |
| 1616 request->SetState(stream_types[i], MEDIA_REQUEST_STATE_PENDING_APPROVAL); | 1395 request->SetState(stream_types[i], MEDIA_REQUEST_STATE_PENDING_APPROVAL); |
| 1617 } | 1396 } |
| 1618 } | 1397 } |
| 1619 | 1398 |
| 1620 if (!SetupDeviceCaptureRequest(request, enumeration)) | 1399 if (!SetupDeviceCaptureRequest(request, enumeration)) |
| 1621 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE); | 1400 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE); |
| 1622 else | 1401 else |
| 1623 ReadOutputParamsAndPostRequestToUI(label, request, enumeration); | 1402 ReadOutputParamsAndPostRequestToUI(label, request, enumeration); |
| 1624 } | 1403 } |
| 1625 | 1404 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 if (media_observer) | 1600 if (media_observer) |
| 1822 media_observer->OnAudioCaptureDevicesChanged(); | 1601 media_observer->OnAudioCaptureDevicesChanged(); |
| 1823 } else if (IsVideoMediaType(stream_type)) { | 1602 } else if (IsVideoMediaType(stream_type)) { |
| 1824 MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged( | 1603 MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged( |
| 1825 new_devices); | 1604 new_devices); |
| 1826 if (media_observer) | 1605 if (media_observer) |
| 1827 media_observer->OnVideoCaptureDevicesChanged(); | 1606 media_observer->OnVideoCaptureDevicesChanged(); |
| 1828 } else { | 1607 } else { |
| 1829 NOTREACHED(); | 1608 NOTREACHED(); |
| 1830 } | 1609 } |
| 1831 | |
| 1832 ProcessOpenEnumerationRequests(stream_type, devices); | |
| 1833 } | 1610 } |
| 1834 | 1611 |
| 1835 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { | 1612 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
| 1836 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1613 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1837 | 1614 |
| 1838 const bool requested_audio = IsAudioInputMediaType(request.audio_type()); | 1615 const bool requested_audio = IsAudioInputMediaType(request.audio_type()); |
| 1839 const bool requested_video = IsVideoMediaType(request.video_type()); | 1616 const bool requested_video = IsVideoMediaType(request.video_type()); |
| 1840 | 1617 |
| 1841 const bool audio_done = | 1618 const bool audio_done = |
| 1842 !requested_audio || | 1619 !requested_audio || |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 // Re-registering (overwriting) is allowed and happens in some tests. | 1680 // Re-registering (overwriting) is allowed and happens in some tests. |
| 1904 log_callbacks_[renderer_host_id] = callback; | 1681 log_callbacks_[renderer_host_id] = callback; |
| 1905 } | 1682 } |
| 1906 | 1683 |
| 1907 void MediaStreamManager::DoNativeLogCallbackUnregistration( | 1684 void MediaStreamManager::DoNativeLogCallbackUnregistration( |
| 1908 int renderer_host_id) { | 1685 int renderer_host_id) { |
| 1909 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1686 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1910 log_callbacks_.erase(renderer_host_id); | 1687 log_callbacks_.erase(renderer_host_id); |
| 1911 } | 1688 } |
| 1912 | 1689 |
| 1913 void MediaStreamManager::SubscribeToDeviceChangeNotifications( | |
| 1914 MediaStreamRequester* subscriber) { | |
| 1915 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1916 DCHECK(subscriber); | |
| 1917 DCHECK(std::find_if(device_change_subscribers_.begin(), | |
| 1918 device_change_subscribers_.end(), | |
| 1919 [subscriber](MediaStreamRequester* item) { | |
| 1920 return subscriber == item; | |
| 1921 }) == device_change_subscribers_.end()); | |
| 1922 device_change_subscribers_.push_back(subscriber); | |
| 1923 } | |
| 1924 | |
| 1925 void MediaStreamManager::CancelDeviceChangeNotifications( | |
| 1926 MediaStreamRequester* subscriber) { | |
| 1927 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1928 auto it = std::find(device_change_subscribers_.begin(), | |
| 1929 device_change_subscribers_.end(), subscriber); | |
| 1930 CHECK(it != device_change_subscribers_.end()); | |
| 1931 device_change_subscribers_.erase(it); | |
| 1932 } | |
| 1933 | |
| 1934 void MediaStreamManager::NotifyDeviceChangeSubscribers(MediaStreamType type) { | |
| 1935 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1936 for (auto* subscriber : device_change_subscribers_) | |
| 1937 subscriber->DevicesChanged(type); | |
| 1938 } | |
| 1939 | |
| 1940 // static | 1690 // static |
| 1941 std::string MediaStreamManager::GetHMACForMediaDeviceID( | 1691 std::string MediaStreamManager::GetHMACForMediaDeviceID( |
| 1942 const std::string& salt, | 1692 const std::string& salt, |
| 1943 const url::Origin& security_origin, | 1693 const url::Origin& security_origin, |
| 1944 const std::string& raw_unique_id) { | 1694 const std::string& raw_unique_id) { |
| 1945 DCHECK(!raw_unique_id.empty()); | 1695 DCHECK(!raw_unique_id.empty()); |
| 1946 if (raw_unique_id == media::AudioDeviceDescription::kDefaultDeviceId || | 1696 if (raw_unique_id == media::AudioDeviceDescription::kDefaultDeviceId || |
| 1947 raw_unique_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { | 1697 raw_unique_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { |
| 1948 return raw_unique_id; | 1698 return raw_unique_id; |
| 1949 } | 1699 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1995 for (const StreamDeviceInfo& device_info : request->devices) { | 1745 for (const StreamDeviceInfo& device_info : request->devices) { |
| 1996 if (device_info.session_id == session_id && | 1746 if (device_info.session_id == session_id && |
| 1997 device_info.device.type == type) { | 1747 device_info.device.type == type) { |
| 1998 request->SetCapturingLinkSecured(is_secure); | 1748 request->SetCapturingLinkSecured(is_secure); |
| 1999 return; | 1749 return; |
| 2000 } | 1750 } |
| 2001 } | 1751 } |
| 2002 } | 1752 } |
| 2003 } | 1753 } |
| 2004 | 1754 |
| 2005 void MediaStreamManager::ProcessEnumerationRequest( | |
| 2006 const std::string& label, | |
| 2007 DeviceRequest* request, | |
| 2008 MediaStreamType stream_type, | |
| 2009 const MediaDeviceInfoArray& device_infos) { | |
| 2010 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 2011 DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED, request->state(stream_type)); | |
| 2012 DCHECK(request->audio_type() == stream_type || | |
| 2013 request->video_type() == stream_type); | |
| 2014 DCHECK(request->audio_type() == MEDIA_NO_SERVICE || | |
| 2015 request->video_type() == MEDIA_NO_SERVICE); | |
| 2016 DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type); | |
| 2017 | |
| 2018 if (request->requester && !request->ui_proxy) { | |
| 2019 request->devices = | |
| 2020 ConvertToStreamDeviceInfoArray(stream_type, device_infos); | |
| 2021 FinalizeEnumerateDevices(label, request); | |
| 2022 } | |
| 2023 } | |
| 2024 | |
| 2025 // This function is intended to support subscription-style device enumerations. | |
| 2026 // It is only supported for media capture devices and will be removed once | |
| 2027 // handling of enumeration requests and device-change notifications is migrated | |
| 2028 // out of MediaStreamManager. | |
| 2029 void MediaStreamManager::ProcessOpenEnumerationRequests( | |
| 2030 MediaStreamType stream_type, | |
| 2031 const MediaDeviceInfoArray& device_infos) { | |
| 2032 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 2033 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || | |
| 2034 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); | |
| 2035 | |
| 2036 for (const LabeledDeviceRequest& labeled_request : requests_) { | |
| 2037 DeviceRequest* request = labeled_request.second; | |
| 2038 if (request->request_type == MEDIA_ENUMERATE_DEVICES && | |
| 2039 request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED && | |
| 2040 (request->audio_type() == stream_type || | |
| 2041 request->video_type() == stream_type)) { | |
| 2042 ProcessEnumerationRequest(labeled_request.first, request, stream_type, | |
| 2043 device_infos); | |
| 2044 } | |
| 2045 } | |
| 2046 } | |
| 2047 | |
| 2048 void MediaStreamManager::SetGenerateStreamCallbackForTesting( | 1755 void MediaStreamManager::SetGenerateStreamCallbackForTesting( |
| 2049 GenerateStreamTestCallback test_callback) { | 1756 GenerateStreamTestCallback test_callback) { |
| 2050 generate_stream_test_callback_ = test_callback; | 1757 generate_stream_test_callback_ = test_callback; |
| 2051 } | 1758 } |
| 2052 | 1759 |
| 2053 } // namespace content | 1760 } // namespace content |
| OLD | NEW |