1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_CHROMEOS_SCANNING_SCAN_SERVICE_H_
6 #define CHROME_BROWSER_CHROMEOS_SCANNING_SCAN_SERVICE_H_
7 
8 #include <cstdint>
9 #include <string>
10 #include <vector>
11 
12 #include "base/containers/flat_map.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/optional.h"
16 #include "base/time/time.h"
17 #include "base/unguessable_token.h"
18 #include "chromeos/components/scanning/mojom/scanning.mojom.h"
19 #include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
20 #include "components/keyed_service/core/keyed_service.h"
21 #include "mojo/public/cpp/bindings/pending_receiver.h"
22 #include "mojo/public/cpp/bindings/pending_remote.h"
23 #include "mojo/public/cpp/bindings/receiver.h"
24 #include "mojo/public/cpp/bindings/remote.h"
25 
26 namespace chromeos {
27 
28 class LorgnetteScannerManager;
29 
30 // Implementation of the chromeos::scanning::mojom::ScanService interface. Used
31 // by the scanning WebUI (chrome://scanning) to get connected scanners, obtain
32 // scanner capabilities, and perform scans.
33 class ScanService : public scanning::mojom::ScanService, public KeyedService {
34  public:
35   ScanService(LorgnetteScannerManager* lorgnette_scanner_manager,
36               base::FilePath my_files_path,
37               base::FilePath google_drive_path);
38   ~ScanService() override;
39 
40   ScanService(const ScanService&) = delete;
41   ScanService& operator=(const ScanService&) = delete;
42 
43   // scanning::mojom::ScanService:
44   void GetScanners(GetScannersCallback callback) override;
45   void GetScannerCapabilities(const base::UnguessableToken& scanner_id,
46                               GetScannerCapabilitiesCallback callback) override;
47   void StartScan(const base::UnguessableToken& scanner_id,
48                  scanning::mojom::ScanSettingsPtr settings,
49                  mojo::PendingRemote<scanning::mojom::ScanJobObserver> observer,
50                  StartScanCallback callback) override;
51 
52   // Binds receiver_ by consuming |pending_receiver|.
53   void BindInterface(
54       mojo::PendingReceiver<scanning::mojom::ScanService> pending_receiver);
55 
56   // Sets |google_drive_path_| for tests.
57   void SetGoogleDrivePathForTesting(const base::FilePath& google_drive_path);
58 
59   // Sets |my_files_path_| for tests.
60   void SetMyFilesPathForTesting(const base::FilePath& my_files_path);
61 
62  private:
63   // KeyedService:
64   void Shutdown() override;
65 
66   // Processes the result of calling LorgnetteScannerManager::GetScannerNames().
67   void OnScannerNamesReceived(GetScannersCallback callback,
68                               std::vector<std::string> scanner_names);
69 
70   // Processes the result of calling
71   // LorgnetteScannerManager::GetScannerCapabilities().
72   void OnScannerCapabilitiesReceived(
73       GetScannerCapabilitiesCallback callback,
74       const base::Optional<lorgnette::ScannerCapabilities>& capabilities);
75 
76   // Receives progress updates after calling LorgnetteScannerManager::Scan().
77   // |page_number| indicates the page the |progress_percent| corresponds to.
78   void OnProgressPercentReceived(uint32_t progress_percent,
79                                  uint32_t page_number);
80 
81   // Processes each |scanned_image| received after calling
82   // LorgnetteScannerManager::Scan(). |scan_to_path| is where images will be
83   // saved, and |file_type| specifies the file type to use when saving scanned
84   // images.
85   void OnPageReceived(const base::FilePath& scan_to_path,
86                       const scanning::mojom::FileType file_type,
87                       std::string scanned_image,
88                       uint32_t page_number);
89 
90   // Processes the final result of calling LorgnetteScannerManager::Scan().
91   void OnScanCompleted(bool success);
92 
93   // TODO(jschettler): Replace this with a generic helper function when one is
94   // available.
95   // Determines whether the service supports saving scanned images to
96   // |file_path|.
97   bool FilePathSupported(const base::FilePath& file_path);
98 
99   // Returns the scanner name corresponding to the given |scanner_id| or an
100   // empty string if the name cannot be found.
101   std::string GetScannerName(const base::UnguessableToken& scanner_id);
102 
103   // Map of scanner IDs to display names. Used to pass the correct display name
104   // to LorgnetteScannerManager when clients provide an ID.
105   base::flat_map<base::UnguessableToken, std::string> scanner_names_;
106 
107   // Receives and dispatches method calls to this implementation of the
108   // chromeos::scanning::mojom::ScanService interface.
109   mojo::Receiver<scanning::mojom::ScanService> receiver_{this};
110 
111   // Used to send scan job events to an observer. The remote is bound when a
112   // scan job is started and is disconnected when the scan job is complete.
113   mojo::Remote<scanning::mojom::ScanJobObserver> scan_job_observer_;
114 
115   // Unowned. Used to get scanner information and perform scans.
116   LorgnetteScannerManager* lorgnette_scanner_manager_;
117 
118   // The paths to the user's My files and Google Drive directories. Used to
119   // determine if a selected file path is supported.
120   base::FilePath my_files_path_;
121   base::FilePath google_drive_path_;
122 
123   // Indicates whether there was a failure to save scanned images.
124   bool save_failed_;
125 
126   // The time a scan was started. Used in filenames when saving scanned images.
127   base::Time::Exploded start_time_;
128 
129   base::WeakPtrFactory<ScanService> weak_ptr_factory_{this};
130 };
131 
132 }  // namespace chromeos
133 
134 #endif  // CHROME_BROWSER_CHROMEOS_SCANNING_SCAN_SERVICE_H_
135