blob: 5de1e97b908d1de9098a804652a8636cc324b252 [file] [log] [blame]
// Copyright 2013 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LORGNETTE_MANAGER_H_
#define LORGNETTE_MANAGER_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include <base/containers/flat_map.h>
#include <base/containers/flat_set.h>
#include <base/files/scoped_file.h>
#include <base/functional/callback.h>
#include <base/functional/callback_helpers.h>
#include <base/memory/weak_ptr.h>
#include <base/sequence_checker.h>
#include <base/time/time.h>
#include <brillo/errors/error.h>
#include <lorgnette/proto_bindings/lorgnette_service.pb.h>
#include <metrics/metrics_library.h>
#include "lorgnette/dbus_adaptors/org.chromium.lorgnette.Manager.h"
#include "lorgnette/sane_client.h"
using brillo::dbus_utils::DBusMethodResponse;
namespace brillo {
namespace dbus_utils {
class ExportedObjectManager;
} // namespace dbus_utils
} // namespace brillo
namespace lorgnette {
// This enum corresponds to Chromium's ScanJobFailureReason in
// src/ash/webui/scanning/scanning_uma.h
// DO NOT CHANGE THESE VALUES without changing values in the original file.
enum class ScanJobFailureReason {
kUnknownScannerError = 0,
kScannerNotFound = 1,
kUnsupportedScanToPath = 2,
kSaveToDiskFailed = 3,
kDeviceBusy = 4,
kAdfJammed = 5,
kAdfEmpty = 6,
kFlatbedOpen = 7,
kIoError = 8,
kSuccess = 9,
kMaxValue = kSuccess,
};
namespace impl {
// Returns a byte vector containing the serialized representation of |proto|.
template <typename T>
std::vector<uint8_t> SerializeProto(const T& proto) {
std::vector<uint8_t> serialized;
serialized.resize(proto.ByteSizeLong());
proto.SerializeToArray(serialized.data(), serialized.size());
return serialized;
}
// Attempts to parse a ColorMode from the mode names used by SANE. If |mode|
// is not recognized, returns MODE_UNSPECIFIED.
ColorMode ColorModeFromSaneString(const std::string& mode);
} // namespace impl
using StatusSignalSender =
base::RepeatingCallback<void(const ScanStatusChangedSignal&)>;
class FirewallManager;
class Manager {
public:
Manager(base::RepeatingCallback<void(base::TimeDelta)> activity_callback,
SaneClient* sane_client);
Manager(const Manager&) = delete;
Manager& operator=(const Manager&) = delete;
virtual ~Manager();
void SetFirewallManager(FirewallManager* firewall_manager);
// Implementation of MethodInterface.
virtual bool ListScanners(brillo::ErrorPtr* error,
ListScannersResponse* scanner_list_out);
virtual bool GetScannerCapabilities(brillo::ErrorPtr* error,
const std::string& device_name,
ScannerCapabilities* capabilities);
virtual StartScanResponse StartScan(const StartScanRequest& request);
virtual void GetNextImage(
std::unique_ptr<DBusMethodResponse<GetNextImageResponse>> response,
const GetNextImageRequest& get_next_image_request,
const base::ScopedFD& out_fd);
virtual CancelScanResponse CancelScan(
const CancelScanRequest& cancel_scan_request);
void SetProgressSignalInterval(base::TimeDelta interval);
// Register the callback to call when we send a ScanStatusChanged signal for
// tests.
void SetScanStatusChangedSignalSender(StatusSignalSender sender);
void RemoveDuplicateScanners(std::vector<ScannerInfo>* scanners,
base::flat_set<std::string> seen_vidpid,
base::flat_set<std::string> seen_busdev,
const std::vector<ScannerInfo>& sane_scanners);
// Returns false if a particular scanner model is blocked (e.g. because of
// known backend incompatibilities).
static bool ScannerCanBeUsed(const ScannerInfo& scanner);
private:
friend class ManagerTest;
struct ScanJobState {
std::string device_name;
bool in_use = false;
bool cancelled = false;
std::unique_ptr<SaneDevice> device;
int current_page = 1;
// The total number of pages to scan for the scan job. If this is nullopt,
// keep scanning until we get an error.
std::optional<int> total_pages;
// The image format for scanned images for the scan job.
ImageFormat format;
};
static const char kMetricScanRequested[];
static const char kMetricScanSucceeded[];
static const char kMetricScanFailed[];
static const char kMetricScanFailedFailureReason[];
bool StartScanInternal(brillo::ErrorPtr* error,
ScanFailureMode* failure_mode,
const StartScanRequest& request,
std::unique_ptr<SaneDevice>* device_out);
void GetNextImageInternal(const std::string& uuid,
ScanJobState* scan_state,
base::ScopedFILE out_file);
ScanState RunScanLoop(brillo::ErrorPtr* error,
ScanFailureMode* failure_mode,
ScanJobState* scan_state,
base::ScopedFILE out_file,
const std::string& scan_uuid);
void ReportScanRequested(const std::string& device_name);
void ReportScanSucceeded(const std::string& device_name);
void ReportScanFailed(const std::string& device_name,
const ScanFailureMode failure_mode);
void SendStatusSignal(const std::string& uuid,
const ScanState state,
const int page,
const int progress,
const bool more_pages);
void SendCancelledSignal(const std::string& uuid);
void SendFailureSignal(const std::string& uuid,
const std::string& failure_reason,
const ScanFailureMode failure_mode);
SEQUENCE_CHECKER(sequence_checker_);
base::RepeatingCallback<void(base::TimeDelta)> activity_callback_
GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<MetricsLibraryInterface> metrics_library_
GUARDED_BY_CONTEXT(sequence_checker_);
// Manages port access for receiving replies from network scanners.
// Not owned.
FirewallManager* firewall_manager_ GUARDED_BY_CONTEXT(sequence_checker_);
// Manages connection to SANE for listing and connecting to scanners.
// Not owned.
SaneClient* sane_client_ GUARDED_BY_CONTEXT(sequence_checker_);
// A callback to call when we attempt to send a D-Bus signal. This is used
// for testing in order to track the signals sent from StartScan.
StatusSignalSender status_signal_sender_;
base::TimeDelta progress_signal_interval_;
// Mapping from scan UUIDs to the state for that scan job.
base::flat_map<std::string, ScanJobState> active_scans_
GUARDED_BY_CONTEXT(sequence_checker_);
// Keep as the last member variable.
base::WeakPtrFactory<Manager> weak_factory_
GUARDED_BY_CONTEXT(sequence_checker_){this};
};
} // namespace lorgnette
#endif // LORGNETTE_MANAGER_H_