blob: 38237643d2ae16da85757a99f53cc96900888114 [file] [log] [blame]
// 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