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 kGetWebcamPTZError
[] = "Can't get web camera pan/tilt/zoom.";
28 const char kSetWebcamPTZError
[] = "Can't set web camera pan/tilt/zoom.";
29 const char kResetWebcamError
[] = "Can't reset web camera.";
33 namespace extensions
{
36 WebcamPrivateAPI
* WebcamPrivateAPI::Get(content::BrowserContext
* context
) {
37 return GetFactoryInstance()->Get(context
);
40 WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext
* context
)
41 : browser_context_(context
),
42 weak_ptr_factory_(this) {
43 webcam_resource_manager_
.reset(
44 new ApiResourceManager
<WebcamResource
>(context
));
47 WebcamPrivateAPI::~WebcamPrivateAPI() {
50 Webcam
* WebcamPrivateAPI::GetWebcam(const std::string
& extension_id
,
51 const std::string
& webcam_id
) {
52 WebcamResource
* webcam_resource
= FindWebcamResource(extension_id
, webcam_id
);
54 return webcam_resource
->GetWebcam();
56 std::string device_id
;
57 GetDeviceId(extension_id
, webcam_id
, &device_id
);
58 V4L2Webcam
* v4l2_webcam(new V4L2Webcam(device_id
));
59 if (!v4l2_webcam
->Open()) {
63 webcam_resource_manager_
->Add(
64 new WebcamResource(extension_id
, v4l2_webcam
, webcam_id
));
69 bool WebcamPrivateAPI::OpenSerialWebcam(
70 const std::string
& extension_id
,
71 const std::string
& device_path
,
72 const base::Callback
<void(const std::string
&, bool)>& callback
) {
73 const std::string
& webcam_id
= GetWebcamId(extension_id
, device_path
);
74 WebcamResource
* webcam_resource
= FindWebcamResource(extension_id
, webcam_id
);
78 ViscaWebcam
* visca_webcam(new ViscaWebcam(device_path
, extension_id
));
79 visca_webcam
->Open(base::Bind(
80 &WebcamPrivateAPI::OnOpenSerialWebcam
, weak_ptr_factory_
.GetWeakPtr(),
81 extension_id
, device_path
, make_scoped_refptr(visca_webcam
), callback
));
85 bool WebcamPrivateAPI::CloseWebcam(const std::string
& extension_id
,
86 const std::string
& webcam_id
) {
87 if (FindWebcamResource(extension_id
, webcam_id
)) {
88 RemoveWebcamResource(extension_id
, webcam_id
);
94 void WebcamPrivateAPI::OnOpenSerialWebcam(
95 const std::string
& extension_id
,
96 const std::string
& device_path
,
97 scoped_refptr
<Webcam
> webcam
,
98 const base::Callback
<void(const std::string
&, bool)>& callback
,
101 const std::string
& webcam_id
= GetWebcamId(extension_id
, device_path
);
102 webcam_resource_manager_
->Add(
103 new WebcamResource(extension_id
, webcam
.get(), webcam_id
));
104 callback
.Run(webcam_id
, true);
106 callback
.Run("", false);
110 bool WebcamPrivateAPI::GetDeviceId(const std::string
& extension_id
,
111 const std::string
& webcam_id
,
112 std::string
* device_id
) {
113 GURL security_origin
=
114 extensions::Extension::GetBaseURLFromExtensionId(extension_id
);
116 return content::GetMediaDeviceIDForHMAC(
117 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
118 browser_context_
->GetResourceContext()->GetMediaDeviceIDSalt(),
124 std::string
WebcamPrivateAPI::GetWebcamId(const std::string
& extension_id
,
125 const std::string
& device_id
) {
126 GURL security_origin
=
127 extensions::Extension::GetBaseURLFromExtensionId(extension_id
);
129 return content::GetHMACForMediaDeviceID(
130 browser_context_
->GetResourceContext()->GetMediaDeviceIDSalt(),
131 security_origin
, device_id
);
134 WebcamResource
* WebcamPrivateAPI::FindWebcamResource(
135 const std::string
& extension_id
,
136 const std::string
& webcam_id
) const {
137 DCHECK(webcam_resource_manager_
);
139 base::hash_set
<int>* connection_ids
=
140 webcam_resource_manager_
->GetResourceIds(extension_id
);
144 for (const auto& connection_id
: *connection_ids
) {
145 WebcamResource
* webcam_resource
=
146 webcam_resource_manager_
->Get(extension_id
, connection_id
);
147 if (webcam_resource
&& webcam_resource
->GetWebcamId() == webcam_id
)
148 return webcam_resource
;
154 bool WebcamPrivateAPI::RemoveWebcamResource(const std::string
& extension_id
,
155 const std::string
& webcam_id
) {
156 DCHECK(webcam_resource_manager_
);
158 base::hash_set
<int>* connection_ids
=
159 webcam_resource_manager_
->GetResourceIds(extension_id
);
163 for (const auto& connection_id
: *connection_ids
) {
164 WebcamResource
* webcam_resource
=
165 webcam_resource_manager_
->Get(extension_id
, connection_id
);
166 if (webcam_resource
&& webcam_resource
->GetWebcamId() == webcam_id
) {
167 webcam_resource_manager_
->Remove(extension_id
, connection_id
);
175 WebcamPrivateOpenSerialWebcamFunction::WebcamPrivateOpenSerialWebcamFunction() {
178 WebcamPrivateOpenSerialWebcamFunction::
179 ~WebcamPrivateOpenSerialWebcamFunction() {
182 bool WebcamPrivateOpenSerialWebcamFunction::RunAsync() {
183 scoped_ptr
<webcam_private::OpenSerialWebcam::Params
> params(
184 webcam_private::OpenSerialWebcam::Params::Create(*args_
));
185 EXTENSION_FUNCTION_VALIDATE(params
.get());
187 if (WebcamPrivateAPI::Get(browser_context())
189 extension_id(), params
->path
,
190 base::Bind(&WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam
,
194 SetError(kPathInUse
);
199 void WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam(
200 const std::string
& webcam_id
,
203 SetResult(new base::StringValue(webcam_id
));
206 SetError(kUnknownWebcam
);
211 WebcamPrivateCloseWebcamFunction::WebcamPrivateCloseWebcamFunction() {
214 WebcamPrivateCloseWebcamFunction::~WebcamPrivateCloseWebcamFunction() {
217 bool WebcamPrivateCloseWebcamFunction::RunAsync() {
218 scoped_ptr
<webcam_private::CloseWebcam::Params
> params(
219 webcam_private::CloseWebcam::Params::Create(*args_
));
220 EXTENSION_FUNCTION_VALIDATE(params
.get());
222 return WebcamPrivateAPI::Get(browser_context())
223 ->CloseWebcam(extension_id(), params
->webcam_id
);
226 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
229 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
232 bool WebcamPrivateSetFunction::RunAsync() {
233 scoped_ptr
<webcam_private::Set::Params
> params(
234 webcam_private::Set::Params::Create(*args_
));
235 EXTENSION_FUNCTION_VALIDATE(params
.get());
237 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
238 ->GetWebcam(extension_id(), params
->webcam_id
);
240 SetError(kUnknownWebcam
);
246 if (params
->config
.pan_speed
)
247 pan_speed
= *(params
->config
.pan_speed
);
249 if (params
->config
.tilt_speed
)
250 tilt_speed
= *(params
->config
.tilt_speed
);
252 if (params
->config
.pan
) {
254 *(params
->config
.pan
), pan_speed
,
255 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
258 if (params
->config
.pan_direction
) {
259 Webcam::PanDirection direction
= Webcam::PAN_STOP
;
260 switch (params
->config
.pan_direction
) {
261 case webcam_private::PAN_DIRECTION_NONE
:
262 case webcam_private::PAN_DIRECTION_STOP
:
263 direction
= Webcam::PAN_STOP
;
266 case webcam_private::PAN_DIRECTION_RIGHT
:
267 direction
= Webcam::PAN_RIGHT
;
270 case webcam_private::PAN_DIRECTION_LEFT
:
271 direction
= Webcam::PAN_LEFT
;
274 webcam
->SetPanDirection(
275 direction
, pan_speed
,
276 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
279 if (params
->config
.tilt
) {
281 *(params
->config
.tilt
), tilt_speed
,
282 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
285 if (params
->config
.tilt_direction
) {
286 Webcam::TiltDirection direction
= Webcam::TILT_STOP
;
287 switch (params
->config
.tilt_direction
) {
288 case webcam_private::TILT_DIRECTION_NONE
:
289 case webcam_private::TILT_DIRECTION_STOP
:
290 direction
= Webcam::TILT_STOP
;
293 case webcam_private::TILT_DIRECTION_UP
:
294 direction
= Webcam::TILT_UP
;
297 case webcam_private::TILT_DIRECTION_DOWN
:
298 direction
= Webcam::TILT_DOWN
;
301 webcam
->SetTiltDirection(
302 direction
, tilt_speed
,
303 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
306 if (params
->config
.zoom
) {
308 *(params
->config
.zoom
),
309 base::Bind(&WebcamPrivateSetFunction::OnSetWebcamParameters
, this));
315 void WebcamPrivateSetFunction::OnSetWebcamParameters(bool success
) {
317 SetError(kSetWebcamPTZError
);
320 WebcamPrivateGetFunction::WebcamPrivateGetFunction()
329 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
332 bool WebcamPrivateGetFunction::RunAsync() {
333 scoped_ptr
<webcam_private::Get::Params
> params(
334 webcam_private::Get::Params::Create(*args_
));
335 EXTENSION_FUNCTION_VALIDATE(params
.get());
337 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
338 ->GetWebcam(extension_id(), params
->webcam_id
);
340 SetError(kUnknownWebcam
);
344 webcam
->GetPan(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
346 webcam
->GetTilt(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
347 this, INQUIRY_TILT
));
348 webcam
->GetZoom(base::Bind(&WebcamPrivateGetFunction::OnGetWebcamParameters
,
349 this, INQUIRY_ZOOM
));
354 void WebcamPrivateGetFunction::OnGetWebcamParameters(InquiryType type
,
359 success_
= success_
&& success
;
362 SetError(kGetWebcamPTZError
);
379 if (get_pan_
&& get_tilt_
&& get_zoom_
) {
380 webcam_private::WebcamConfiguration result
;
381 result
.pan
.reset(new double(pan_
));
382 result
.tilt
.reset(new double(tilt_
));
383 result
.zoom
.reset(new double(zoom_
));
384 SetResult(result
.ToValue().release());
390 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
393 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
396 bool WebcamPrivateResetFunction::RunAsync() {
397 scoped_ptr
<webcam_private::Reset::Params
> params(
398 webcam_private::Reset::Params::Create(*args_
));
399 EXTENSION_FUNCTION_VALIDATE(params
.get());
401 Webcam
* webcam
= WebcamPrivateAPI::Get(browser_context())
402 ->GetWebcam(extension_id(), params
->webcam_id
);
404 SetError(kUnknownWebcam
);
408 webcam
->Reset(params
->config
.pan
, params
->config
.tilt
, params
->config
.zoom
,
409 base::Bind(&WebcamPrivateResetFunction::OnResetWebcam
, this));
414 void WebcamPrivateResetFunction::OnResetWebcam(bool success
) {
416 SetError(kResetWebcamError
);
419 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>>
420 g_factory
= LAZY_INSTANCE_INITIALIZER
;
423 BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>*
424 WebcamPrivateAPI::GetFactoryInstance() {
425 return g_factory
.Pointer();
429 void BrowserContextKeyedAPIFactory
<WebcamPrivateAPI
>
430 ::DeclareFactoryDependencies() {
431 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
432 DependsOn(ProcessManagerFactory::GetInstance());
435 } // namespace extensions