Commit 76152eea authored by Jesse Schettler's avatar Jesse Schettler Committed by Commit Bot

scanning: Create LorgnetteScannerManager

Create the LorgnetteScannerManager to manage all available scanners in
Chrome OS. Clients can request the names of available scanners and use
them to perform scans.

The manager obtains available scanners using a ZeroconfScannerDetector
and the lorgnette D-Bus service. It deduplicates the scanners before
giving their names to clients and then uses the lorgnette D-Bus service
to perform scans.

Bug: b:153541027
Change-Id: I4e93ee7a97e3c06ec8b6390db79997c1441eac7f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2318310Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797901}
parent 95555558
...@@ -2419,6 +2419,12 @@ source_set("chromeos") { ...@@ -2419,6 +2419,12 @@ source_set("chromeos") {
"remote_apps/remote_apps_model.cc", "remote_apps/remote_apps_model.cc",
"remote_apps/remote_apps_model.h", "remote_apps/remote_apps_model.h",
"reset/metrics.h", "reset/metrics.h",
"scanning/lorgnette_scanner_manager.cc",
"scanning/lorgnette_scanner_manager.h",
"scanning/lorgnette_scanner_manager_factory.cc",
"scanning/lorgnette_scanner_manager_factory.h",
"scanning/lorgnette_scanner_manager_util.cc",
"scanning/lorgnette_scanner_manager_util.h",
"scanning/scanner_detector.h", "scanning/scanner_detector.h",
"scanning/zeroconf_scanner_detector.cc", "scanning/zeroconf_scanner_detector.cc",
"scanning/zeroconf_scanner_detector.h", "scanning/zeroconf_scanner_detector.h",
...@@ -3465,6 +3471,8 @@ source_set("unit_tests") { ...@@ -3465,6 +3471,8 @@ source_set("unit_tests") {
"release_notes/release_notes_notification_unittest.cc", "release_notes/release_notes_notification_unittest.cc",
"release_notes/release_notes_storage_unittest.cc", "release_notes/release_notes_storage_unittest.cc",
"remote_apps/remote_apps_model_unittest.cc", "remote_apps/remote_apps_model_unittest.cc",
"scanning/lorgnette_scanner_manager_unittest.cc",
"scanning/lorgnette_scanner_manager_util_unittest.cc",
"scanning/zeroconf_scanner_detector_unittest.cc", "scanning/zeroconf_scanner_detector_unittest.cc",
"scheduler_configuration_manager_unittest.cc", "scheduler_configuration_manager_unittest.cc",
"session_length_limiter_unittest.cc", "session_length_limiter_unittest.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_util.h"
#include "chrome/browser/chromeos/scanning/zeroconf_scanner_detector.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
#include "chromeos/dbus/lorgnette_manager_client.h"
#include "chromeos/scanning/scanner.h"
#include "net/base/ip_address.h"
namespace chromeos {
namespace {
// Returns a pointer to LorgnetteManagerClient, which is used to detect and
// interact with scanners via the lorgnette D-Bus service.
LorgnetteManagerClient* GetLorgnetteManagerClient() {
DCHECK(DBusThreadManager::IsInitialized());
return DBusThreadManager::Get()->GetLorgnetteManagerClient();
}
// Returns the first usable device name corresponding to the highest priority
// protocol. Returns an empty string if no usable device name is found.
std::string GetUsableDeviceName(const Scanner& scanner) {
const std::vector<ScanProtocol> prioritized_protocols{
ScanProtocol::kEscls, ScanProtocol::kEscl, ScanProtocol::kLegacyNetwork,
ScanProtocol::kLegacyUsb};
for (const auto& protocol : prioritized_protocols) {
const auto it = scanner.device_names.find(protocol);
if (it != scanner.device_names.end()) {
for (const ScannerDeviceName& device_name : it->second) {
if (device_name.usable)
return device_name.device_name;
}
}
}
return "";
}
class LorgnetteScannerManagerImpl final : public LorgnetteScannerManager {
public:
LorgnetteScannerManagerImpl(
std::unique_ptr<ZeroconfScannerDetector> zeroconf_scanner_detector)
: zeroconf_scanner_detector_(std::move(zeroconf_scanner_detector)) {
zeroconf_scanner_detector_->RegisterScannersDetectedCallback(
base::BindRepeating(&LorgnetteScannerManagerImpl::OnScannersDetected,
weak_ptr_factory_.GetWeakPtr()));
OnScannersDetected(zeroconf_scanner_detector_->GetScanners());
}
~LorgnetteScannerManagerImpl() override = default;
// KeyedService:
void Shutdown() override { weak_ptr_factory_.InvalidateWeakPtrs(); }
// LorgnetteScannerManager:
void GetScannerNames(GetScannerNamesCallback callback) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
GetLorgnetteManagerClient()->ListScanners(
base::BindOnce(&LorgnetteScannerManagerImpl::OnListScannersResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
// LorgnetteScannerManager:
void Scan(const std::string& scanner_name,
const LorgnetteManagerClient::ScanProperties& scan_properties,
ScanCallback callback) override {
const auto it = deduped_scanners_.find(scanner_name);
if (it == deduped_scanners_.end()) {
LOG(ERROR) << "Failed to find scanner with name " << scanner_name;
std::move(callback).Run(base::nullopt);
return;
}
const std::string device_name = GetUsableDeviceName(it->second);
if (device_name.empty()) {
LOG(ERROR) << "Failed to find usable device name for " << scanner_name;
std::move(callback).Run(base::nullopt);
return;
}
GetLorgnetteManagerClient()->StartScan(
device_name, scan_properties,
base::BindOnce(
&LorgnetteScannerManagerImpl::OnScanImageToStringResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::nullopt);
}
private:
// Called when scanners are detected by a ScannerDetector.
void OnScannersDetected(std::vector<Scanner> scanners) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
zeroconf_scanners_ = scanners;
}
// Handles the result of calling LorgnetteManagerClient::ListScanners().
void OnListScannersResponse(
GetScannerNamesCallback callback,
base::Optional<lorgnette::ListScannersResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
RebuildDedupedScanners(response);
std::vector<std::string> scanner_names;
scanner_names.reserve(deduped_scanners_.size());
for (const auto& entry : deduped_scanners_)
scanner_names.push_back(entry.first);
std::move(callback).Run(std::move(scanner_names));
}
// Handles the result of calling LorgnetteManagerClient::ScanImageToString().
void OnScanImageToStringResponse(ScanCallback callback,
base::Optional<std::string> scan_data) {
std::move(callback).Run(scan_data);
}
// Uses |response| and zeroconf_scanners_ to rebuild deduped_scanners_.
void RebuildDedupedScanners(
base::Optional<lorgnette::ListScannersResponse> response) {
ResetDedupedScanners();
if (!response || response->scanners_size() == 0)
return;
// Iterate through each lorgnette scanner and add its info to an existing
// Scanner if it has a matching IP address. Otherwise, create a new Scanner
// for the lorgnette scanner.
base::flat_map<net::IPAddress, Scanner*> known_ip_addresses =
GetKnownIpAddresses();
for (const auto& lorgnette_scanner : response->scanners()) {
std::string ip_address_str;
ScanProtocol protocol = ScanProtocol::kUnknown;
ParseScannerName(lorgnette_scanner.name(), ip_address_str, protocol);
if (!ip_address_str.empty()) {
net::IPAddress ip_address;
if (ip_address.AssignFromIPLiteral(ip_address_str)) {
const auto it = known_ip_addresses.find(ip_address);
if (it != known_ip_addresses.end()) {
it->second->device_names[protocol].emplace(
lorgnette_scanner.name());
continue;
}
}
}
const bool is_usb_scanner = protocol == ScanProtocol::kLegacyUsb;
const std::string base_name = base::StringPrintf(
"%s %s%s", lorgnette_scanner.manufacturer().c_str(),
lorgnette_scanner.model().c_str(), is_usb_scanner ? " (USB)" : "");
const std::string display_name = CreateUniqueDisplayName(base_name);
Scanner scanner;
scanner.display_name = display_name;
scanner.device_names[protocol].emplace(lorgnette_scanner.name());
deduped_scanners_[display_name] = scanner;
}
}
// Resets |deduped_scanners_| by clearing it and repopulating it with
// zeroconf_scanners_.
void ResetDedupedScanners() {
deduped_scanners_.clear();
deduped_scanners_.reserve(zeroconf_scanners_.size());
for (const auto& scanner : zeroconf_scanners_)
deduped_scanners_[scanner.display_name] = scanner;
}
// Returns a map of IP addresses to the scanners they correspond to in
// deduped_scanners_. This enables deduplication of network scanners by making
// it easy to check for and modify them using their IP addresses.
base::flat_map<net::IPAddress, Scanner*> GetKnownIpAddresses() {
base::flat_map<net::IPAddress, Scanner*> known_ip_addresses;
for (auto& entry : deduped_scanners_) {
for (const auto& ip_address : entry.second.ip_addresses)
known_ip_addresses[ip_address] = &entry.second;
}
return known_ip_addresses;
}
// Creates a unique display name by appending a copy number to a duplicate
// name (e.g. if Scanner Name already exists, the second instance will be
// renamed Scanner Name (1)).
std::string CreateUniqueDisplayName(const std::string& base_name) {
std::string display_name = base_name;
int i = 1; // The first duplicate will become "Scanner Name (1)."
while (deduped_scanners_.find(display_name) != deduped_scanners_.end()) {
display_name = base::StringPrintf("%s (%d)", base_name.c_str(), i);
i++;
}
return display_name;
}
// Used to detect zeroconf scanners.
std::unique_ptr<ZeroconfScannerDetector> zeroconf_scanner_detector_;
// The deduplicated zeroconf scanners reported by the
// zeroconf_scanner_detector_.
std::vector<Scanner> zeroconf_scanners_;
// Stores the deduplicated scanners from all sources in a map of display name
// to Scanner. Clients are given display names and can use them to interact
// with the corresponding scanners.
base::flat_map<std::string, Scanner> deduped_scanners_;
SEQUENCE_CHECKER(sequence_);
base::WeakPtrFactory<LorgnetteScannerManagerImpl> weak_ptr_factory_{this};
};
} // namespace
// static
std::unique_ptr<LorgnetteScannerManager> LorgnetteScannerManager::Create(
std::unique_ptr<ZeroconfScannerDetector> zeroconf_scanner_detector) {
return std::make_unique<LorgnetteScannerManagerImpl>(
std::move(zeroconf_scanner_detector));
}
} // namespace chromeos
// Copyright 2020 The Chromium 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 CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/optional.h"
#include "chromeos/dbus/lorgnette_manager_client.h"
#include "components/keyed_service/core/keyed_service.h"
namespace chromeos {
class ZeroconfScannerDetector;
// Top-level manager of available scanners in Chrome OS. All functions in this
// class must be called from a sequenced context.
class LorgnetteScannerManager : public KeyedService {
public:
using GetScannerNamesCallback =
base::OnceCallback<void(std::vector<std::string> scanner_names)>;
using ScanCallback =
base::OnceCallback<void(base::Optional<std::string> scan_data)>;
~LorgnetteScannerManager() override = default;
static std::unique_ptr<LorgnetteScannerManager> Create(
std::unique_ptr<ZeroconfScannerDetector> zeroconf_scanner_detector);
// Returns the names of all available, deduplicated scanners.
virtual void GetScannerNames(GetScannerNamesCallback callback) = 0;
// Performs a scan with the scanner specified by |scanner_name| using the
// given |scan_properties|. If |scanner_name| does not correspond to a known
// scanner, base::nullopt is returned in the callback.
virtual void Scan(
const std::string& scanner_name,
const LorgnetteManagerClient::ScanProperties& scan_properties,
ScanCallback callback) = 0;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_factory.h"
#include "base/memory/singleton.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h"
#include "chrome/browser/chromeos/scanning/zeroconf_scanner_detector.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
namespace chromeos {
// static
LorgnetteScannerManager* LorgnetteScannerManagerFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<LorgnetteScannerManager*>(
LorgnetteScannerManagerFactory::GetInstance()
->GetServiceForBrowserContext(context, /*create=*/true));
}
// static
LorgnetteScannerManagerFactory* LorgnetteScannerManagerFactory::GetInstance() {
return base::Singleton<LorgnetteScannerManagerFactory>::get();
}
LorgnetteScannerManagerFactory::LorgnetteScannerManagerFactory()
: BrowserContextKeyedServiceFactory(
"LorgnetteScannerManager",
BrowserContextDependencyManager::GetInstance()) {}
LorgnetteScannerManagerFactory::~LorgnetteScannerManagerFactory() = default;
KeyedService* LorgnetteScannerManagerFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
// Prevent an instance of LorgnetteScannerManager from being created on the
// lock screen.
Profile* profile = Profile::FromBrowserContext(context);
if (ProfileHelper::IsLockScreenAppProfile(profile) ||
ProfileHelper::IsSigninProfile(profile)) {
return nullptr;
}
return LorgnetteScannerManager::Create(ZeroconfScannerDetector::Create())
.release();
}
bool LorgnetteScannerManagerFactory::ServiceIsCreatedWithBrowserContext()
const {
return true;
}
bool LorgnetteScannerManagerFactory::ServiceIsNULLWhileTesting() const {
return true;
}
} // namespace chromeos
// Copyright 2020 The Chromium 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 CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_FACTORY_H_
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
}
namespace content {
class BrowserContext;
}
namespace chromeos {
class LorgnetteScannerManager;
// Factory for LorgnetteScannerManager.
class LorgnetteScannerManagerFactory
: public BrowserContextKeyedServiceFactory {
public:
static LorgnetteScannerManager* GetForBrowserContext(
content::BrowserContext* context);
static LorgnetteScannerManagerFactory* GetInstance();
private:
friend struct base::DefaultSingletonTraits<LorgnetteScannerManagerFactory>;
LorgnetteScannerManagerFactory();
~LorgnetteScannerManagerFactory() override;
LorgnetteScannerManagerFactory(const LorgnetteScannerManagerFactory&) =
delete;
LorgnetteScannerManagerFactory& operator=(
const LorgnetteScannerManagerFactory&) = delete;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
bool ServiceIsCreatedWithBrowserContext() const override;
bool ServiceIsNULLWhileTesting() const override;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_FACTORY_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_util.h"
#include "third_party/re2/src/re2/re2.h"
namespace chromeos {
namespace {
// Regular expressions used to determine whether a device name contains an IPv4
// address or URL.
constexpr char kIpv4Pattern[] = R"((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))";
constexpr char kUrlPattern[] = R"((://))";
} // namespace
void ParseScannerName(const std::string& scanner_name,
std::string& ip_address_out,
ScanProtocol& protocol_out) {
if (RE2::PartialMatch(scanner_name, kIpv4Pattern, &ip_address_out) ||
RE2::PartialMatch(scanner_name, kUrlPattern)) {
protocol_out = ScanProtocol::kLegacyNetwork;
return;
}
protocol_out = ScanProtocol::kLegacyUsb;
}
} // namespace chromeos
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Utility functions for the LorgnetteScannerManager.
#ifndef CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_UTIL_H_
#define CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_UTIL_H_
#include <string>
#include "chromeos/scanning/scanner.h"
namespace chromeos {
// Attempts to parse |scanner_name| to find an IP address and determine the scan
// protocol it corresponds to. If an IP address is found, it is returned in
// |ip_address_out|.
void ParseScannerName(const std::string& scanner_name,
std::string& ip_address_out,
ScanProtocol& protocol_out);
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_UTIL_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_util.h"
#include <string>
#include "chromeos/scanning/scanner.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
// Test that parsing a scanner name with an IP address successfully extracts the
// IP address and sets the protocol to kLegacyNetwork.
TEST(LorgnetteScannerManagerUtilTest, ParseNameWithIPAddress) {
const std::string scanner_name = "test:MX3100_192.168.0.3";
std::string ip_address;
ScanProtocol protocol;
ParseScannerName(scanner_name, ip_address, protocol);
EXPECT_EQ(ip_address, "192.168.0.3");
EXPECT_EQ(protocol, ScanProtocol::kLegacyNetwork);
}
// Test that parsing a scanner name with a URL successfully sets the protocol to
// kLegacyNetwork.
TEST(LorgnetteScannerManagerUtilTest, ParseNameWithUrl) {
const std::string scanner_name = "http://testscanner.domain.org";
std::string ip_address;
ScanProtocol protocol;
ParseScannerName(scanner_name, ip_address, protocol);
EXPECT_TRUE(ip_address.empty());
EXPECT_EQ(protocol, ScanProtocol::kLegacyNetwork);
}
// Test that parsing a scanner name without an IP address or URL successfully
// sets the protocol to kLegacyUsb.
TEST(LorgnetteScannerManagerUtilTest, ParseNameWithVidPid) {
const std::string scanner_name = "test:04A91752_94370B";
std::string ip_address;
ScanProtocol protocol;
ParseScannerName(scanner_name, ip_address, protocol);
EXPECT_TRUE(ip_address.empty());
EXPECT_EQ(protocol, ScanProtocol::kLegacyUsb);
}
} // namespace chromeos
...@@ -32,7 +32,7 @@ class CHROMEOS_EXPORT ScannerDetector { ...@@ -32,7 +32,7 @@ class CHROMEOS_EXPORT ScannerDetector {
// Registers the callback used to provide notifications when scanners are // Registers the callback used to provide notifications when scanners are
// detected. // detected.
using OnScannersDetectedCallback = using OnScannersDetectedCallback =
base::RepeatingCallback<void(const std::vector<Scanner>& scanners)>; base::RepeatingCallback<void(std::vector<Scanner> scanners)>;
virtual void RegisterScannersDetectedCallback( virtual void RegisterScannersDetectedCallback(
OnScannersDetectedCallback callback) = 0; OnScannersDetectedCallback callback) = 0;
......
...@@ -169,8 +169,8 @@ class ZeroconfScannerDetectorTest : public testing::Test { ...@@ -169,8 +169,8 @@ class ZeroconfScannerDetectorTest : public testing::Test {
} }
// ScannerDetector callback. // ScannerDetector callback.
void OnScannersDetected(const std::vector<Scanner>& scanners) { void OnScannersDetected(std::vector<Scanner> scanners) {
scanners_ = scanners; scanners_ = std::move(scanners);
} }
protected: protected:
......
...@@ -67,7 +67,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner( ...@@ -67,7 +67,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner(
const std::string& service_type, const std::string& service_type,
const std::string& rs, const std::string& rs,
const net::IPAddress& ip_address, const net::IPAddress& ip_address,
int port) { int port,
bool usable) {
std::string scheme; std::string scheme;
ScanProtocol protocol = ScanProtocol::kUnknown; ScanProtocol protocol = ScanProtocol::kUnknown;
SetSchemeAndProtocol(service_type, scheme, protocol); SetSchemeAndProtocol(service_type, scheme, protocol);
...@@ -78,7 +79,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner( ...@@ -78,7 +79,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner(
Scanner scanner; Scanner scanner;
scanner.display_name = name; scanner.display_name = name;
scanner.device_names[protocol].insert(ScannerDeviceName(device_name)); scanner.device_names[protocol].emplace(
ScannerDeviceName(device_name, usable));
scanner.ip_addresses.insert(ip_address); scanner.ip_addresses.insert(ip_address);
return scanner; return scanner;
} }
......
...@@ -26,7 +26,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner( ...@@ -26,7 +26,8 @@ base::Optional<Scanner> CreateSaneAirscanScanner(
const std::string& service_type, const std::string& service_type,
const std::string& rs, const std::string& rs,
const net::IPAddress& ip_address, const net::IPAddress& ip_address,
int port); int port,
bool usable = true);
} // namespace chromeos } // namespace chromeos
......
...@@ -9,6 +9,10 @@ namespace chromeos { ...@@ -9,6 +9,10 @@ namespace chromeos {
ScannerDeviceName::ScannerDeviceName(const std::string& device_name) ScannerDeviceName::ScannerDeviceName(const std::string& device_name)
: device_name(device_name) {} : device_name(device_name) {}
ScannerDeviceName::ScannerDeviceName(const std::string& device_name,
bool usable)
: device_name(device_name), usable(usable) {}
ScannerDeviceName::~ScannerDeviceName() = default; ScannerDeviceName::~ScannerDeviceName() = default;
ScannerDeviceName::ScannerDeviceName(const ScannerDeviceName& other) = default; ScannerDeviceName::ScannerDeviceName(const ScannerDeviceName& other) = default;
......
...@@ -25,6 +25,7 @@ enum class CHROMEOS_EXPORT ScanProtocol { ...@@ -25,6 +25,7 @@ enum class CHROMEOS_EXPORT ScanProtocol {
struct CHROMEOS_EXPORT ScannerDeviceName { struct CHROMEOS_EXPORT ScannerDeviceName {
explicit ScannerDeviceName(const std::string& device_name); explicit ScannerDeviceName(const std::string& device_name);
ScannerDeviceName(const std::string& device_name, bool usable);
~ScannerDeviceName(); ~ScannerDeviceName();
ScannerDeviceName(const ScannerDeviceName& scanner_device_name); ScannerDeviceName(const ScannerDeviceName& scanner_device_name);
...@@ -56,7 +57,7 @@ struct CHROMEOS_EXPORT Scanner { ...@@ -56,7 +57,7 @@ struct CHROMEOS_EXPORT Scanner {
// Map of ScanProtocol to a set of corresponding ScannerDeviceNames that can // Map of ScanProtocol to a set of corresponding ScannerDeviceNames that can
// be used with the lorgnette D-Bus service. Clients are responsible for // be used with the lorgnette D-Bus service. Clients are responsible for
// selecting which device name to use. // selecting which device name to use.
base::flat_map<ScanProtocol, std::set<ScannerDeviceName>> device_names; base::flat_map<ScanProtocol, base::flat_set<ScannerDeviceName>> device_names;
// Known IP addresses for this scanner. Used to deduplicate network scanners // Known IP addresses for this scanner. Used to deduplicate network scanners
// from multiple sources. // from multiple sources.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment