| Index: extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
|
| diff --git a/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc b/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
|
| index 765c778d048e6f1772916d0b1cb101471b105499..4b0f0d375aa2100ccc56191822a2e42a44ddaaa5 100644
|
| --- a/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
|
| +++ b/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
|
| @@ -4,33 +4,17 @@
|
|
|
| #include "extensions/browser/api/webcam_private/webcam_private_api.h"
|
|
|
| -#include <fcntl.h>
|
| -#include <linux/uvcvideo.h>
|
| -#include <linux/videodev2.h>
|
| -#include <stdio.h>
|
| -#include <sys/ioctl.h>
|
| -#include <unistd.h>
|
| -
|
| -#include "base/files/scoped_file.h"
|
| -#include "base/posix/eintr_wrapper.h"
|
| +#include "base/lazy_instance.h"
|
| #include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/media_device_id.h"
|
| #include "content/public/browser/resource_context.h"
|
| #include "content/public/common/media_stream_request.h"
|
| +#include "extensions/browser/api/webcam_private/v4l2_webcam.h"
|
| +#include "extensions/browser/api/webcam_private/webcam.h"
|
| +#include "extensions/browser/process_manager.h"
|
| +#include "extensions/browser/process_manager_factory.h"
|
| #include "extensions/common/api/webcam_private.h"
|
|
|
| -#define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
|
| -#define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
|
| -#define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE+34)
|
| -
|
| -// GUID of the Extension Unit for Logitech CC3300e motor control:
|
| -// {212de5ff-3080-2c4e-82d9-f587d00540bd}
|
| -#define UVC_GUID_LOGITECH_CC3000E_MOTORS \
|
| - {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \
|
| - 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd}
|
| -
|
| -#define LOGITECH_MOTORCONTROL_PANTILT_CMD 2
|
| -
|
| namespace webcam_private = extensions::core_api::webcam_private;
|
|
|
| namespace content {
|
| @@ -38,70 +22,75 @@ class BrowserContext;
|
| } // namespace content
|
|
|
| namespace {
|
| -const int kLogitechMenuIndexGoHome = 2;
|
| -
|
| -const uvc_menu_info kLogitechCmdMenu[] = {
|
| - {1, "Set Preset"}, {2, "Get Preset"}, {3, "Go Home"}
|
| -};
|
| -
|
| -const uvc_xu_control_mapping kLogitechCmdMapping = {
|
| - V4L2_CID_PANTILT_CMD,
|
| - "Pan/Tilt Go",
|
| - UVC_GUID_LOGITECH_CC3000E_MOTORS,
|
| - LOGITECH_MOTORCONTROL_PANTILT_CMD,
|
| - 8,
|
| - 0,
|
| - V4L2_CTRL_TYPE_MENU,
|
| - UVC_CTRL_DATA_TYPE_ENUM,
|
| - const_cast<uvc_menu_info*>(&kLogitechCmdMenu[0]),
|
| - arraysize(kLogitechCmdMenu),
|
| -};
|
| -
|
| -base::ScopedFD OpenWebcam(const std::string& extension_id,
|
| - content::BrowserContext* browser_context,
|
| - const std::string& webcam_id) {
|
| - GURL security_origin =
|
| - extensions::Extension::GetBaseURLFromExtensionId(extension_id);
|
| -
|
| - std::string device_id;
|
| - bool success = content::GetMediaDeviceIDForHMAC(
|
| - content::MEDIA_DEVICE_VIDEO_CAPTURE,
|
| - browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
|
| - security_origin,
|
| - webcam_id,
|
| - &device_id);
|
| +const char kUnknownWebcam[] = "Unknown webcam id";
|
| +} // namespace
|
|
|
| - if (!success)
|
| - return base::ScopedFD();
|
| +namespace extensions {
|
|
|
| - return base::ScopedFD(HANDLE_EINTR(open(device_id.c_str(), 0)));
|
| +// static
|
| +WebcamPrivateAPI* WebcamPrivateAPI::Get(content::BrowserContext* context) {
|
| + return GetFactoryInstance()->Get(context);
|
| }
|
|
|
| -void SetWebcamParameter(int fd, uint32_t control_id, int value) {
|
| - struct v4l2_control v4l2_ctrl = {control_id, value};
|
| - HANDLE_EINTR(ioctl(fd, VIDIOC_S_CTRL, &v4l2_ctrl));
|
| +WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext* context)
|
| + : browser_context_(context),
|
| + process_manager_observer_(this),
|
| + weak_ptr_factory_(this) {
|
| + process_manager_observer_.Add(ProcessManager::Get(browser_context_));
|
| }
|
|
|
| -bool GetWebcamParameter(int fd, uint32_t control_id, int* value) {
|
| - struct v4l2_control v4l2_ctrl = {control_id};
|
| +WebcamPrivateAPI::~WebcamPrivateAPI() {}
|
|
|
| - if (HANDLE_EINTR(ioctl(fd, VIDIOC_G_CTRL, &v4l2_ctrl)))
|
| - return false;
|
| +Webcam* WebcamPrivateAPI::GetWebcam(const std::string& extension_id,
|
| + const std::string& webcam_id) {
|
| + std::string device_id;
|
| + if (!GetDeviceId(extension_id, webcam_id, &device_id)) {
|
| + return nullptr;
|
| + }
|
|
|
| - *value = v4l2_ctrl.value;
|
| - return true;
|
| -}
|
| + auto ix = webcams_.find(device_id);
|
| + if (ix != webcams_.end()) {
|
| + ix->second->AddExtensionRef(extension_id);
|
| + return ix->second.get();
|
| + }
|
| +
|
| + scoped_ptr<V4L2Webcam> v4l2_webcam(new V4L2Webcam(device_id));
|
| + if (!v4l2_webcam->Open()) {
|
| + return nullptr;
|
| + }
|
|
|
| -bool EnsureLogitechCommandsMapped(int fd) {
|
| - int res = ioctl(fd, UVCIOC_CTRL_MAP, &kLogitechCmdMapping);
|
| - // If mapping is successful or it's already mapped, this is a Logitech camera.
|
| - return res >= 0 || errno == EEXIST;
|
| + linked_ptr<Webcam> webcam(v4l2_webcam.release());
|
| +
|
| + webcams_[device_id] = webcam;
|
| + webcam->AddExtensionRef(extension_id);
|
| +
|
| + return webcam.get();
|
| }
|
|
|
| -const char kUnknownWebcam[] = "Unknown webcam id";
|
| -} // namespace
|
| +bool WebcamPrivateAPI::GetDeviceId(const std::string& extension_id,
|
| + const std::string& webcam_id,
|
| + std::string* device_id) {
|
| + GURL security_origin =
|
| + extensions::Extension::GetBaseURLFromExtensionId(extension_id);
|
|
|
| -namespace extensions {
|
| + return content::GetMediaDeviceIDForHMAC(
|
| + content::MEDIA_DEVICE_VIDEO_CAPTURE,
|
| + browser_context_->GetResourceContext()->GetMediaDeviceIDSalt(),
|
| + security_origin,
|
| + webcam_id,
|
| + device_id);
|
| +}
|
| +
|
| +void WebcamPrivateAPI::OnBackgroundHostClose(const std::string& extension_id) {
|
| + for (auto webcam = webcams_.begin();
|
| + webcam != webcams_.end(); /* No increment */ ) {
|
| + auto next = std::next(webcam);
|
| + webcam->second->RemoveExtensionRef(extension_id);
|
| + if (webcam->second->ShouldDelete())
|
| + webcams_.erase(webcam);
|
| + webcam = next;
|
| + }
|
| +}
|
|
|
| WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
|
| }
|
| @@ -115,64 +104,61 @@ bool WebcamPrivateSetFunction::RunSync() {
|
| webcam_private::Set::Params::Create(*args_));
|
| EXTENSION_FUNCTION_VALIDATE(params.get());
|
|
|
| - base::ScopedFD fd =
|
| - OpenWebcam(extension_id(), browser_context(), params->webcam_id);
|
| - if (!fd.is_valid()) {
|
| + Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
|
| + GetWebcam(extension_id(), params->webcam_id);
|
| + if (!webcam) {
|
| SetError(kUnknownWebcam);
|
| return false;
|
| }
|
|
|
| if (params->config.pan) {
|
| - SetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE,
|
| - *(params->config.pan));
|
| + webcam->SetPan(*(params->config.pan));
|
| }
|
|
|
| if (params->config.pan_direction) {
|
| - int direction = 0;
|
| + Webcam::PanDirection direction = Webcam::PAN_STOP;
|
| switch (params->config.pan_direction) {
|
| case webcam_private::PAN_DIRECTION_NONE:
|
| case webcam_private::PAN_DIRECTION_STOP:
|
| - direction = 0;
|
| + direction = Webcam::PAN_STOP;
|
| break;
|
|
|
| case webcam_private::PAN_DIRECTION_RIGHT:
|
| - direction = 1;
|
| + direction = Webcam::PAN_RIGHT;
|
| break;
|
|
|
| case webcam_private::PAN_DIRECTION_LEFT:
|
| - direction = -1;
|
| + direction = Webcam::PAN_LEFT;
|
| break;
|
| }
|
| - SetWebcamParameter(fd.get(), V4L2_CID_PAN_SPEED, direction);
|
| + webcam->SetPanDirection(direction);
|
| }
|
|
|
| if (params->config.tilt) {
|
| - SetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE,
|
| - *(params->config.tilt));
|
| + webcam->SetTilt(*(params->config.tilt));
|
| }
|
|
|
| if (params->config.tilt_direction) {
|
| - int direction = 0;
|
| + Webcam::TiltDirection direction = Webcam::TILT_STOP;
|
| switch (params->config.tilt_direction) {
|
| case webcam_private::TILT_DIRECTION_NONE:
|
| case webcam_private::TILT_DIRECTION_STOP:
|
| - direction = 0;
|
| + direction = Webcam::TILT_STOP;
|
| break;
|
|
|
| case webcam_private::TILT_DIRECTION_UP:
|
| - direction = 1;
|
| + direction = Webcam::TILT_UP;
|
| break;
|
|
|
| case webcam_private::TILT_DIRECTION_DOWN:
|
| - direction = -1;
|
| + direction = Webcam::TILT_DOWN;
|
| break;
|
| }
|
| - SetWebcamParameter(fd.get(), V4L2_CID_TILT_SPEED, direction);
|
| + webcam->SetTiltDirection(direction);
|
| }
|
|
|
| if (params->config.zoom) {
|
| - SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE,
|
| - *(params->config.zoom));
|
| + webcam->SetZoom(*(params->config.zoom));
|
| }
|
|
|
|
|
| @@ -191,9 +177,9 @@ bool WebcamPrivateGetFunction::RunSync() {
|
| webcam_private::Get::Params::Create(*args_));
|
| EXTENSION_FUNCTION_VALIDATE(params.get());
|
|
|
| - base::ScopedFD fd =
|
| - OpenWebcam(extension_id(), browser_context(), params->webcam_id);
|
| - if (!fd.is_valid()) {
|
| + Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
|
| + GetWebcam(extension_id(), params->webcam_id);
|
| + if (!webcam) {
|
| SetError(kUnknownWebcam);
|
| return false;
|
| }
|
| @@ -201,15 +187,15 @@ bool WebcamPrivateGetFunction::RunSync() {
|
| webcam_private::WebcamConfiguration result;
|
|
|
| int pan;
|
| - if (GetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, &pan))
|
| + if (webcam->GetPan(&pan))
|
| result.pan.reset(new double(pan));
|
|
|
| int tilt;
|
| - if (GetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, &tilt))
|
| + if (webcam->GetTilt(&tilt))
|
| result.tilt.reset(new double(tilt));
|
|
|
| int zoom;
|
| - if (GetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, &zoom))
|
| + if (webcam->GetZoom(&zoom))
|
| result.zoom.reset(new double(zoom));
|
|
|
| SetResult(result.ToValue().release());
|
| @@ -229,36 +215,32 @@ bool WebcamPrivateResetFunction::RunSync() {
|
| webcam_private::Reset::Params::Create(*args_));
|
| EXTENSION_FUNCTION_VALIDATE(params.get());
|
|
|
| - base::ScopedFD fd =
|
| - OpenWebcam(extension_id(), browser_context(), params->webcam_id);
|
| - if (!fd.is_valid()) {
|
| + Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
|
| + GetWebcam(extension_id(), params->webcam_id);
|
| + if (!webcam) {
|
| SetError(kUnknownWebcam);
|
| return false;
|
| }
|
|
|
| - if (params->config.pan || params->config.tilt) {
|
| - if (EnsureLogitechCommandsMapped(fd.get())) {
|
| - SetWebcamParameter(fd.get(), V4L2_CID_PANTILT_CMD,
|
| - kLogitechMenuIndexGoHome);
|
| - }
|
| - }
|
| + webcam->Reset(params->config.pan, params->config.tilt, params->config.zoom);
|
|
|
| - if (params->config.pan) {
|
| - struct v4l2_control v4l2_ctrl = {V4L2_CID_PAN_RESET};
|
| - HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
|
| - }
|
| + return true;
|
| +}
|
|
|
| - if (params->config.tilt) {
|
| - struct v4l2_control v4l2_ctrl = {V4L2_CID_TILT_RESET};
|
| - HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
|
| - }
|
| +static base::LazyInstance<BrowserContextKeyedAPIFactory<WebcamPrivateAPI>>
|
| + g_factory = LAZY_INSTANCE_INITIALIZER;
|
|
|
| - if (params->config.zoom) {
|
| - const int kDefaultZoom = 100;
|
| - SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, kDefaultZoom);
|
| - }
|
| +// static
|
| +BrowserContextKeyedAPIFactory<WebcamPrivateAPI>*
|
| +WebcamPrivateAPI::GetFactoryInstance() {
|
| + return g_factory.Pointer();
|
| +}
|
|
|
| - return true;
|
| +template <>
|
| +void BrowserContextKeyedAPIFactory<WebcamPrivateAPI>
|
| + ::DeclareFactoryDependencies() {
|
| + DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
|
| + DependsOn(ProcessManagerFactory::GetInstance());
|
| }
|
|
|
| } // namespace extensions
|
|
|