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 "base/lazy_instance.h"
8 #include "content/public/browser/browser_context.h"
9 #include "content/public/browser/media_device_id.h"
10 #include "content/public/browser/resource_context.h"
11 #include "extensions/browser/api/webcam_private/v4l2_webcam.h"
12 #include "extensions/browser/api/webcam_private/visca_webcam.h"
13 #include "extensions/browser/process_manager.h"
14 #include "extensions/browser/process_manager_factory.h"
15 #include "extensions/common/api/webcam_private.h"
17 namespace webcam_private
= extensions::api::webcam_private
;
21 } // namespace content
25 const char kPathInUse
[] = "Path in use";
26 const char kUnknownWebcam
[] = "Unknown webcam id";
27 const char kOpenSerialWebcamError
[] = "Can't open serial webcam.";
28 const char kGetWebcamPTZError
[] = "Can't get web camera pan/tilt/zoom.";
29 const char kSetWebcamPTZError
[] = "Can't set web camera pan/tilt/zoom.";
30 const char kResetWebcamError
[] = "Can't reset web camera.";
34 namespace extensions
{
37 WebcamPrivateAPI
* WebcamPrivateAPI::Get(content::BrowserContext
* context
) {
38 return GetFactoryInstance()->Get(context
);
41 WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext
* context
)
42 : browser_context_(context
),
43 weak_ptr_factory_(this) {
44 webcam_resource_manager_
.reset(
45 new ApiResourceManager
<WebcamResource
>(context
));
48 WebcamPrivateAPI::~WebcamPrivateAPI() {
51 Webcam
* WebcamPrivateAPI::GetWebcam(const std::string
& extension_id
,
52 const std::string
& webcam_id
) {
53 WebcamResource
* webcam_resource
= FindWebcamResource(extension_id
, webcam_id
);
55 return webcam_resource
->GetWebcam();
57 std::string device_id
;
58 GetDeviceId(extension_id
, webcam_id
, &device_id
);
59 V4L2Webcam
* v4l2_webcam(new V4L2Webcam(device_id
));
60 if (!v4l2_webcam
->Open()) {
64 webcam_resource_manager_
->Add(
65 new WebcamResource(extension_id
, v4l2_webcam
, webcam_id
));
70 bool WebcamPrivateAPI::OpenSerialWebcam(
71 const std::string
& extension_id
,
72 const std::string
& device_path
,
73 const base::Callback
<void(const std::string
&, bool)>& callback
) {
74 const std::string
& webcam_id
= GetWebcamId(extension_id
, device_path
);
75 WebcamResource
* webcam_resource
= FindWebcamResource(extension_id
, webcam_id
);
79 ViscaWebcam
* visca_webcam(new ViscaWebcam(device_path
, extension_id
));
80 visca_webcam
->Open(base::Bind(
81 &WebcamPrivateAPI::OnOpenSerialWebcam
, weak_ptr_factory_
.GetWeakPtr(),
82 extension_id
, device_path
, make_scoped_refptr(visca_webcam
), callback
));
86 bool WebcamPrivateAPI::CloseWebcam(const std::string
& extension_id
,
87 const std::string
& webcam_id
) {
88 if (FindWebcamResource(extension_id
, webcam_id
)) {
89 RemoveWebcamResource(extension_id
, webcam_id
);
95 void WebcamPrivateAPI::OnOpenSerialWebcam(
96 const std::string
& extension_id
,
97 const std::string
& device_path
,
98 scoped_refptr
<Webcam
> webcam
,
99 const base::Callback
<void(const std::string
&, bool)>& callback
,
102 const std::string
& webcam_id
= GetWebcamId(extension_id
, device_path
);
103 webcam_resource_manager_
->Add(
104 new WebcamResource(extension_id
, webcam
.get(), webcam_id
));
105 callback
.Run(webcam_id
, true);
107 callback
.Run("", false);
111 bool WebcamPrivateAPI::GetDeviceId(const std::string
& extension_id
,
112 const std::string
& webcam_id
,
113 std::string
* device_id
) {
114 GURL security_origin
=
115 extensions::Extension::GetBaseURLFromExtensionId(extension_id
);
117 return content::GetMediaDeviceIDForHMAC(
118 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
119 browser_context_
->GetResourceContext()->GetMediaDeviceIDSalt(),
125 std::string
WebcamPrivateAPI::GetWebcamId(const std::string
& extension_id
,
126 const std::string
& device_id
) {
127 GURL security_origin
=
128 extensions::Extension::GetBaseURLFromExtensionId(extension_id
);
130 return content::GetHMACForMediaDeviceID(
131 browser_context_
->GetResourceContext()->GetMediaDeviceIDSalt(),
132 security_origin
, device_id
);
135 WebcamResource
* WebcamPrivateAPI::FindWebcamResource(
136 const std::string
& extension_id
,
137 const std::string
& webcam_id
) const {
138 DCHECK(webcam_resource_manager_
);
140 base::hash_set
<int>* connection_ids
=
141 webcam_resource_manager_
->GetResourceIds(extension_id
);
145 for (const auto& connection_id
: *connection_ids
) {
146 WebcamResource
* webcam_resource
=
147 webcam_resource_manager_
->Get(extension_id
, connection_id
);
148 if (webcam_resource
&& webcam_resource
->GetWebcamId() == webcam_id
)
149 return webcam_resource
;
155 bool WebcamPrivateAPI::RemoveWebcamResource(const std::string
& extension_id
,
156 const std::string
& webcam_id
) {
157 DCHECK(webcam_resource_manager_
);
159 base::hash_set
<int>* connection_ids
=
160 webcam_resource_manager_
->GetResourceIds(extension_id
);
164 for (const auto& connection_id
: *connection_ids
) {
165 WebcamResource
* webcam_resource
=
166 webcam_resource_manager_
->Get(extension_id
, connection_id
);
167 if (webcam_resource
&& webcam_resource
->GetWebcamId() == webcam_id
) {
168 webcam_resource_manager_
->Remove(extension_id
, connection_id
);
176 WebcamPrivateOpenSerialWebcamFunction::WebcamPrivateOpenSerialWebcamFunction() {
179 WebcamPrivateOpenSerialWebcamFunction::
180 ~WebcamPrivateOpenSerialWebcamFunction() {
183 bool WebcamPrivateOpenSerialWebcamFunction::RunAsync() {
184 scoped_ptr
<webcam_private::OpenSerialWebcam::Params
> params(
185 webcam_private::OpenSerialWebcam::Params::Create(*args_
));
186 EXTENSION_FUNCTION_VALIDATE(params
.get());
188 if (WebcamPrivateAPI::Get(browser_context())
190 extension_id(), params
->path
,
191 base::Bind(&WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam
,
195 SetError(kPathInUse
);
200 void WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam(
201 const std::string
& webcam_id
,
204 SetResult(new base::StringValue(webcam_id
));
207 SetError(kOpenSerialWebcamError
);
212 WebcamPrivateCloseWebcamFunction::WebcamPrivateCloseWebcamFunction() {
215 WebcamPrivateCloseWebcamFunction::~WebcamPrivateCloseWebcamFunction() {
218 bool WebcamPrivateCloseWebcamFunction::RunAsync() {
219 scoped_ptr
<webcam_private::CloseWebcam::Params
> params(
220 webcam_private::CloseWebcam::Params::Create(*args_
));
221 EXTENSION_FUNCTION_VALIDATE(params
.get());
223 return WebcamPrivateAPI::Get(browser_context())
224 ->CloseWebcam(extension_id(), params
->webcam_id
);
227 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
230 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
233 bool WebcamPrivateSetFunction::RunAsync() {
234 scoped_ptr
<webcam_private::Set::Params
> params(
235 webcam_private::Set::Params::Create(*args_
));
236 EXTENSION_FUNCTION_VALIDATE(params
.get());
238 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
239 ->GetWebcam(extension_id(), params
->webcam_id
);
241 SetError(kUnknownWebcam
);
247 if (params
->config
.pan_speed
)
248 pan_speed
= *(params
->config
.pan_speed
);
250 if (params
->config
.tilt_speed
)
251 tilt_speed
= *(params
->config
.tilt_speed
);
253 if (params
->config
.pan
) {
255 *(params
->config
.pan
), pan_speed
,
256 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
259 if (params
->config
.pan_direction
) {
260 Webcam::PanDirection direction
= Webcam::PAN_STOP
;
261 switch (params
->config
.pan_direction
) {
262 case webcam_private::PAN_DIRECTION_NONE
:
263 case webcam_private::PAN_DIRECTION_STOP
:
264 direction
= Webcam::PAN_STOP
;
267 case webcam_private::PAN_DIRECTION_RIGHT
:
268 direction
= Webcam::PAN_RIGHT
;
271 case webcam_private::PAN_DIRECTION_LEFT
:
272 direction
= Webcam::PAN_LEFT
;
275 webcam
->SetPanDirection(
276 direction
, pan_speed
,
277 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
280 if (params
->config
.tilt
) {
282 *(params
->config
.tilt
), tilt_speed
,
283 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
286 if (params
->config
.tilt_direction
) {
287 Webcam::TiltDirection direction
= Webcam::TILT_STOP
;
288 switch (params
->config
.tilt_direction
) {
289 case webcam_private::TILT_DIRECTION_NONE
:
290 case webcam_private::TILT_DIRECTION_STOP
:
291 direction
= Webcam::TILT_STOP
;
294 case webcam_private::TILT_DIRECTION_UP
:
295 direction
= Webcam::TILT_UP
;
298 case webcam_private::TILT_DIRECTION_DOWN
:
299 direction
= Webcam::TILT_DOWN
;
302 webcam
->SetTiltDirection(
303 direction
, tilt_speed
,
304 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
307 if (params
->config
.zoom
) {
309 *(params
->config
.zoom
),
310 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
316 void WebcamPrivateSetFunction::OnSetWebcamParameters(bool success
) {
318 SetError(kSetWebcamPTZError
);
321 WebcamPrivateGetFunction::WebcamPrivateGetFunction()
330 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
333 bool WebcamPrivateGetFunction::RunAsync() {
334 scoped_ptr
<webcam_private::Get::Params
> params(
335 webcam_private::Get::Params::Create(*args_
));
336 EXTENSION_FUNCTION_VALIDATE(params
.get());
338 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
339 ->GetWebcam(extension_id(), params
->webcam_id
);
341 SetError(kUnknownWebcam
);
345 webcam
->GetPan(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
347 webcam
->GetTilt(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
348 this, INQUIRY_TILT
));
349 webcam
->GetZoom(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
350 this, INQUIRY_ZOOM
));
355 void WebcamPrivateGetFunction::OnGetWebcamParameters(InquiryType type
,
360 success_
= success_
&& success
;
363 SetError(kGetWebcamPTZError
);
380 if (get_pan_
&& get_tilt_
&& get_zoom_
) {
381 webcam_private::WebcamConfiguration result
;
382 result
.pan
.reset(new double(pan_
));
383 result
.tilt
.reset(new double(tilt_
));
384 result
.zoom
.reset(new double(zoom_
));
385 SetResult(result
.ToValue().release());
391 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
394 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
397 bool WebcamPrivateResetFunction::RunAsync() {
398 scoped_ptr
<webcam_private::Reset::Params
> params(
399 webcam_private::Reset::Params::Create(*args_
));
400 EXTENSION_FUNCTION_VALIDATE(params
.get());
402 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
403 ->GetWebcam(extension_id(), params
->webcam_id
);
405 SetError(kUnknownWebcam
);
409 webcam
->Reset(params
->config
.pan
, params
->config
.tilt
, params
->config
.zoom
,
410 base::Bind(&WebcamPrivateResetFunction::OnResetWebcam
, this));
415 void WebcamPrivateResetFunction::OnResetWebcam(bool success
) {
417 SetError(kResetWebcamError
);
420 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>>
421 g_factory
= LAZY_INSTANCE_INITIALIZER
;
424 BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>*
425 WebcamPrivateAPI::GetFactoryInstance() {
426 return g_factory
.Pointer();
430 void BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>
431 ::DeclareFactoryDependencies() {
432 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
433 DependsOn(ProcessManagerFactory::GetInstance());
436 } // namespace extensions