| // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| // 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 <string> |
| #include <vector> |
| |
| #include <base/callback.h> |
| #include <base/callback_helpers.h> |
| #include <base/containers/flat_map.h> |
| #include <base/containers/flat_set.h> |
| #include <base/files/scoped_file.h> |
| #include <base/memory/weak_ptr.h> |
| #include <base/optional.h> |
| #include <base/synchronization/lock.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 { |
| |
| 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 org::chromium::lorgnette::ManagerAdaptor, |
| public org::chromium::lorgnette::ManagerInterface { |
| public: |
| Manager(base::Callback<void()> activity_callback, |
| std::unique_ptr<SaneClient> sane_client); |
| Manager(const Manager&) = delete; |
| Manager& operator=(const Manager&) = delete; |
| virtual ~Manager(); |
| |
| void RegisterAsync(brillo::dbus_utils::ExportedObjectManager* object_manager, |
| brillo::dbus_utils::AsyncEventSequencer* sequencer); |
| |
| // Implementation of MethodInterface. |
| bool ListScanners(brillo::ErrorPtr* error, |
| std::vector<uint8_t>* scanner_list_out) override; |
| bool GetScannerCapabilities(brillo::ErrorPtr* error, |
| const std::string& device_name, |
| std::vector<uint8_t>* capabilities) override; |
| std::vector<uint8_t> StartScan( |
| const std::vector<uint8_t>& start_scan_request) override; |
| void GetNextImage( |
| std::unique_ptr<DBusMethodResponse<std::vector<uint8_t>>> response, |
| const std::vector<uint8_t>& get_next_image_request, |
| const base::ScopedFD& out_fd) override; |
| std::vector<uint8_t> CancelScan( |
| const std::vector<uint8_t>& cancel_scan_request) override; |
| |
| void SetProgressSignalInterval(base::TimeDelta interval); |
| |
| // Register the callback to call when we send a ScanStatusChanged signal for |
| // tests. |
| void SetScanStatusChangedSignalSenderForTest(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); |
| |
| 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. |
| base::Optional<int> total_pages; |
| }; |
| |
| static const char kMetricScanRequested[]; |
| static const char kMetricScanSucceeded[]; |
| static const char kMetricScanFailed[]; |
| |
| bool StartScanInternal(brillo::ErrorPtr* error, |
| 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, |
| 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); |
| |
| void SendStatusSignal(std::string uuid, |
| ScanState state, |
| int page, |
| int progress, |
| bool more_pages); |
| void SendCancelledSignal(std::string uuid); |
| void SendFailureSignal(std::string uuid, std::string failure_reason); |
| |
| std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_; |
| base::Callback<void()> activity_callback_; |
| std::unique_ptr<MetricsLibraryInterface> metrics_library_; |
| |
| // Manages port access for receiving replies from network scanners. |
| std::unique_ptr<FirewallManager> firewall_manager_; |
| |
| // Manages connection to SANE for listing and connecting to scanners. |
| std::unique_ptr<SaneClient> sane_client_; |
| |
| // 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_; |
| |
| base::Lock active_scans_lock_; |
| // Mapping from scan UUIDs to the state for that scan job. |
| base::flat_map<std::string, ScanJobState> active_scans_; |
| |
| // Keep as the last member variable. |
| base::WeakPtrFactory<Manager> weak_factory_{this}; |
| }; |
| |
| } // namespace lorgnette |
| |
| #endif // LORGNETTE_MANAGER_H_ |