| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "extensions/browser/api/webcam_private/webcam_private_api.h" |
| |
| #include <memory> |
| |
| #include "base/functional/bind.h" |
| #include "base/lazy_instance.h" |
| #include "components/media_device_salt/media_device_salt_service.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/media_device_id.h" |
| #include "content/public/browser/resource_context.h" |
| #include "extensions/browser/api/serial/serial_port_manager.h" |
| #include "extensions/browser/api/webcam_private/ip_webcam.h" |
| #include "extensions/browser/api/webcam_private/v4l2_webcam.h" |
| #include "extensions/browser/api/webcam_private/visca_webcam.h" |
| #include "extensions/browser/extensions_browser_client.h" |
| #include "extensions/browser/process_manager.h" |
| #include "extensions/browser/process_manager_factory.h" |
| #include "extensions/common/extension_id.h" |
| #include "mojo/public/cpp/bindings/pending_remote.h" |
| #include "url/origin.h" |
| |
| namespace webcam_private = extensions::api::webcam_private; |
| |
| namespace content { |
| class BrowserContext; |
| } // namespace content |
| |
| namespace { |
| |
| const char kPathInUse[] = "Path in use"; |
| const char kUnknownWebcam[] = "Unknown webcam id"; |
| const char kOpenSerialWebcamError[] = "Can't open serial webcam."; |
| const char kGetWebcamPTZError[] = "Can't get web camera pan/tilt/zoom."; |
| const char kSetWebcamPTZError[] = "Can't set web camera pan/tilt/zoom."; |
| const char kResetWebcamError[] = "Can't reset web camera."; |
| const char kSetHomeWebcamError[] = "Can't set home position"; |
| const char kRestorePresetWebcamError[] = "Can't restore preset."; |
| const char kSetPresetWebcamError[] = "Can't set preset."; |
| |
| } // namespace |
| |
| namespace extensions { |
| |
| // static |
| WebcamPrivateAPI* WebcamPrivateAPI::Get(content::BrowserContext* context) { |
| return GetFactoryInstance()->Get(context); |
| } |
| |
| WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext* context) |
| : browser_context_(context) { |
| webcam_resource_manager_ = |
| std::make_unique<ApiResourceManager<WebcamResource>>(context); |
| } |
| |
| WebcamPrivateAPI::~WebcamPrivateAPI() { |
| } |
| |
| void WebcamPrivateAPI::OnGotDeviceIdOnUIThread( |
| const ExtensionId& extension_id, |
| const std::string& webcam_id, |
| base::OnceCallback<void(Webcam*)> callback, |
| const std::optional<std::string>& device_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (!device_id) { |
| std::move(callback).Run(nullptr); |
| return; |
| } |
| |
| Webcam* webcam = nullptr; |
| |
| if (device_id->compare(0, 8, "192.168.") == 0) { |
| webcam = new IpWebcam(device_id.value()); |
| } else { |
| V4L2Webcam* v4l2_webcam = new V4L2Webcam(device_id.value()); |
| if (!v4l2_webcam->Open()) { |
| std::move(callback).Run(nullptr); |
| return; |
| } |
| webcam = v4l2_webcam; |
| } |
| |
| webcam_resource_manager_->Add( |
| new WebcamResource(extension_id, webcam, webcam_id)); |
| |
| std::move(callback).Run(webcam); |
| } |
| |
| // static |
| void WebcamPrivateAPI::GetDeviceIdOnIOThread( |
| std::string salt, |
| url::Origin security_origin, |
| std::string hmac_device_id, |
| base::OnceCallback<void(const std::optional<std::string>&)> callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| content::GetMediaDeviceIDForHMAC( |
| blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, salt, |
| std::move(security_origin), std::move(hmac_device_id), |
| content::GetUIThreadTaskRunner({}), std::move(callback)); |
| } |
| |
| void WebcamPrivateAPI::GetWebcam(const ExtensionId& extension_id, |
| const std::string& webcam_id, |
| base::OnceCallback<void(Webcam*)> callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| WebcamResource* webcam_resource = FindWebcamResource(extension_id, webcam_id); |
| if (webcam_resource) { |
| Webcam* webcam = webcam_resource->GetWebcam(); |
| std::move(callback).Run(webcam); |
| return; |
| } |
| |
| url::Origin security_origin = |
| extensions::Extension::CreateOriginFromExtensionId(extension_id); |
| if (media_device_salt::MediaDeviceSaltService* salt_service = |
| ExtensionsBrowserClient::Get()->GetMediaDeviceSaltService( |
| browser_context_)) { |
| salt_service->GetSalt( |
| blink::StorageKey::CreateFirstParty(security_origin), |
| base::BindOnce(&WebcamPrivateAPI::GetDeviceIdOnUIThread, |
| weak_ptr_factory_.GetWeakPtr(), security_origin, |
| extension_id, webcam_id, std::move(callback))); |
| } else { |
| // If the embedder does not provide a salt service, use the browser |
| // context's unique ID as salt. |
| GetDeviceIdOnUIThread(security_origin, extension_id, webcam_id, |
| std::move(callback), browser_context_->UniqueId()); |
| } |
| } |
| |
| void WebcamPrivateAPI::GetDeviceIdOnUIThread( |
| const url::Origin& security_origin, |
| const ExtensionId& extension_id, |
| const std::string& webcam_id, |
| base::OnceCallback<void(Webcam*)> webcam_callback, |
| const std::string& salt) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| auto got_device_cb = |
| base::BindOnce(&WebcamPrivateAPI::OnGotDeviceIdOnUIThread, |
| weak_ptr_factory_.GetWeakPtr(), extension_id, webcam_id, |
| std::move(webcam_callback)); |
| |
| content::GetIOThreadTaskRunner({})->PostTask( |
| FROM_HERE, |
| base::BindOnce(&WebcamPrivateAPI::GetDeviceIdOnIOThread, salt, |
| security_origin, webcam_id, std::move(got_device_cb))); |
| } |
| |
| void WebcamPrivateAPI::OpenSerialWebcam( |
| const ExtensionId& extension_id, |
| const std::string& device_path, |
| const base::RepeatingCallback<void(const std::string&, |
| OpenSerialWebcamResult)>& callback) { |
| GetWebcamId(extension_id, device_path, |
| base::BindOnce(&WebcamPrivateAPI::GotWebcamId, |
| weak_ptr_factory_.GetWeakPtr(), extension_id, |
| device_path, callback)); |
| } |
| |
| void WebcamPrivateAPI::GotWebcamId( |
| const ExtensionId& extension_id, |
| const std::string& device_path, |
| const base::RepeatingCallback<void(const std::string&, |
| OpenSerialWebcamResult)>& callback, |
| const std::string& webcam_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| WebcamResource* webcam_resource = FindWebcamResource(extension_id, webcam_id); |
| if (webcam_resource) { |
| callback.Run("", OpenSerialWebcamResult::kInUse); |
| return; |
| } |
| |
| mojo::PendingRemote<device::mojom::SerialPort> port; |
| auto* port_manager = api::SerialPortManager::Get(browser_context_); |
| DCHECK(port_manager); |
| |
| auto visca_webcam = base::MakeRefCounted<ViscaWebcam>(); |
| visca_webcam->Open( |
| extension_id, port_manager, device_path, |
| base::BindRepeating(&WebcamPrivateAPI::OnOpenSerialWebcam, |
| weak_ptr_factory_.GetWeakPtr(), webcam_id, |
| extension_id, device_path, visca_webcam, callback)); |
| } |
| |
| bool WebcamPrivateAPI::CloseWebcam(const ExtensionId& extension_id, |
| const std::string& webcam_id) { |
| if (FindWebcamResource(extension_id, webcam_id)) { |
| RemoveWebcamResource(extension_id, webcam_id); |
| return true; |
| } |
| return false; |
| } |
| |
| void WebcamPrivateAPI::OnOpenSerialWebcam( |
| const std::string& webcam_id, |
| const ExtensionId& extension_id, |
| const std::string& device_path, |
| scoped_refptr<Webcam> webcam, |
| const base::RepeatingCallback<void(const std::string&, |
| OpenSerialWebcamResult)>& callback, |
| bool success) { |
| if (success) { |
| webcam_resource_manager_->Add( |
| new WebcamResource(extension_id, webcam.get(), webcam_id)); |
| callback.Run(webcam_id, OpenSerialWebcamResult::kSuccess); |
| } else { |
| callback.Run("", OpenSerialWebcamResult::kError); |
| } |
| } |
| |
| void WebcamPrivateAPI::GetWebcamId( |
| const ExtensionId& extension_id, |
| const std::string& device_id, |
| base::OnceCallback<void(const std::string&)> webcam_id_callback) { |
| url::Origin security_origin = |
| extensions::Extension::CreateOriginFromExtensionId(extension_id); |
| if (media_device_salt::MediaDeviceSaltService* salt_service = |
| ExtensionsBrowserClient::Get()->GetMediaDeviceSaltService( |
| browser_context_)) { |
| salt_service->GetSalt( |
| blink::StorageKey::CreateFirstParty(security_origin), |
| base::BindOnce(&WebcamPrivateAPI::FinalizeGetWebcamId, |
| weak_ptr_factory_.GetWeakPtr(), security_origin, |
| device_id, std::move(webcam_id_callback))); |
| } else { |
| // If the embedder does not provide a salt service, use the browser |
| // context's unique ID as salt. |
| FinalizeGetWebcamId(security_origin, device_id, |
| std::move(webcam_id_callback), |
| browser_context_->UniqueId()); |
| } |
| } |
| |
| void WebcamPrivateAPI::FinalizeGetWebcamId( |
| const url::Origin& security_origin, |
| const std::string& device_id, |
| base::OnceCallback<void(const std::string&)> webcam_id_callback, |
| const std::string& device_id_salt) { |
| std::string webcam_id = content::GetHMACForMediaDeviceID( |
| device_id_salt, security_origin, device_id); |
| std::move(webcam_id_callback).Run(webcam_id); |
| } |
| |
| WebcamResource* WebcamPrivateAPI::FindWebcamResource( |
| const ExtensionId& extension_id, |
| const std::string& webcam_id) const { |
| DCHECK(webcam_resource_manager_); |
| |
| std::unordered_set<int>* connection_ids = |
| webcam_resource_manager_->GetResourceIds(extension_id); |
| if (!connection_ids) |
| return nullptr; |
| |
| for (const auto& connection_id : *connection_ids) { |
| WebcamResource* webcam_resource = |
| webcam_resource_manager_->Get(extension_id, connection_id); |
| if (webcam_resource && webcam_resource->GetWebcamId() == webcam_id) |
| return webcam_resource; |
| } |
| |
| return nullptr; |
| } |
| |
| bool WebcamPrivateAPI::RemoveWebcamResource(const ExtensionId& extension_id, |
| const std::string& webcam_id) { |
| DCHECK(webcam_resource_manager_); |
| |
| std::unordered_set<int>* connection_ids = |
| webcam_resource_manager_->GetResourceIds(extension_id); |
| if (!connection_ids) |
| return false; |
| |
| for (const auto& connection_id : *connection_ids) { |
| WebcamResource* webcam_resource = |
| webcam_resource_manager_->Get(extension_id, connection_id); |
| if (webcam_resource && webcam_resource->GetWebcamId() == webcam_id) { |
| webcam_resource_manager_->Remove(extension_id, connection_id); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| WebcamPrivateOpenSerialWebcamFunction::WebcamPrivateOpenSerialWebcamFunction() { |
| } |
| |
| WebcamPrivateOpenSerialWebcamFunction:: |
| ~WebcamPrivateOpenSerialWebcamFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WebcamPrivateOpenSerialWebcamFunction::Run() { |
| std::optional<webcam_private::OpenSerialWebcam::Params> params = |
| webcam_private::OpenSerialWebcam::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->OpenSerialWebcam( |
| extension_id(), params->path, |
| base::BindRepeating( |
| &WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam, this)); |
| // OpenSerialWebcam responds asynchronously. |
| return RespondLater(); |
| } |
| |
| void WebcamPrivateOpenSerialWebcamFunction::OnOpenWebcam( |
| const std::string& webcam_id, |
| WebcamPrivateAPI::OpenSerialWebcamResult result) { |
| if (result == WebcamPrivateAPI::OpenSerialWebcamResult::kSuccess) { |
| Respond(WithArguments(webcam_id)); |
| } else if (result == WebcamPrivateAPI::OpenSerialWebcamResult::kError) { |
| Respond(Error(kOpenSerialWebcamError)); |
| } else if (result == WebcamPrivateAPI::OpenSerialWebcamResult::kInUse) { |
| Respond(Error(kPathInUse)); |
| } |
| } |
| |
| WebcamPrivateCloseWebcamFunction::WebcamPrivateCloseWebcamFunction() { |
| } |
| |
| WebcamPrivateCloseWebcamFunction::~WebcamPrivateCloseWebcamFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WebcamPrivateCloseWebcamFunction::Run() { |
| std::optional<webcam_private::CloseWebcam::Params> params = |
| webcam_private::CloseWebcam::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| const bool success = WebcamPrivateAPI::Get(browser_context()) |
| ->CloseWebcam(extension_id(), params->webcam_id); |
| return RespondNow(success ? NoArguments() : Error(kUnknownErrorDoNotUse)); |
| } |
| |
| WebcamPrivateSetFunction::WebcamPrivateSetFunction() { |
| } |
| |
| WebcamPrivateSetFunction::~WebcamPrivateSetFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WebcamPrivateSetFunction::Run() { |
| std::optional<webcam_private::Set::Params> params = |
| webcam_private::Set::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| std::string webcam_id = params->webcam_id; |
| |
| auto on_webcam = base::BindOnce(&WebcamPrivateSetFunction::OnWebcam, this, |
| std::move(params)); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), webcam_id, std::move(on_webcam)); |
| |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateSetFunction::OnWebcam( |
| std::optional<webcam_private::Set::Params> params, |
| Webcam* webcam) { |
| if (!webcam) |
| return Respond(Error(kUnknownWebcam)); |
| |
| int pan_speed = 0; |
| int tilt_speed = 0; |
| if (params->config.pan_speed) |
| pan_speed = *(params->config.pan_speed); |
| |
| if (params->config.tilt_speed) |
| tilt_speed = *(params->config.tilt_speed); |
| |
| // Count all of the requests we will send before potentially sending any. |
| pending_num_set_webcam_param_requests_ = 0; |
| if (params->config.pan) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.pan_direction != webcam_private::PanDirection::kNone) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.tilt) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.tilt_direction != webcam_private::TiltDirection::kNone) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.zoom) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.autofocus_state != webcam_private::AutofocusState::kNone) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| if (params->config.focus) { |
| ++pending_num_set_webcam_param_requests_; |
| } |
| |
| if (params->config.pan) { |
| webcam->SetPan(*(params->config.pan), pan_speed, |
| base::BindRepeating( |
| &WebcamPrivateSetFunction::OnSetWebcamParameters, this)); |
| } |
| |
| if (params->config.pan_direction != webcam_private::PanDirection::kNone) { |
| Webcam::PanDirection direction = Webcam::PAN_STOP; |
| switch (params->config.pan_direction) { |
| case webcam_private::PanDirection::kNone: |
| case webcam_private::PanDirection::kStop: |
| direction = Webcam::PAN_STOP; |
| break; |
| |
| case webcam_private::PanDirection::kRight: |
| direction = Webcam::PAN_RIGHT; |
| break; |
| |
| case webcam_private::PanDirection::kLeft: |
| direction = Webcam::PAN_LEFT; |
| break; |
| } |
| webcam->SetPanDirection( |
| direction, pan_speed, |
| base::BindRepeating(&WebcamPrivateSetFunction::OnSetWebcamParameters, |
| this)); |
| } |
| |
| if (params->config.tilt) { |
| webcam->SetTilt( |
| *(params->config.tilt), tilt_speed, |
| base::BindRepeating(&WebcamPrivateSetFunction::OnSetWebcamParameters, |
| this)); |
| } |
| |
| if (params->config.tilt_direction != webcam_private::TiltDirection::kNone) { |
| Webcam::TiltDirection direction = Webcam::TILT_STOP; |
| switch (params->config.tilt_direction) { |
| case webcam_private::TiltDirection::kNone: |
| case webcam_private::TiltDirection::kStop: |
| direction = Webcam::TILT_STOP; |
| break; |
| |
| case webcam_private::TiltDirection::kUp: |
| direction = Webcam::TILT_UP; |
| break; |
| |
| case webcam_private::TiltDirection::kDown: |
| direction = Webcam::TILT_DOWN; |
| break; |
| } |
| webcam->SetTiltDirection( |
| direction, tilt_speed, |
| base::BindRepeating(&WebcamPrivateSetFunction::OnSetWebcamParameters, |
| this)); |
| } |
| |
| if (params->config.zoom) { |
| webcam->SetZoom( |
| *(params->config.zoom), |
| base::BindRepeating(&WebcamPrivateSetFunction::OnSetWebcamParameters, |
| this)); |
| } |
| |
| if (params->config.autofocus_state != webcam_private::AutofocusState::kNone) { |
| Webcam::AutofocusState state = Webcam::AUTOFOCUS_ON; |
| switch (params->config.autofocus_state) { |
| case webcam_private::AutofocusState::kNone: |
| case webcam_private::AutofocusState::kOff: |
| state = Webcam::AUTOFOCUS_OFF; |
| break; |
| |
| case webcam_private::AutofocusState::kOn: |
| state = Webcam::AUTOFOCUS_ON; |
| break; |
| } |
| webcam->SetAutofocusState( |
| state, base::BindRepeating( |
| &WebcamPrivateSetFunction::OnSetWebcamParameters, this)); |
| } |
| |
| if (params->config.focus) { |
| webcam->SetFocus( |
| *(params->config.focus), |
| base::BindRepeating(&WebcamPrivateSetFunction::OnSetWebcamParameters, |
| this)); |
| } |
| } |
| |
| void WebcamPrivateSetFunction::OnSetWebcamParameters(bool success) { |
| failed_ |= !success; |
| --pending_num_set_webcam_param_requests_; |
| |
| DCHECK_GE(pending_num_set_webcam_param_requests_, 0); |
| if (pending_num_set_webcam_param_requests_ != 0) { |
| return; |
| } |
| |
| if (failed_) { |
| Respond(Error(kSetWebcamPTZError)); |
| return; |
| } |
| |
| // Reply with a dummy, empty configuration. |
| webcam_private::WebcamCurrentConfiguration result; |
| Respond(WithArguments(result.ToValue())); |
| } |
| |
| WebcamPrivateGetFunction::WebcamPrivateGetFunction() |
| : min_pan_(0), |
| max_pan_(0), |
| pan_(0), |
| min_tilt_(0), |
| max_tilt_(0), |
| tilt_(0), |
| min_zoom_(0), |
| max_zoom_(0), |
| zoom_(0), |
| min_focus_(0), |
| max_focus_(0), |
| focus_(0), |
| got_pan_(false), |
| got_tilt_(false), |
| got_zoom_(false), |
| got_focus_(false), |
| success_(false) {} |
| |
| WebcamPrivateGetFunction::~WebcamPrivateGetFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WebcamPrivateGetFunction::Run() { |
| std::optional<webcam_private::Get::Params> params = |
| webcam_private::Get::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| auto on_webcam = base::BindOnce(&WebcamPrivateGetFunction::OnWebcam, this); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), params->webcam_id, std::move(on_webcam)); |
| |
| // Might have already responded if webcam_resource_manager_ already has the |
| // Webcam. |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateGetFunction::OnWebcam(Webcam* webcam) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (!webcam) { |
| Respond(Error(kUnknownWebcam)); |
| return; |
| } |
| |
| webcam->GetPan(base::BindRepeating( |
| &WebcamPrivateGetFunction::OnGetWebcamParameters, this, INQUIRY_PAN)); |
| webcam->GetTilt(base::BindRepeating( |
| &WebcamPrivateGetFunction::OnGetWebcamParameters, this, INQUIRY_TILT)); |
| webcam->GetZoom(base::BindRepeating( |
| &WebcamPrivateGetFunction::OnGetWebcamParameters, this, INQUIRY_ZOOM)); |
| webcam->GetFocus(base::BindRepeating( |
| &WebcamPrivateGetFunction::OnGetWebcamParameters, this, INQUIRY_FOCUS)); |
| } |
| |
| // Retrieve webcam parameters. Will respond a config holding the requested |
| // values if any of the requests succeeds. Otherwise will respond an error. |
| void WebcamPrivateGetFunction::OnGetWebcamParameters(InquiryType type, |
| bool success, |
| int value, |
| int min_value, |
| int max_value) { |
| success_ = success_ || success; |
| |
| switch (type) { |
| case INQUIRY_PAN: |
| if (success) { |
| min_pan_ = min_value; |
| max_pan_ = max_value; |
| pan_ = value; |
| } |
| got_pan_ = true; |
| break; |
| case INQUIRY_TILT: |
| if (success) { |
| min_tilt_ = min_value; |
| max_tilt_ = max_value; |
| tilt_ = value; |
| } |
| got_tilt_ = true; |
| break; |
| case INQUIRY_ZOOM: |
| if (success) { |
| min_zoom_ = min_value; |
| max_zoom_ = max_value; |
| zoom_ = value; |
| } |
| got_zoom_ = true; |
| break; |
| case INQUIRY_FOCUS: |
| if (success) { |
| min_focus_ = min_value; |
| max_focus_ = max_value; |
| focus_ = value; |
| } |
| got_focus_ = true; |
| break; |
| } |
| if (got_pan_ && got_tilt_ && got_zoom_ && got_focus_) { |
| if (!success_) { |
| Respond(Error(kGetWebcamPTZError)); |
| return; |
| } |
| |
| webcam_private::WebcamCurrentConfiguration result; |
| if (min_pan_ != max_pan_) { |
| result.pan_range.emplace(); |
| result.pan_range->min = min_pan_; |
| result.pan_range->max = max_pan_; |
| } |
| if (min_tilt_ != max_tilt_) { |
| result.tilt_range.emplace(); |
| result.tilt_range->min = min_tilt_; |
| result.tilt_range->max = max_tilt_; |
| } |
| if (min_zoom_ != max_zoom_) { |
| result.zoom_range.emplace(); |
| result.zoom_range->min = min_zoom_; |
| result.zoom_range->max = max_zoom_; |
| } |
| if (min_focus_ != max_focus_) { |
| result.focus_range.emplace(); |
| result.focus_range->min = min_focus_; |
| result.focus_range->max = max_focus_; |
| } |
| |
| result.pan = pan_; |
| result.tilt = tilt_; |
| result.zoom = zoom_; |
| result.focus = focus_; |
| Respond(WithArguments(result.ToValue())); |
| } |
| } |
| |
| WebcamPrivateResetFunction::WebcamPrivateResetFunction() { |
| } |
| |
| WebcamPrivateResetFunction::~WebcamPrivateResetFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WebcamPrivateResetFunction::Run() { |
| std::optional<webcam_private::Reset::Params> params = |
| webcam_private::Reset::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| std::string webcam_id = params->webcam_id; |
| |
| auto on_webcam = base::BindOnce(&WebcamPrivateResetFunction::OnWebcam, this, |
| std::move(params)); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), webcam_id, std::move(on_webcam)); |
| |
| // Might have already responsed if webcam_resource_manager_ already has the |
| // Webcam and WebCam::Reset just runs the callback. |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateResetFunction::OnWebcam( |
| std::optional<webcam_private::Reset::Params> params, |
| Webcam* webcam) { |
| if (!webcam) |
| return Respond(Error(kUnknownWebcam)); |
| |
| webcam->Reset( |
| params->config.pan.has_value(), params->config.tilt.has_value(), |
| params->config.zoom.has_value(), |
| base::BindRepeating(&WebcamPrivateResetFunction::OnResetWebcam, this)); |
| } |
| |
| void WebcamPrivateResetFunction::OnResetWebcam(bool success) { |
| if (!success) { |
| Respond(Error(kResetWebcamError)); |
| return; |
| } |
| |
| // Reply with a dummy, empty configuration. |
| webcam_private::WebcamCurrentConfiguration result; |
| Respond(WithArguments(result.ToValue())); |
| } |
| |
| WebcamPrivateSetHomeFunction::WebcamPrivateSetHomeFunction() = default; |
| |
| WebcamPrivateSetHomeFunction::~WebcamPrivateSetHomeFunction() = default; |
| |
| ExtensionFunction::ResponseAction WebcamPrivateSetHomeFunction::Run() { |
| std::optional<webcam_private::SetHome::Params> params = |
| webcam_private::SetHome::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| auto on_webcam = |
| base::BindOnce(&WebcamPrivateSetHomeFunction::OnWebcam, this); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), params->webcam_id, std::move(on_webcam)); |
| |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateSetHomeFunction::OnWebcam(Webcam* webcam) { |
| if (!webcam) |
| return Respond(Error(kUnknownWebcam)); |
| |
| webcam->SetHome(base::BindRepeating( |
| &WebcamPrivateSetHomeFunction::OnSetHomeWebcam, this)); |
| } |
| |
| void WebcamPrivateSetHomeFunction::OnSetHomeWebcam(bool success) { |
| if (!success) { |
| Respond(Error(kSetHomeWebcamError)); |
| return; |
| } |
| |
| // Reply with a dummy, empty configuration. |
| webcam_private::WebcamCurrentConfiguration result; |
| Respond(WithArguments(result.ToValue())); |
| } |
| |
| WebcamPrivateRestoreCameraPresetFunction:: |
| WebcamPrivateRestoreCameraPresetFunction() {} |
| |
| WebcamPrivateRestoreCameraPresetFunction:: |
| ~WebcamPrivateRestoreCameraPresetFunction() {} |
| |
| ExtensionFunction::ResponseAction |
| WebcamPrivateRestoreCameraPresetFunction::Run() { |
| std::optional<webcam_private::RestoreCameraPreset::Params> params = |
| webcam_private::RestoreCameraPreset::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| auto on_webcam = |
| base::BindOnce(&WebcamPrivateRestoreCameraPresetFunction::OnWebcam, this, |
| params->preset_number); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), params->webcam_id, std::move(on_webcam)); |
| |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateRestoreCameraPresetFunction::OnWebcam(int preset_number, |
| Webcam* webcam) { |
| if (!webcam) { |
| Respond(Error(kUnknownWebcam)); |
| return; |
| } |
| |
| webcam->RestoreCameraPreset( |
| preset_number, |
| base::BindRepeating(&WebcamPrivateRestoreCameraPresetFunction:: |
| OnRestoreCameraPresetWebcam, |
| this)); |
| } |
| |
| void WebcamPrivateRestoreCameraPresetFunction::OnRestoreCameraPresetWebcam( |
| bool success) { |
| if (!success) { |
| Respond(Error(kRestorePresetWebcamError)); |
| return; |
| } |
| |
| // Reply with a dummy, empty configuration. |
| webcam_private::WebcamCurrentConfiguration result; |
| Respond(WithArguments(result.ToValue())); |
| } |
| |
| WebcamPrivateSetCameraPresetFunction::WebcamPrivateSetCameraPresetFunction() = |
| default; |
| |
| WebcamPrivateSetCameraPresetFunction::~WebcamPrivateSetCameraPresetFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction WebcamPrivateSetCameraPresetFunction::Run() { |
| std::optional<webcam_private::SetCameraPreset::Params> params = |
| webcam_private::SetCameraPreset::Params::Create(args()); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| auto on_webcam = |
| base::BindOnce(&WebcamPrivateSetCameraPresetFunction::OnWebcam, this, |
| params->preset_number); |
| |
| WebcamPrivateAPI::Get(browser_context()) |
| ->GetWebcam(extension_id(), params->webcam_id, std::move(on_webcam)); |
| |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void WebcamPrivateSetCameraPresetFunction::OnWebcam(int preset_number, |
| Webcam* webcam) { |
| if (!webcam) { |
| Respond(Error(kUnknownWebcam)); |
| return; |
| } |
| |
| webcam->SetCameraPreset( |
| preset_number, |
| base::BindRepeating( |
| &WebcamPrivateSetCameraPresetFunction::OnSetCameraPresetWebcam, |
| this)); |
| } |
| |
| void WebcamPrivateSetCameraPresetFunction::OnSetCameraPresetWebcam( |
| bool success) { |
| if (!success) { |
| Respond(Error(kSetPresetWebcamError)); |
| return; |
| } |
| |
| // Reply with a dummy, empty configuration. |
| webcam_private::WebcamCurrentConfiguration result; |
| Respond(WithArguments(result.ToValue())); |
| } |
| |
| static base::LazyInstance<BrowserContextKeyedAPIFactory<WebcamPrivateAPI>>:: |
| DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER; |
| |
| // static |
| BrowserContextKeyedAPIFactory<WebcamPrivateAPI>* |
| WebcamPrivateAPI::GetFactoryInstance() { |
| return g_factory.Pointer(); |
| } |
| |
| template <> |
| void BrowserContextKeyedAPIFactory<WebcamPrivateAPI> |
| ::DeclareFactoryDependencies() { |
| DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); |
| DependsOn(ProcessManagerFactory::GetInstance()); |
| } |
| |
| } // namespace extensions |