| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/crosapi/document_scan_ash.h" |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "ash/constants/ash_features.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chrome/browser/ash/crosapi/document_scan_ash_type_converters.h" |
| #include "chrome/browser/ash/scanning/lorgnette_scanner_manager.h" |
| #include "chrome/browser/ash/scanning/lorgnette_scanner_manager_factory.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chromeos/ash/components/dbus/lorgnette/lorgnette_service.pb.h" |
| #include "components/user_manager/user_manager.h" |
| |
| namespace crosapi { |
| |
| namespace { |
| |
| Profile* GetProfile() { |
| if (!user_manager::UserManager::IsInitialized() || |
| !user_manager::UserManager::Get()->IsUserLoggedIn()) { |
| return nullptr; |
| } |
| return ProfileManager::GetPrimaryUserProfile(); |
| } |
| |
| // Supports the static_cast() in ProtobufResultToMojoResult() below. |
| static_assert(lorgnette::SCAN_FAILURE_MODE_NO_FAILURE == |
| static_cast<int>(mojom::ScanFailureMode::kNoFailure)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_UNKNOWN == |
| static_cast<int>(mojom::ScanFailureMode::kUnknown)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_DEVICE_BUSY == |
| static_cast<int>(mojom::ScanFailureMode::kDeviceBusy)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_ADF_JAMMED == |
| static_cast<int>(mojom::ScanFailureMode::kAdfJammed)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_ADF_EMPTY == |
| static_cast<int>(mojom::ScanFailureMode::kAdfEmpty)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_FLATBED_OPEN == |
| static_cast<int>(mojom::ScanFailureMode::kFlatbedOpen)); |
| static_assert(lorgnette::SCAN_FAILURE_MODE_IO_ERROR == |
| static_cast<int>(mojom::ScanFailureMode::kIoError)); |
| |
| void OpenScannerAdapter( |
| const std::string& scanner_id, |
| DocumentScanAsh::OpenScannerCallback callback, |
| const std::optional<lorgnette::OpenScannerResponse>& response_in) { |
| if (!response_in) { |
| auto response_out = mojom::OpenScannerResponse::New(); |
| response_out->scanner_id = scanner_id; |
| response_out->result = mojom::ScannerOperationResult::kInternalError; |
| std::move(callback).Run(std::move(response_out)); |
| return; |
| } |
| std::move(callback).Run( |
| mojom::OpenScannerResponse::From(response_in.value())); |
| } |
| |
| void CloseScannerAdapter( |
| const std::string& scanner_handle, |
| DocumentScanAsh::CloseScannerCallback callback, |
| const std::optional<lorgnette::CloseScannerResponse>& response_in) { |
| if (!response_in) { |
| auto response_out = mojom::CloseScannerResponse::New(); |
| response_out->scanner_handle = scanner_handle; |
| response_out->result = mojom::ScannerOperationResult::kInternalError; |
| std::move(callback).Run(std::move(response_out)); |
| return; |
| } |
| std::move(callback).Run( |
| mojom::CloseScannerResponse::From(response_in.value())); |
| } |
| |
| void StartPreparedScanAdapter( |
| const std::string& scanner_handle, |
| DocumentScanAsh::StartPreparedScanCallback callback, |
| const std::optional<lorgnette::StartPreparedScanResponse>& response_in) { |
| if (!response_in) { |
| auto response = mojom::StartPreparedScanResponse::New(); |
| response->result = mojom::ScannerOperationResult::kInternalError; |
| response->scanner_handle = scanner_handle; |
| std::move(callback).Run(std::move(response)); |
| return; |
| } |
| std::move(callback).Run( |
| mojom::StartPreparedScanResponse::From(response_in.value())); |
| } |
| |
| void ReadScanDataAdapter( |
| const std::string& job_handle, |
| DocumentScanAsh::ReadScanDataCallback callback, |
| const std::optional<lorgnette::ReadScanDataResponse>& response_in) { |
| if (!response_in) { |
| auto response = mojom::ReadScanDataResponse::New(); |
| response->result = mojom::ScannerOperationResult::kInternalError; |
| response->job_handle = job_handle; |
| std::move(callback).Run(std::move(response)); |
| return; |
| } |
| std::move(callback).Run( |
| mojom::ReadScanDataResponse::From(response_in.value())); |
| } |
| |
| void SetOptionsAdapter( |
| const std::string& scanner_handle, |
| std::vector<std::string> option_names, |
| std::vector<std::string> invalid_option_names, |
| DocumentScanAsh::SetOptionsCallback callback, |
| const std::optional<lorgnette::SetOptionsResponse>& response_in) { |
| if (!response_in) { |
| auto response = mojom::SetOptionsResponse::New(); |
| response->scanner_handle = scanner_handle; |
| for (const std::string& option_name : option_names) { |
| auto result = mojom::SetOptionResult::New(); |
| result->name = option_name; |
| result->result = mojom::ScannerOperationResult::kInternalError; |
| response->results.emplace_back(std::move(result)); |
| } |
| std::move(callback).Run(std::move(response)); |
| return; |
| } |
| lorgnette::SetOptionsResponse response = response_in.value(); |
| for (const std::string& invalid_name : invalid_option_names) { |
| (*response.mutable_results())[invalid_name] = |
| lorgnette::OperationResult::OPERATION_RESULT_WRONG_TYPE; |
| } |
| std::move(callback).Run(mojom::SetOptionsResponse::From(response)); |
| } |
| |
| void GetOptionGroupsAdapter( |
| const std::string& scanner_handle, |
| DocumentScanAsh::GetOptionGroupsCallback callback, |
| const std::optional<lorgnette::GetCurrentConfigResponse>& response_in) { |
| if (!response_in) { |
| auto response = mojom::GetOptionGroupsResponse::New(); |
| response->result = mojom::ScannerOperationResult::kInternalError; |
| response->scanner_handle = scanner_handle; |
| std::move(callback).Run(std::move(response)); |
| return; |
| } |
| std::move(callback).Run( |
| mojom::GetOptionGroupsResponse::From(response_in.value())); |
| } |
| |
| void CancelScanAdapter( |
| const std::string& job_handle, |
| DocumentScanAsh::CancelScanCallback callback, |
| const std::optional<lorgnette::CancelScanResponse>& response_in) { |
| if (!response_in) { |
| auto response = mojom::CancelScanResponse::New(); |
| response->job_handle = job_handle; |
| response->result = mojom::ScannerOperationResult::kInternalError; |
| std::move(callback).Run(std::move(response)); |
| return; |
| } |
| std::move(callback).Run(mojom::CancelScanResponse::From(response_in.value())); |
| } |
| |
| } // namespace |
| |
| DocumentScanAsh::DocumentScanAsh() = default; |
| |
| DocumentScanAsh::~DocumentScanAsh() = default; |
| |
| void DocumentScanAsh::BindReceiver( |
| mojo::PendingReceiver<mojom::DocumentScan> pending_receiver) { |
| receivers_.Add(this, std::move(pending_receiver)); |
| } |
| |
| void DocumentScanAsh::OpenScanner(const std::string& client_id, |
| const std::string& scanner_id, |
| OpenScannerCallback callback) { |
| lorgnette::OpenScannerRequest request; |
| request.mutable_scanner_id()->set_connection_string(scanner_id); |
| request.set_client_id(client_id); |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->OpenScanner( |
| std::move(request), |
| base::BindOnce(&OpenScannerAdapter, scanner_id, std::move(callback))); |
| } |
| |
| void DocumentScanAsh::CloseScanner(const std::string& scanner_handle, |
| CloseScannerCallback callback) { |
| lorgnette::CloseScannerRequest request; |
| request.mutable_scanner()->set_token(scanner_handle); |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->CloseScanner(std::move(request), |
| base::BindOnce(&CloseScannerAdapter, scanner_handle, |
| std::move(callback))); |
| } |
| |
| void DocumentScanAsh::StartPreparedScan(const std::string& scanner_handle, |
| mojom::StartScanOptionsPtr options, |
| StartPreparedScanCallback callback) { |
| lorgnette::StartPreparedScanRequest request; |
| request.mutable_scanner()->set_token(scanner_handle); |
| request.set_image_format(options->format); |
| if (options->max_read_size) { |
| request.set_max_read_size(*options->max_read_size); |
| } |
| |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->StartPreparedScan( |
| request, base::BindOnce(&StartPreparedScanAdapter, scanner_handle, |
| std::move(callback))); |
| } |
| |
| void DocumentScanAsh::ReadScanData(const std::string& job_handle, |
| ReadScanDataCallback callback) { |
| lorgnette::ReadScanDataRequest request; |
| request.mutable_job_handle()->set_token(job_handle); |
| |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->ReadScanData(request, base::BindOnce(&ReadScanDataAdapter, job_handle, |
| std::move(callback))); |
| } |
| |
| void DocumentScanAsh::SetOptions(const std::string& scanner_handle, |
| std::vector<mojom::OptionSettingPtr> options, |
| SetOptionsCallback callback) { |
| lorgnette::SetOptionsRequest request; |
| request.mutable_scanner()->set_token(scanner_handle); |
| // Keep track of all of the option names. This is used if we don't get a |
| // valid response from the backend. All of these options will get sent back |
| // to the caller with an error result. |
| std::vector<std::string> option_names; |
| // Separately, keep track of any invalid options names (where the type |
| // specified for the value does not equal the type of the option). These |
| // options will get sent back to the caller with an appropriate error result. |
| std::vector<std::string> invalid_option_names; |
| for (const mojom::OptionSettingPtr& option_request : options) { |
| option_names.emplace_back(option_request->name); |
| |
| auto maybe_option = |
| option_request.To<std::optional<lorgnette::ScannerOption>>(); |
| if (maybe_option.has_value()) { |
| *request.add_options() = maybe_option.value(); |
| } else { |
| invalid_option_names.emplace_back(option_request->name); |
| } |
| } |
| |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->SetOptions(request, base::BindOnce(&SetOptionsAdapter, scanner_handle, |
| option_names, invalid_option_names, |
| std::move(callback))); |
| } |
| |
| void DocumentScanAsh::GetOptionGroups(const std::string& scanner_handle, |
| GetOptionGroupsCallback callback) { |
| lorgnette::GetCurrentConfigRequest request; |
| request.mutable_scanner()->set_token(scanner_handle); |
| |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->GetCurrentConfig(request, |
| base::BindOnce(&GetOptionGroupsAdapter, scanner_handle, |
| std::move(callback))); |
| } |
| |
| void DocumentScanAsh::CancelScan(const std::string& job_handle, |
| CancelScanCallback callback) { |
| lorgnette::CancelScanRequest request; |
| request.mutable_job_handle()->set_token(job_handle); |
| |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->CancelScan(request, base::BindOnce(&CancelScanAdapter, job_handle, |
| std::move(callback))); |
| } |
| |
| } // namespace crosapi |