blob: 676b2fb44b931b0da3b0f01a89dc5404953cafe6 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/pepper/pepper_media_device_manager.h"
#include "base/logging.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/render_frame_impl.h"
#include "ppapi/shared_impl/ppb_device_ref_shared.h"
namespace content {
namespace {
ppapi::DeviceRefData FromStreamDeviceInfo(const StreamDeviceInfo& info) {
ppapi::DeviceRefData data;
data.id = info.device.id;
// Some Flash content can't handle an empty string, so stick a space in to
// make them happy. See crbug.com/408404.
data.name = info.device.name.empty() ? std::string(" ") : info.device.name;
data.type = PepperMediaDeviceManager::FromMediaStreamType(info.device.type);
return data;
}
} // namespace
base::WeakPtr<PepperMediaDeviceManager>
PepperMediaDeviceManager::GetForRenderFrame(
RenderFrame* render_frame) {
PepperMediaDeviceManager* handler =
PepperMediaDeviceManager::Get(render_frame);
if (!handler)
handler = new PepperMediaDeviceManager(render_frame);
return handler->AsWeakPtr();
}
PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame),
next_id_(1) {}
PepperMediaDeviceManager::~PepperMediaDeviceManager() {
DCHECK(enumerate_callbacks_.empty());
DCHECK(open_callbacks_.empty());
}
int PepperMediaDeviceManager::EnumerateDevices(
PP_DeviceType_Dev type,
const GURL& document_url,
const EnumerateDevicesCallback& callback) {
enumerate_callbacks_[next_id_] = callback;
int request_id = next_id_++;
#if defined(ENABLE_WEBRTC)
GetMediaStreamDispatcher()->EnumerateDevices(
request_id,
AsWeakPtr(),
PepperMediaDeviceManager::FromPepperDeviceType(type),
document_url.GetOrigin());
#else
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PepperMediaDeviceManager::OnDevicesEnumerated,
AsWeakPtr(),
request_id,
StreamDeviceInfoArray()));
#endif
return request_id;
}
void PepperMediaDeviceManager::StopEnumerateDevices(int request_id) {
enumerate_callbacks_.erase(request_id);
#if defined(ENABLE_WEBRTC)
// Need to post task since this function might be called inside the callback
// of EnumerateDevices.
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PepperMediaDeviceManager::StopEnumerateDevicesDelayed,
AsWeakPtr(),
request_id));
#endif
}
void PepperMediaDeviceManager::StopEnumerateDevicesDelayed(int request_id) {
#if defined(ENABLE_WEBRTC)
// This method is being invoked by the message loop at some unknown
// point-in-time after StopEnumerateDevices(). Therefore, check that
// render_frame() is not NULL, in order to guarantee
// GetMediaStreamDispatcher() won't return NULL.
if (render_frame())
GetMediaStreamDispatcher()->StopEnumerateDevices(request_id, AsWeakPtr());
#endif
}
int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
const std::string& device_id,
const GURL& document_url,
const OpenDeviceCallback& callback) {
open_callbacks_[next_id_] = callback;
int request_id = next_id_++;
#if defined(ENABLE_WEBRTC)
GetMediaStreamDispatcher()->OpenDevice(
request_id,
AsWeakPtr(),
device_id,
PepperMediaDeviceManager::FromPepperDeviceType(type),
document_url.GetOrigin());
#else
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PepperMediaDeviceManager::OnDeviceOpenFailed,
AsWeakPtr(),
request_id));
#endif
return request_id;
}
void PepperMediaDeviceManager::CancelOpenDevice(int request_id) {
open_callbacks_.erase(request_id);
#if defined(ENABLE_WEBRTC)
GetMediaStreamDispatcher()->CancelOpenDevice(request_id, AsWeakPtr());
#endif
}
void PepperMediaDeviceManager::CloseDevice(const std::string& label) {
#if defined(ENABLE_WEBRTC)
GetMediaStreamDispatcher()->CloseDevice(label);
#endif
}
int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type,
const std::string& label) {
#if defined(ENABLE_WEBRTC)
switch (type) {
case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
return GetMediaStreamDispatcher()->audio_session_id(label, 0);
case PP_DEVICETYPE_DEV_VIDEOCAPTURE:
return GetMediaStreamDispatcher()->video_session_id(label, 0);
default:
NOTREACHED();
return 0;
}
#else
return 0;
#endif
}
void PepperMediaDeviceManager::OnStreamGenerated(
int request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_device_array,
const StreamDeviceInfoArray& video_device_array) {}
void PepperMediaDeviceManager::OnStreamGenerationFailed(
int request_id,
content::MediaStreamRequestResult result) {}
void PepperMediaDeviceManager::OnDeviceStopped(
const std::string& label,
const StreamDeviceInfo& device_info) {}
void PepperMediaDeviceManager::OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) {
EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id);
if (iter == enumerate_callbacks_.end()) {
// This might be enumerated result sent before StopEnumerateDevices is
// called since EnumerateDevices is persistent request.
return;
}
EnumerateDevicesCallback callback = iter->second;
std::vector<ppapi::DeviceRefData> devices;
devices.reserve(device_array.size());
for (StreamDeviceInfoArray::const_iterator info = device_array.begin();
info != device_array.end();
++info) {
devices.push_back(FromStreamDeviceInfo(*info));
}
callback.Run(request_id, devices);
}
void PepperMediaDeviceManager::OnDeviceOpened(
int request_id,
const std::string& label,
const StreamDeviceInfo& device_info) {
NotifyDeviceOpened(request_id, true, label);
}
void PepperMediaDeviceManager::OnDeviceOpenFailed(int request_id) {
NotifyDeviceOpened(request_id, false, std::string());
}
// static
MediaStreamType PepperMediaDeviceManager::FromPepperDeviceType(
PP_DeviceType_Dev type) {
switch (type) {
case PP_DEVICETYPE_DEV_INVALID:
return MEDIA_NO_SERVICE;
case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
return MEDIA_DEVICE_AUDIO_CAPTURE;
case PP_DEVICETYPE_DEV_VIDEOCAPTURE:
return MEDIA_DEVICE_VIDEO_CAPTURE;
default:
NOTREACHED();
return MEDIA_NO_SERVICE;
}
}
// static
PP_DeviceType_Dev PepperMediaDeviceManager::FromMediaStreamType(
MediaStreamType type) {
switch (type) {
case MEDIA_NO_SERVICE:
return PP_DEVICETYPE_DEV_INVALID;
case MEDIA_DEVICE_AUDIO_CAPTURE:
return PP_DEVICETYPE_DEV_AUDIOCAPTURE;
case MEDIA_DEVICE_VIDEO_CAPTURE:
return PP_DEVICETYPE_DEV_VIDEOCAPTURE;
default:
NOTREACHED();
return PP_DEVICETYPE_DEV_INVALID;
}
}
void PepperMediaDeviceManager::NotifyDeviceOpened(int request_id,
bool succeeded,
const std::string& label) {
OpenCallbackMap::iterator iter = open_callbacks_.find(request_id);
if (iter == open_callbacks_.end()) {
// The callback may have been unregistered.
return;
}
OpenDeviceCallback callback = iter->second;
open_callbacks_.erase(iter);
callback.Run(request_id, succeeded, label);
}
MediaStreamDispatcher* PepperMediaDeviceManager::GetMediaStreamDispatcher()
const {
DCHECK(render_frame());
MediaStreamDispatcher* const dispatcher =
static_cast<RenderFrameImpl*>(render_frame())->GetMediaStreamDispatcher();
DCHECK(dispatcher);
return dispatcher;
}
} // namespace content