| // 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 <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/memory/weak_ptr.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" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace crosapi { |
| |
| namespace { |
| |
| Profile* GetProfile() { |
| if (!user_manager::UserManager::IsInitialized() || |
| !user_manager::UserManager::Get()->IsUserLoggedIn()) { |
| return nullptr; |
| } |
| return ProfileManager::GetPrimaryUserProfile(); |
| } |
| |
| void GetScannerNamesAdapter(DocumentScanAsh::GetScannerNamesCallback callback, |
| std::vector<std::string> scanner_names) { |
| std::move(callback).Run(scanner_names); |
| } |
| |
| // 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)); |
| |
| mojom::ScanFailureMode ProtobufResultToMojoResult( |
| lorgnette::ScanFailureMode failure_mode) { |
| // The static_assert() checks above make this cast safe. |
| return static_cast<mojom::ScanFailureMode>(failure_mode); |
| } |
| |
| // Wrapper around `data` that allows this to be a WeakPtr. |
| struct ScanResult : public base::SupportsWeakPtr<ScanResult> { |
| public: |
| ScanResult() = default; |
| ScanResult(const ScanResult&) = delete; |
| ScanResult& operator=(const ScanResult&) = delete; |
| ~ScanResult() = default; |
| |
| absl::optional<std::string> data; |
| }; |
| |
| void OnPageReceived(base::WeakPtr<ScanResult> scan_result, |
| std::string scanned_image, |
| uint32_t /*page_number*/) { |
| if (!scan_result) |
| return; |
| |
| // Take only the first page of the scan. |
| if (scan_result->data.has_value()) |
| return; |
| |
| scan_result->data = std::move(scanned_image); |
| } |
| |
| // As a standalone function, this will always run `callback`. If this was a |
| // DocumentScanAsh method instead, then that method bound to a |
| // base::WeakPtr<DocumentScanAsh> may sometimes not run `callback`. |
| void OnScanCompleted(DocumentScanAsh::ScanFirstPageCallback callback, |
| std::unique_ptr<ScanResult> scan_result, |
| lorgnette::ScanFailureMode failure_mode) { |
| std::move(callback).Run(ProtobufResultToMojoResult(failure_mode), |
| std::move(scan_result->data)); |
| } |
| |
| } // 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::GetScannerNames(GetScannerNamesCallback callback) { |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->GetScannerNames( |
| base::BindOnce(GetScannerNamesAdapter, std::move(callback))); |
| } |
| |
| void DocumentScanAsh::ScanFirstPage(const std::string& scanner_name, |
| ScanFirstPageCallback callback) { |
| lorgnette::ScanSettings settings; |
| settings.set_color_mode(lorgnette::MODE_COLOR); // Hardcoded for now. |
| |
| auto scan_result = std::make_unique<ScanResult>(); |
| auto scan_result_weak_ptr = scan_result->AsWeakPtr(); |
| ash::LorgnetteScannerManagerFactory::GetForBrowserContext(GetProfile()) |
| ->Scan(scanner_name, settings, base::NullCallback(), |
| base::BindRepeating(&OnPageReceived, scan_result_weak_ptr), |
| base::BindOnce(&OnScanCompleted, std::move(callback), |
| std::move(scan_result))); |
| } |
| |
| } // namespace crosapi |