Add more checks to investigate SupervisedUserPrefStore crash at startup.
[chromium-blink-merge.git] / extensions / browser / api / webcam_private / webcam_private_api_chromeos.cc
blob765c778d048e6f1772916d0b1cb101471b105499
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/webcam_private/webcam_private_api.h"
7 #include <fcntl.h>
8 #include <linux/uvcvideo.h>
9 #include <linux/videodev2.h>
10 #include <stdio.h>
11 #include <sys/ioctl.h>
12 #include <unistd.h>
14 #include "base/files/scoped_file.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/media_device_id.h"
18 #include "content/public/browser/resource_context.h"
19 #include "content/public/common/media_stream_request.h"
20 #include "extensions/common/api/webcam_private.h"
22 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
23 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
24 #define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE+34)
26 // GUID of the Extension Unit for Logitech CC3300e motor control:
27 // {212de5ff-3080-2c4e-82d9-f587d00540bd}
28 #define UVC_GUID_LOGITECH_CC3000E_MOTORS \
29 {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \
30 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd}
32 #define LOGITECH_MOTORCONTROL_PANTILT_CMD 2
34 namespace webcam_private = extensions::core_api::webcam_private;
36 namespace content {
37 class BrowserContext;
38 } // namespace content
40 namespace {
41 const int kLogitechMenuIndexGoHome = 2;
43 const uvc_menu_info kLogitechCmdMenu[] = {
44 {1, "Set Preset"}, {2, "Get Preset"}, {3, "Go Home"}
47 const uvc_xu_control_mapping kLogitechCmdMapping = {
48 V4L2_CID_PANTILT_CMD,
49 "Pan/Tilt Go",
50 UVC_GUID_LOGITECH_CC3000E_MOTORS,
51 LOGITECH_MOTORCONTROL_PANTILT_CMD,
54 V4L2_CTRL_TYPE_MENU,
55 UVC_CTRL_DATA_TYPE_ENUM,
56 const_cast<uvc_menu_info*>(&kLogitechCmdMenu[0]),
57 arraysize(kLogitechCmdMenu),
60 base::ScopedFD OpenWebcam(const std::string& extension_id,
61 content::BrowserContext* browser_context,
62 const std::string& webcam_id) {
63 GURL security_origin =
64 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
66 std::string device_id;
67 bool success = content::GetMediaDeviceIDForHMAC(
68 content::MEDIA_DEVICE_VIDEO_CAPTURE,
69 browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
70 security_origin,
71 webcam_id,
72 &device_id);
74 if (!success)
75 return base::ScopedFD();
77 return base::ScopedFD(HANDLE_EINTR(open(device_id.c_str(), 0)));
80 void SetWebcamParameter(int fd, uint32_t control_id, int value) {
81 struct v4l2_control v4l2_ctrl = {control_id, value};
82 HANDLE_EINTR(ioctl(fd, VIDIOC_S_CTRL, &v4l2_ctrl));
85 bool GetWebcamParameter(int fd, uint32_t control_id, int* value) {
86 struct v4l2_control v4l2_ctrl = {control_id};
88 if (HANDLE_EINTR(ioctl(fd, VIDIOC_G_CTRL, &v4l2_ctrl)))
89 return false;
91 *value = v4l2_ctrl.value;
92 return true;
95 bool EnsureLogitechCommandsMapped(int fd) {
96 int res = ioctl(fd, UVCIOC_CTRL_MAP, &kLogitechCmdMapping);
97 // If mapping is successful or it's already mapped, this is a Logitech camera.
98 return res >= 0 || errno == EEXIST;
101 const char kUnknownWebcam[] = "Unknown webcam id";
102 } // namespace
104 namespace extensions {
106 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
109 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
112 bool WebcamPrivateSetFunction::RunSync() {
113 // Get parameters
114 scoped_ptr<webcam_private::Set::Params> params(
115 webcam_private::Set::Params::Create(*args_));
116 EXTENSION_FUNCTION_VALIDATE(params.get());
118 base::ScopedFD fd =
119 OpenWebcam(extension_id(), browser_context(), params->webcam_id);
120 if (!fd.is_valid()) {
121 SetError(kUnknownWebcam);
122 return false;
125 if (params->config.pan) {
126 SetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE,
127 *(params->config.pan));
130 if (params->config.pan_direction) {
131 int direction = 0;
132 switch (params->config.pan_direction) {
133 case webcam_private::PAN_DIRECTION_NONE:
134 case webcam_private::PAN_DIRECTION_STOP:
135 direction = 0;
136 break;
138 case webcam_private::PAN_DIRECTION_RIGHT:
139 direction = 1;
140 break;
142 case webcam_private::PAN_DIRECTION_LEFT:
143 direction = -1;
144 break;
146 SetWebcamParameter(fd.get(), V4L2_CID_PAN_SPEED, direction);
149 if (params->config.tilt) {
150 SetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE,
151 *(params->config.tilt));
154 if (params->config.tilt_direction) {
155 int direction = 0;
156 switch (params->config.tilt_direction) {
157 case webcam_private::TILT_DIRECTION_NONE:
158 case webcam_private::TILT_DIRECTION_STOP:
159 direction = 0;
160 break;
162 case webcam_private::TILT_DIRECTION_UP:
163 direction = 1;
164 break;
166 case webcam_private::TILT_DIRECTION_DOWN:
167 direction = -1;
168 break;
170 SetWebcamParameter(fd.get(), V4L2_CID_TILT_SPEED, direction);
173 if (params->config.zoom) {
174 SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE,
175 *(params->config.zoom));
179 return true;
182 WebcamPrivateGetFunction::WebcamPrivateGetFunction() {
185 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
188 bool WebcamPrivateGetFunction::RunSync() {
189 // Get parameters
190 scoped_ptr<webcam_private::Get::Params> params(
191 webcam_private::Get::Params::Create(*args_));
192 EXTENSION_FUNCTION_VALIDATE(params.get());
194 base::ScopedFD fd =
195 OpenWebcam(extension_id(), browser_context(), params->webcam_id);
196 if (!fd.is_valid()) {
197 SetError(kUnknownWebcam);
198 return false;
201 webcam_private::WebcamConfiguration result;
203 int pan;
204 if (GetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, &pan))
205 result.pan.reset(new double(pan));
207 int tilt;
208 if (GetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, &tilt))
209 result.tilt.reset(new double(tilt));
211 int zoom;
212 if (GetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, &zoom))
213 result.zoom.reset(new double(zoom));
215 SetResult(result.ToValue().release());
217 return true;
220 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
223 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
226 bool WebcamPrivateResetFunction::RunSync() {
227 // Get parameters
228 scoped_ptr<webcam_private::Reset::Params> params(
229 webcam_private::Reset::Params::Create(*args_));
230 EXTENSION_FUNCTION_VALIDATE(params.get());
232 base::ScopedFD fd =
233 OpenWebcam(extension_id(), browser_context(), params->webcam_id);
234 if (!fd.is_valid()) {
235 SetError(kUnknownWebcam);
236 return false;
239 if (params->config.pan || params->config.tilt) {
240 if (EnsureLogitechCommandsMapped(fd.get())) {
241 SetWebcamParameter(fd.get(), V4L2_CID_PANTILT_CMD,
242 kLogitechMenuIndexGoHome);
246 if (params->config.pan) {
247 struct v4l2_control v4l2_ctrl = {V4L2_CID_PAN_RESET};
248 HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
251 if (params->config.tilt) {
252 struct v4l2_control v4l2_ctrl = {V4L2_CID_TILT_RESET};
253 HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
256 if (params->config.zoom) {
257 const int kDefaultZoom = 100;
258 SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, kDefaultZoom);
261 return true;
264 } // namespace extensions