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

Unified Diff: content/browser/renderer_host/media/audio_renderer_host.cc

Issue 1323403005: Allow AudioOutputDevice objects to be initialized with a specific hardware output device and store … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Split permissions check and device-ID translation for clarity Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/media/audio_renderer_host.cc
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index dddeee21626a31f30aff5b4f749c396fcd5024b8..515782af139c1b739f612bf92302ecf26c351f21 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/media/audio_renderer_host.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
@@ -61,6 +63,12 @@ void NotifyResourceDispatcherOfAudioStateChange(int render_process_id,
render_process_id, render_view_id, is_playing);
}
+media::AudioParameters DummyParams() {
+ return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LINEAR,
+ media::CHANNEL_LAYOUT_STEREO,
+ media::limits::kMinSampleRate, 1, 1);
+}
+
} // namespace
class AudioRendererHost::AudioEntry
@@ -143,6 +151,64 @@ AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost::AudioEntry::~AudioEntry() {}
+class AudioRendererHost::AuthorizationData {
DaleCurtis 2015/09/09 01:31:57 Hmm, this is a lot of data and complexity added to
Guido Urdaneta 2015/09/09 16:22:23 I removed this class altogether and replaced it wi
+ public:
+ explicit AuthorizationData(int render_frame_id);
+ AuthorizationData(int render_frame_id,
+ const std::string& unique_id,
+ const media::AudioParameters& output_params);
+ ~AuthorizationData() = default;
+ bool is_authorized() const { return is_authorized_; }
+ int render_frame_id() const { return render_frame_id_; }
+ bool is_creation_requested() const { return is_creation_requested_; }
+ media::AudioParameters creation_params() const { return creation_params_; }
+ std::string device_unique_id() const { return device_unique_id_; }
+ media::AudioParameters device_output_params() const {
+ return device_output_params_;
+ }
+
+ void Authorize(const std::string& unique_id,
+ const media::AudioParameters& output_params);
+ void RequestCreation(const media::AudioParameters& params);
+
+ private:
+ bool is_authorized_;
+ int render_frame_id_;
+ bool is_creation_requested_;
+ media::AudioParameters creation_params_;
+ std::string device_unique_id_;
+ media::AudioParameters device_output_params_;
+};
+
+AudioRendererHost::AuthorizationData::AuthorizationData(int render_frame_id)
+ : is_authorized_(false),
+ render_frame_id_(render_frame_id),
+ is_creation_requested_(false) {}
+
+AudioRendererHost::AuthorizationData::AuthorizationData(
+ int render_frame_id,
+ const std::string& device_unique_id,
+ const media::AudioParameters& device_output_params)
+ : is_authorized_(true),
+ render_frame_id_(render_frame_id),
+ is_creation_requested_(false),
+ device_unique_id_(device_unique_id),
+ device_output_params_(device_output_params) {}
+
+void AudioRendererHost::AuthorizationData::Authorize(
+ const std::string& device_unique_id,
+ const media::AudioParameters& device_output_params) {
+ is_authorized_ = true;
+ device_unique_id_ = device_unique_id;
+ device_output_params_ = device_output_params;
+}
+
+void AudioRendererHost::AuthorizationData::RequestCreation(
+ const media::AudioParameters& params) {
+ is_creation_requested_ = true;
+ creation_params_ = params;
+}
+
///////////////////////////////////////////////////////////////////////////////
// AudioRendererHost implementations.
@@ -184,6 +250,9 @@ void AudioRendererHost::OnChannelClosing() {
// Note: OnCloseStream() removes the entries from audio_entries_.
OnCloseStream(audio_entries_.begin()->first);
}
+
+ // Remove any authorizations for streams that were not yet created
+ authorizations_.clear();
}
void AudioRendererHost::OnDestruct() const {
@@ -312,6 +381,8 @@ AudioRendererHost::DoGetOutputControllers() const {
bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
+ IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization,
+ OnRequestDeviceAuthorization)
IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
@@ -324,17 +395,140 @@ bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void AudioRendererHost::OnRequestDeviceAuthorization(
+ int stream_id,
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const GURL& security_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
+ << "(stream_id=" << stream_id
+ << ", render_frame_id=" << render_frame_id
+ << ", session_id=" << session_id << ", device_id=" << device_id
+ << ", security_origin=" << security_origin << ")";
+
+ if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
+ return;
+
+ // If attempting to use the output device associated to an opened input
+ // device and the output device is found, reuse the input device
+ // permissions.
+ if (session_id != 0) {
+ const StreamDeviceInfo* info =
+ media_stream_manager_->audio_input_device_manager()
+ ->GetOpenedDeviceInfoById(session_id);
+ if (info) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ static_cast<media::ChannelLayout>(
+ info->device.matched_output.channel_layout),
+ info->device.matched_output.sample_rate, 16,
+ info->device.matched_output.frames_per_buffer,
+ info->device.matched_output.effects);
+ authorizations_.insert(std::pair<int, AuthorizationData>(
+ stream_id, AuthorizationData(render_frame_id,
+ info->device.matched_output_device_id,
+ output_params)));
+ Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, true, output_params));
+ return;
+ }
+ }
+
+ authorizations_.insert(std::pair<int, AuthorizationData>(
+ stream_id, AuthorizationData(render_frame_id)));
+ CheckOutputDeviceAccess(
+ render_frame_id, device_id, security_origin,
+ base::Bind(&AudioRendererHost::RequestDeviceAuthorizationAccessChecked,
+ this, stream_id, device_id, security_origin));
+}
+
+void AudioRendererHost::RequestDeviceAuthorizationAccessChecked(
+ int stream_id,
+ const std::string& device_id,
+ const GURL& security_origin,
+ bool have_access) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const auto& auth_data = authorizations_.find(stream_id);
+
+ // A close request was received while access check was in progress.
+ if (auth_data == authorizations_.end())
+ return;
+
+ if (!have_access) {
+ authorizations_.erase(auth_data);
+ Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, false, DummyParams()));
+ return;
+ }
+
+ TranslateDeviceID(
+ device_id, security_origin,
+ base::Bind(&AudioRendererHost::RequestDeviceAuthorizationTranslated, this,
+ stream_id));
+}
+
+void AudioRendererHost::RequestDeviceAuthorizationTranslated(
+ int stream_id,
+ bool device_found,
+ const AudioOutputDeviceInfo& device_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const auto& auth_data = authorizations_.find(stream_id);
+
+ // A close request was received while access check was in progress
DaleCurtis 2015/09/09 01:31:57 translate was in progress?
Guido Urdaneta 2015/09/09 16:22:23 Done.
+ if (auth_data == authorizations_.end())
+ return;
+
+ if (!device_found) {
+ authorizations_.erase(auth_data);
+ Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, false, DummyParams()));
+ return;
+ }
+
+ auth_data->second.Authorize(device_info.unique_id, device_info.output_params);
+ Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, true,
+ device_info.output_params));
+
+ if (auth_data->second.is_creation_requested()) {
+ DoCreateStream(stream_id, auth_data->second.render_frame_id(),
+ auth_data->second.creation_params(), device_info.unique_id);
+ authorizations_.erase(auth_data);
+ }
+}
+
void AudioRendererHost::OnCreateStream(int stream_id,
int render_frame_id,
- int session_id,
const media::AudioParameters& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "AudioRendererHost@" << this
- << "::OnCreateStream(stream_id=" << stream_id
- << ", render_frame_id=" << render_frame_id
- << ", session_id=" << session_id << ")";
- DCHECK_GT(render_frame_id, 0);
+ DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
+ << "(stream_id=" << stream_id << ")";
+
+ const auto& auth_data = authorizations_.find(stream_id);
+
+ // If no previous authorization requested, assume default device
+ if (auth_data == authorizations_.end()) {
+ DoCreateStream(stream_id, render_frame_id, params, std::string());
+ return;
+ }
+
+ DCHECK_EQ(render_frame_id, auth_data->second.render_frame_id());
+ // If authorization is ongoing, defer creation.
DaleCurtis 2015/09/09 01:31:57 This ends up adding substantial complexity. Can we
Guido Urdaneta 2015/09/09 16:22:23 Done. See comment above.
+ if (!auth_data->second.is_authorized()) {
+ auth_data->second.RequestCreation(params);
+ return;
+ }
+
+ // If already authorized, create stream and remove authorization
+ DoCreateStream(stream_id, render_frame_id, params,
+ auth_data->second.device_unique_id());
+ authorizations_.erase(auth_data);
+}
+
+void AudioRendererHost::DoCreateStream(int stream_id,
+ int render_frame_id,
+ const media::AudioParameters& params,
+ const std::string& device_unique_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// media::AudioParameters is validated in the deserializer.
if (LookupById(stream_id) != NULL) {
@@ -342,15 +536,6 @@ void AudioRendererHost::OnCreateStream(int stream_id,
return;
}
- // Initialize the |output_device_id| to an empty string which indicates that
- // the default device should be used. If a StreamDeviceInfo instance was found
- // though, then we use the matched output device.
- std::string output_device_id;
- const StreamDeviceInfo* info = media_stream_manager_->
- audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
- if (info)
- output_device_id = info->device.matched_output_device_id;
-
// Create the shared memory and share with the renderer process.
uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
@@ -371,19 +556,16 @@ void AudioRendererHost::OnCreateStream(int stream_id,
if (media_observer)
media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
- scoped_ptr<AudioEntry> entry(new AudioEntry(this,
- stream_id,
- render_frame_id,
- params,
- output_device_id,
- shared_memory.Pass(),
- reader.Pass()));
+ scoped_ptr<AudioEntry> entry(
+ new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id,
+ shared_memory.Pass(), reader.Pass()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
render_process_id_, entry->render_frame_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
- audio_log_->OnCreated(stream_id, params, output_device_id);
+
+ audio_log_->OnCreated(stream_id, params, device_unique_id);
MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry(
stream_id, render_process_id_, render_frame_id, audio_log_.get());
}
@@ -433,150 +615,70 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
void AudioRendererHost::OnSwitchOutputDevice(int stream_id,
DaleCurtis 2015/09/09 01:31:57 As mentioned in the AOD class, after this CL lands
Guido Urdaneta 2015/09/09 16:22:23 That is the goal. A possible road map after this
DaleCurtis 2015/09/12 01:17:19 sgtm!
int render_frame_id,
const std::string& device_id,
- const GURL& security_origin,
- int request_id) {
+ const GURL& security_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "AudioRendererHost@" << this
<< "::OnSwitchOutputDevice(stream_id=" << stream_id
<< ", render_frame_id=" << render_frame_id
<< ", device_id=" << device_id
- << ", security_origin=" << security_origin
- << ", request_id=" << request_id << ")";
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
- render_process_id_, security_origin)) {
- content::bad_message::ReceivedBadMessage(this,
- bad_message::ARH_UNAUTHORIZED_URL);
- return;
- }
-
- if (device_id.empty()) {
- DVLOG(1) << __FUNCTION__ << ": default output device requested. "
- << "No permissions check or device translation/validation needed.";
- DoSwitchOutputDevice(stream_id, device_id, request_id);
- } else {
- // Check that MediaStream device permissions have been granted,
- // hence the use of a MediaStreamUIProxy.
- scoped_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
-
- // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT
- // because MediaStreamUIProxy::CheckAccess does not currently support
- // MEDIA_DEVICE_AUDIO_OUTPUT.
- // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes
- // available. http://crbug.com/498675
- ui_proxy->CheckAccess(
- security_origin, MEDIA_DEVICE_AUDIO_CAPTURE,
- render_process_id_, render_frame_id,
- base::Bind(&AudioRendererHost::OutputDeviceAccessChecked, this,
- base::Passed(&ui_proxy), stream_id, device_id,
- security_origin, render_frame_id, request_id));
- }
+ << ", security_origin=" << security_origin << ")";
+ CheckOutputDeviceAccess(
+ render_frame_id, device_id, security_origin,
+ base::Bind(&AudioRendererHost::SwitchOutputDeviceAccessChecked, this,
+ stream_id, device_id, security_origin));
}
-void AudioRendererHost::OutputDeviceAccessChecked(
- scoped_ptr<MediaStreamUIProxy> ui_proxy,
+void AudioRendererHost::SwitchOutputDeviceAccessChecked(
int stream_id,
const std::string& device_id,
const GURL& security_origin,
- int render_frame_id,
- int request_id,
bool have_access) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << __FUNCTION__;
if (!have_access) {
- DVLOG(0) << __FUNCTION__
- << ": Have no access to media devices. Not switching device.";
Send(new AudioMsg_NotifyOutputDeviceSwitched(
- stream_id, request_id,
- media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED));
+ stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED,
+ DummyParams()));
return;
}
- scoped_refptr<base::SingleThreadTaskRunner> audio_worker_runner =
- AudioManager::Get()->GetWorkerTaskRunner();
- audio_worker_runner->PostTask(
- FROM_HERE,
- base::Bind(&AudioRendererHost::StartTranslateOutputDeviceName, this,
- stream_id, device_id, security_origin, request_id));
+ TranslateDeviceID(device_id, security_origin,
+ base::Bind(&AudioRendererHost::SwitchOutputDeviceTranslated,
+ this, stream_id));
}
-void AudioRendererHost::StartTranslateOutputDeviceName(
+void AudioRendererHost::SwitchOutputDeviceTranslated(
int stream_id,
- const std::string& device_id,
- const GURL& security_origin,
- int request_id) {
- DCHECK(AudioManager::Get()->GetWorkerTaskRunner()->BelongsToCurrentThread());
- DCHECK(!device_id.empty());
- DVLOG(1) << __FUNCTION__;
-
- media::AudioDeviceNames* device_names(new media::AudioDeviceNames);
- AudioManager::Get()->GetAudioOutputDeviceNames(device_names);
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioRendererHost::FinishTranslateOutputDeviceName, this,
- stream_id, device_id, security_origin, request_id,
- base::Owned(device_names)));
-}
-
-void AudioRendererHost::FinishTranslateOutputDeviceName(
- int stream_id,
- const std::string& device_id,
- const GURL& security_origin,
- int request_id,
- media::AudioDeviceNames* device_names) {
+ bool device_found,
+ const AudioOutputDeviceInfo& device_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!device_id.empty());
- DVLOG(1) << __FUNCTION__;
-
- std::string raw_device_id;
- // Process the enumeration here because |salt_callback_| can run
- // only on the IO thread
- for (const auto& device_name : *device_names) {
- const std::string candidate_device_id = content::GetHMACForMediaDeviceID(
- salt_callback_, security_origin, device_name.unique_id);
- if (candidate_device_id == device_id) {
- DVLOG(1) << "Requested device " << device_name.unique_id << " - "
- << device_name.device_name;
- raw_device_id = device_name.unique_id;
- }
- }
-
- if (raw_device_id.empty()) {
- DVLOG(1) << "Requested device " << device_id << " could not be found.";
+ if (!device_found) {
Send(new AudioMsg_NotifyOutputDeviceSwitched(
- stream_id, request_id,
- media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND));
+ stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND,
+ DummyParams()));
return;
}
- DoSwitchOutputDevice(stream_id, raw_device_id, request_id);
-}
-
-void AudioRendererHost::DoSwitchOutputDevice(int stream_id,
- const std::string& raw_device_id,
- int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << __FUNCTION__ << "(" << stream_id << ", " << raw_device_id << ", "
- << request_id << ")";
AudioEntry* entry = LookupById(stream_id);
if (!entry) {
Send(new AudioMsg_NotifyOutputDeviceSwitched(
- stream_id, request_id,
- media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE));
+ stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL,
+ DummyParams()));
return;
}
entry->controller()->SwitchOutputDevice(
- raw_device_id, base::Bind(&AudioRendererHost::DoOutputDeviceSwitched,
- this, stream_id, request_id));
- audio_log_->OnSwitchOutputDevice(entry->stream_id(), raw_device_id);
+ device_info.unique_id,
+ base::Bind(&AudioRendererHost::OutputDeviceSwitched, this, stream_id,
+ device_info.output_params));
+ audio_log_->OnSwitchOutputDevice(entry->stream_id(), device_info.unique_id);
}
-void AudioRendererHost::DoOutputDeviceSwitched(int stream_id, int request_id) {
+void AudioRendererHost::OutputDeviceSwitched(
+ int stream_id,
+ const media::AudioParameters& output_params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << __FUNCTION__ << "(" << stream_id << ", " << request_id << ")";
Send(new AudioMsg_NotifyOutputDeviceSwitched(
- stream_id, request_id, media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS));
+ stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS, output_params));
}
void AudioRendererHost::SendErrorMessage(int stream_id) {
@@ -586,6 +688,7 @@ void AudioRendererHost::SendErrorMessage(int stream_id) {
void AudioRendererHost::OnCloseStream(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ authorizations_.erase(stream_id);
// Prevent oustanding callbacks from attempting to close/delete the same
// AudioEntry twice.
@@ -683,4 +786,90 @@ bool AudioRendererHost::RenderFrameHasActiveAudio(int render_frame_id) const {
return false;
}
+void AudioRendererHost::CheckOutputDeviceAccess(
+ int render_frame_id,
+ const std::string& device_id,
+ const GURL& security_origin,
+ const OutputDeviceAccessCB& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Skip origin check in requests for the default device with an empty
+ // security origin.
+ bool skip_origin_check = security_origin.is_empty() && device_id.empty();
+ if (!skip_origin_check &&
+ !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+ render_process_id_, security_origin)) {
+ content::bad_message::ReceivedBadMessage(this,
+ bad_message::ARH_UNAUTHORIZED_URL);
+ return;
+ }
+
+ if (device_id.empty()) {
+ callback.Run(true);
+ } else {
+ // Check that MediaStream device permissions have been granted,
+ // hence the use of a MediaStreamUIProxy.
+ scoped_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
+
+ // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT
+ // because MediaStreamUIProxy::CheckAccess does not currently support
+ // MEDIA_DEVICE_AUDIO_OUTPUT.
+ // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes
+ // available. http://crbug.com/498675
+ ui_proxy->CheckAccess(security_origin, MEDIA_DEVICE_AUDIO_CAPTURE,
+ render_process_id_, render_frame_id,
+ base::Bind(&AudioRendererHost::AccessChecked, this,
+ base::Passed(&ui_proxy), callback));
+ }
+}
+
+void AudioRendererHost::AccessChecked(scoped_ptr<MediaStreamUIProxy> ui_proxy,
+ const OutputDeviceAccessCB& callback,
+ bool have_access) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ callback.Run(have_access);
+}
+
+void AudioRendererHost::TranslateDeviceID(const std::string& device_id,
+ const GURL& security_origin,
+ const OutputDeviceInfoCB& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ AudioOutputDeviceEnumerator* enumerator =
+ media_stream_manager_->audio_output_device_enumerator();
+ enumerator->Enumerate(base::Bind(&AudioRendererHost::FinishTranslateDeviceID,
+ this, device_id, security_origin, callback));
+}
+
+void AudioRendererHost::FinishTranslateDeviceID(
+ const std::string& device_id,
+ const GURL& security_origin,
+ const OutputDeviceInfoCB& callback,
+ const AudioOutputDeviceEnumeration& device_infos) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ bool use_default_device = device_id.empty();
+ for (const AudioOutputDeviceInfo& device_info : device_infos) {
+ if (use_default_device) {
+ if (device_info.unique_id == media::AudioManagerBase::kDefaultDeviceId) {
+ callback.Run(true, device_info);
+ return;
+ }
+ } else {
+ const std::string candidate_device_id = content::GetHMACForMediaDeviceID(
+ salt_callback_, security_origin, device_info.unique_id);
+ if (candidate_device_id == device_id) {
+ callback.Run(true, device_info);
+ return;
+ }
+ }
+ }
+ DCHECK(!use_default_device); // Default device must always be found
+ callback.Run(false, {std::string(), std::string(), DummyParams()});
DaleCurtis 2015/09/09 01:31:57 Is this initialization syntax allowed? http://chro
Guido Urdaneta 2015/09/09 16:22:23 Structs are allowed to be initialized this way, bu
+}
+
+bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const auto& i = authorizations_.find(stream_id);
+ return i != authorizations_.end();
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698