#include "chromeos/printing/ppd_metadata_manager.h"
#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/containers/span.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chromeos/printing/ppd_metadata_parser.h"
#include "chromeos/printing/ppd_provider.h"
#include "chromeos/printing/printer_config_cache.h"
#include "ppd_metadata_manager.h"
namespace chromeos {
namespace {
constexpr int kNumShards = 20;
constexpr int kSixteenBitsMaximum = 0xffff;
template <typename T>
struct ParsedMetadataWithTimestamp {
base::Time time_of_parse;
T value;
};
class ForwardIndexSearchContext {
public:
ForwardIndexSearchContext(
const std::vector<std::string>& emms,
base::Time max_age,
PpdMetadataManager::FindAllEmmsAvailableInIndexCallback cb)
: emms_(emms), current_index_(), max_age_(max_age), cb_(std::move(cb)) {}
~ForwardIndexSearchContext() = default;
ForwardIndexSearchContext(const ForwardIndexSearchContext&) = delete;
ForwardIndexSearchContext& operator=(const ForwardIndexSearchContext&) =
delete;
ForwardIndexSearchContext(ForwardIndexSearchContext&&) = default;
std::string_view CurrentEmm() const {
DCHECK_LT(current_index_, emms_.size());
return emms_[current_index_];
}
bool CurrentEmmIsLast() const {
DCHECK_LT(current_index_, emms_.size());
return current_index_ + 1 == emms_.size();
}
void AdvanceToNextEmm() {
DCHECK_LT(current_index_, emms_.size());
current_index_++;
}
void PostCallback() {
DCHECK(CurrentEmmIsLast());
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb_), cb_arg_));
}
void AddDataFromForwardIndexForCurrentEmm(const ParsedIndexValues& value) {
cb_arg_.insert_or_assign(CurrentEmm(), value);
}
base::Time MaxAge() const { return max_age_; }
private:
std::vector<std::string> emms_;
size_t current_index_;
base::Time max_age_;
PpdMetadataManager::FindAllEmmsAvailableInIndexCallback cb_;
base::flat_map<std::string, ParsedIndexValues> cb_arg_;
};
class ForwardIndexSearchQueue {
public:
ForwardIndexSearchQueue() = default;
~ForwardIndexSearchQueue() = default;
ForwardIndexSearchQueue(const ForwardIndexSearchQueue&) = delete;
ForwardIndexSearchQueue& operator=(const ForwardIndexSearchQueue&) = delete;
void Enqueue(ForwardIndexSearchContext context) {
contexts_.push(std::move(context));
}
bool IsIdle() const { return contexts_.empty(); }
ForwardIndexSearchContext& CurrentContext() {
DCHECK(!IsIdle());
return contexts_.front();
}
void AdvanceToNextEmm() {
DCHECK(!IsIdle());
if (CurrentContext().CurrentEmmIsLast()) {
CurrentContext().PostCallback();
contexts_.pop();
} else {
CurrentContext().AdvanceToNextEmm();
}
}
private:
base::queue<ForwardIndexSearchContext> contexts_;
};
template <typename T>
using CachedParsedMetadataMap =
base::flat_map<std::string, ParsedMetadataWithTimestamp<T>>;
template <typename T>
bool MapHasValueFresherThan(const CachedParsedMetadataMap<T>& metadata_map,
std::string_view key,
base::Time expiration) {
if (auto it = metadata_map.find(key); it != metadata_map.end()) {
const auto& value = it->second;
return value.time_of_parse > expiration;
}
return false;
}
int IndexShard(std::string_view key) {
unsigned int hash = 5381;
for (char c : key) {
hash = hash * 33 + c;
}
return hash % kNumShards;
}
class PpdMetadataPathSpecifier {
public:
enum class Type {
kManufacturers,
kPrinters,
kForwardIndex,
kReverseIndex,
kUsbIndex,
kUsbVendorIds,
};
PpdMetadataPathSpecifier(Type type, PpdIndexChannel channel)
: type_(type),
channel_(channel),
printers_basename_(nullptr),
shard_(0),
usb_vendor_id_(0) {}
~PpdMetadataPathSpecifier() = default;
PpdMetadataPathSpecifier(const PpdMetadataPathSpecifier&) = delete;
PpdMetadataPathSpecifier& operator=(const PpdMetadataPathSpecifier&) = delete;
void SetPrintersBasename(const char* const basename) {
DCHECK_EQ(type_, Type::kPrinters);
printers_basename_ = basename;
}
void SetUsbVendorId(const int vendor_id) {
DCHECK_EQ(type_, Type::kUsbIndex);
usb_vendor_id_ = vendor_id;
}
void SetShard(const int shard) {
DCHECK(type_ == Type::kForwardIndex || type_ == Type::kReverseIndex);
shard_ = shard;
}
std::string AsString() const {
switch (type_) {
case Type::kManufacturers:
return base::StringPrintf("%s/manufacturers-en.json",
MetadataParentDirectory());
case Type::kPrinters:
DCHECK(printers_basename_);
DCHECK(!std::string_view(printers_basename_).empty());
return base::StringPrintf("%s/%s", MetadataParentDirectory(),
printers_basename_);
case Type::kForwardIndex:
DCHECK(shard_ >= 0 && shard_ < kNumShards);
return base::StringPrintf("%s/index-%02d.json",
MetadataParentDirectory(), shard_);
case Type::kReverseIndex:
DCHECK(shard_ >= 0 && shard_ < kNumShards);
return base::StringPrintf("%s/reverse_index-en-%02d.json",
MetadataParentDirectory(), shard_);
case Type::kUsbIndex:
DCHECK(usb_vendor_id_ >= 0 && usb_vendor_id_ <= kSixteenBitsMaximum);
return base::StringPrintf("%s/usb-%04x.json", MetadataParentDirectory(),
usb_vendor_id_);
case Type::kUsbVendorIds:
return base::StringPrintf("%s/usb_vendor_ids.json",
MetadataParentDirectory());
}
NOTREACHED();
}
private:
const char* MetadataParentDirectory() const {
switch (channel_) {
case PpdIndexChannel::kLocalhost:
[[fallthrough]];
case PpdIndexChannel::kProduction:
return "metadata_v3";
case PpdIndexChannel::kStaging:
return "metadata_v3_staging";
case PpdIndexChannel::kDev:
return "metadata_v3_dev";
}
}
Type type_;
const PpdIndexChannel channel_;
const char* printers_basename_;
int shard_;
int usb_vendor_id_;
};
class PpdMetadataManagerImpl : public PpdMetadataManager {
public:
PpdMetadataManagerImpl(PpdIndexChannel channel,
base::Clock* clock,
std::unique_ptr<PrinterConfigCache> config_cache)
: channel_(channel),
clock_(clock),
config_cache_(std::move(config_cache)),
weak_factory_(this) {}
~PpdMetadataManagerImpl() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void GetManufacturers(base::TimeDelta age,
PpdProvider::ResolveManufacturersCallback cb) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PpdMetadataPathSpecifier path(
PpdMetadataPathSpecifier::Type::kManufacturers, channel_);
const std::string metadata_name = path.AsString();
if (MapHasValueFresherThan(cached_manufacturers_, metadata_name,
clock_->Now() - age)) {
OnManufacturersAvailable(metadata_name, std::move(cb));
return;
}
PrinterConfigCache::FetchCallback fetch_cb =
base::BindOnce(&PpdMetadataManagerImpl::OnManufacturersFetched,
weak_factory_.GetWeakPtr(), std::move(cb));
config_cache_->Fetch(metadata_name, age, std::move(fetch_cb));
}
void GetPrinters(std::string_view manufacturer,
base::TimeDelta age,
GetPrintersCallback cb) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const auto metadata_name = GetPrintersMetadataName(manufacturer);
if (!metadata_name.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), false, ParsedPrinters{}));
return;
}
if (MapHasValueFresherThan(cached_printers_, metadata_name.value(),
clock_->Now() - age)) {
OnPrintersAvailable(metadata_name.value(), std::move(cb));
return;
}
PrinterConfigCache::FetchCallback fetch_cb =
base::BindOnce(&PpdMetadataManagerImpl::OnPrintersFetched,
weak_factory_.GetWeakPtr(), std::move(cb));
config_cache_->Fetch(metadata_name.value(), age, std::move(fetch_cb));
}
void FindAllEmmsAvailableInIndex(
const std::vector<std::string>& emms,
base::TimeDelta age,
FindAllEmmsAvailableInIndexCallback cb) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ForwardIndexSearchContext context(emms, clock_->Now() - age, std::move(cb));
bool queue_was_idle = forward_index_search_queue_.IsIdle();
forward_index_search_queue_.Enqueue(std::move(context));
if (queue_was_idle) {
ContinueSearchingForwardIndices();
}
}
void FindDeviceInUsbIndex(int vendor_id,
int product_id,
base::TimeDelta age,
FindDeviceInUsbIndexCallback cb) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (vendor_id < 0 || vendor_id > kSixteenBitsMaximum || product_id < 0 ||
product_id > kSixteenBitsMaximum) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), std::string()));
return;
}
PpdMetadataPathSpecifier path(PpdMetadataPathSpecifier::Type::kUsbIndex,
channel_);
path.SetUsbVendorId(vendor_id);
const std::string metadata_name = path.AsString();
if (MapHasValueFresherThan(cached_usb_indices_, metadata_name,
clock_->Now() - age)) {
OnUsbIndexAvailable(metadata_name, product_id, std::move(cb));
return;
}
auto callback = base::BindOnce(&PpdMetadataManagerImpl::OnUsbIndexFetched,
weak_factory_.GetWeakPtr(), metadata_name,
product_id, std::move(cb));
config_cache_->Fetch(metadata_name, age, std::move(callback));
}
void GetUsbManufacturerName(int vendor_id,
base::TimeDelta age,
GetUsbManufacturerNameCallback cb) override {
PpdMetadataPathSpecifier path(PpdMetadataPathSpecifier::Type::kUsbVendorIds,
channel_);
const std::string metadata_name = path.AsString();
if (MapHasValueFresherThan(cached_usb_vendor_id_map_, metadata_name,
clock_->Now() - age)) {
OnUsbVendorIdMapAvailable(metadata_name, vendor_id, std::move(cb));
return;
}
auto fetch_cb =
base::BindOnce(&PpdMetadataManagerImpl::OnUsbVendorIdMapFetched,
weak_factory_.GetWeakPtr(), vendor_id, std::move(cb));
config_cache_->Fetch(metadata_name, age, std::move(fetch_cb));
}
void SplitMakeAndModel(std::string_view effective_make_and_model,
base::TimeDelta age,
PpdProvider::ReverseLookupCallback cb) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PpdMetadataPathSpecifier path(PpdMetadataPathSpecifier::Type::kReverseIndex,
channel_);
path.SetShard(IndexShard(effective_make_and_model));
const std::string metadata_name = path.AsString();
if (MapHasValueFresherThan(cached_reverse_indices_, metadata_name,
clock_->Now() - age)) {
OnReverseIndexAvailable(metadata_name, effective_make_and_model,
std::move(cb));
return;
}
PrinterConfigCache::FetchCallback fetch_cb =
base::BindOnce(&PpdMetadataManagerImpl::OnReverseIndexFetched,
weak_factory_.GetWeakPtr(),
std::string(effective_make_and_model), std::move(cb));
config_cache_->Fetch(metadata_name, age, std::move(fetch_cb));
}
PrinterConfigCache* GetPrinterConfigCacheForTesting() const override {
return config_cache_.get();
}
bool SetManufacturersForTesting(
std::string_view manufacturers_json) override {
const auto parsed = ParseManufacturers(manufacturers_json);
if (!parsed.has_value()) {
return false;
}
PpdMetadataPathSpecifier path(
PpdMetadataPathSpecifier::Type::kManufacturers, channel_);
const std::string manufacturers_name = path.AsString();
ParsedMetadataWithTimestamp<ParsedManufacturers> value = {clock_->Now(),
parsed.value()};
cached_manufacturers_.insert_or_assign(manufacturers_name, value);
return true;
}
private:
enum class ForwardIndexSearchStatus {
kWillResumeOnFetchCompletion,
kCanContinue,
};
void OnManufacturersAvailable(std::string_view metadata_name,
PpdProvider::ResolveManufacturersCallback cb) {
const auto& parsed_manufacturers = cached_manufacturers_.at(metadata_name);
std::vector<std::string> manufacturers_for_cb;
for (const auto& iter : parsed_manufacturers.value) {
manufacturers_for_cb.push_back(iter.first);
}
std::sort(manufacturers_for_cb.begin(), manufacturers_for_cb.end());
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb), PpdProvider::CallbackResultCode::SUCCESS,
manufacturers_for_cb));
}
void OnManufacturersFetched(PpdProvider::ResolveManufacturersCallback cb,
const PrinterConfigCache::FetchResult& result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!result.succeeded) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb),
PpdProvider::CallbackResultCode::SERVER_ERROR,
std::vector<std::string>{}));
return;
}
const auto parsed = ParseManufacturers(result.contents);
if (!parsed.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb),
PpdProvider::CallbackResultCode::INTERNAL_ERROR,
std::vector<std::string>{}));
return;
}
ParsedMetadataWithTimestamp<ParsedManufacturers> value = {clock_->Now(),
parsed.value()};
cached_manufacturers_.insert_or_assign(result.key, value);
OnManufacturersAvailable(result.key, std::move(cb));
}
std::optional<std::string> GetPrintersMetadataName(
std::string_view manufacturer) {
PpdMetadataPathSpecifier manufacturers_path(
PpdMetadataPathSpecifier::Type::kManufacturers, channel_);
const std::string manufacturers_metadata_name =
manufacturers_path.AsString();
auto cached_manufacturers_it =
cached_manufacturers_.find(manufacturers_metadata_name);
if (cached_manufacturers_it == cached_manufacturers_.end()) {
return std::nullopt;
}
const ParsedMetadataWithTimestamp<ParsedManufacturers>& manufacturers =
cached_manufacturers_it->second;
auto manufacturers_it = manufacturers.value.find(manufacturer);
if (manufacturers_it == manufacturers.value.end()) {
return std::nullopt;
}
PpdMetadataPathSpecifier printers_path(
PpdMetadataPathSpecifier::Type::kPrinters, channel_);
printers_path.SetPrintersBasename(manufacturers_it->second.c_str());
return printers_path.AsString();
}
void OnPrintersAvailable(std::string_view metadata_name,
GetPrintersCallback cb) {
const auto& parsed_printers = cached_printers_.at(metadata_name);
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), true, parsed_printers.value));
}
void OnPrintersFetched(GetPrintersCallback cb,
const PrinterConfigCache::FetchResult& result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!result.succeeded) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), false, ParsedPrinters{}));
return;
}
const auto parsed = ParsePrinters(result.contents);
if (!parsed.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), false, ParsedPrinters{}));
return;
}
ParsedMetadataWithTimestamp<ParsedPrinters> value = {clock_->Now(),
parsed.value()};
cached_printers_.insert_or_assign(result.key, value);
OnPrintersAvailable(result.key, std::move(cb));
}
void FindEmmInForwardIndex(std::string_view metadata_name) {
DCHECK(cached_forward_indices_.contains(metadata_name));
ForwardIndexSearchContext& context =
forward_index_search_queue_.CurrentContext();
const ParsedIndex& index = cached_forward_indices_.at(metadata_name).value;
const auto& iter = index.find(context.CurrentEmm());
if (iter != index.end()) {
context.AddDataFromForwardIndexForCurrentEmm(iter->second);
}
forward_index_search_queue_.AdvanceToNextEmm();
}
void OnForwardIndexFetched(const PrinterConfigCache::FetchResult& result) {
if (!result.succeeded) {
forward_index_search_queue_.AdvanceToNextEmm();
ContinueSearchingForwardIndices();
return;
}
const auto parsed = ParseForwardIndex(result.contents);
if (!parsed.has_value()) {
forward_index_search_queue_.AdvanceToNextEmm();
ContinueSearchingForwardIndices();
return;
}
ParsedMetadataWithTimestamp<ParsedIndex> value = {clock_->Now(),
parsed.value()};
cached_forward_indices_.insert_or_assign(result.key, value);
ContinueSearchingForwardIndices();
}
ForwardIndexSearchStatus SearchForwardIndicesForOneEmm() {
const ForwardIndexSearchContext& context =
forward_index_search_queue_.CurrentContext();
PpdMetadataPathSpecifier path(PpdMetadataPathSpecifier::Type::kForwardIndex,
channel_);
path.SetShard(IndexShard(context.CurrentEmm()));
const std::string forward_index_name = path.AsString();
if (MapHasValueFresherThan(cached_forward_indices_, forward_index_name,
context.MaxAge())) {
FindEmmInForwardIndex(forward_index_name);
return ForwardIndexSearchStatus::kCanContinue;
}
auto callback =
base::BindOnce(&PpdMetadataManagerImpl::OnForwardIndexFetched,
weak_factory_.GetWeakPtr());
config_cache_->Fetch(forward_index_name, clock_->Now() - context.MaxAge(),
std::move(callback));
return ForwardIndexSearchStatus::kWillResumeOnFetchCompletion;
}
void ContinueSearchingForwardIndices() {
while (!forward_index_search_queue_.IsIdle()) {
ForwardIndexSearchStatus status = SearchForwardIndicesForOneEmm();
if (status == ForwardIndexSearchStatus::kWillResumeOnFetchCompletion) {
break;
}
}
}
void OnUsbIndexAvailable(std::string_view metadata_name,
int product_id,
FindDeviceInUsbIndexCallback cb) {
DCHECK(cached_usb_indices_.contains(metadata_name));
const ParsedUsbIndex& usb_index =
cached_usb_indices_.at(metadata_name).value;
const auto& iter = usb_index.find(product_id);
std::string effective_make_and_model;
if (iter != usb_index.end()) {
effective_make_and_model = iter->second;
}
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb), std::move(effective_make_and_model)));
}
void OnUsbIndexFetched(std::string metadata_name,
int product_id,
FindDeviceInUsbIndexCallback cb,
const PrinterConfigCache::FetchResult& fetch_result) {
if (!fetch_result.succeeded) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), std::string()));
return;
}
std::optional<ParsedUsbIndex> parsed = ParseUsbIndex(fetch_result.contents);
if (!parsed.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), std::string()));
return;
}
DCHECK(fetch_result.key == metadata_name);
ParsedMetadataWithTimestamp<ParsedUsbIndex> value = {clock_->Now(),
parsed.value()};
cached_usb_indices_.insert_or_assign(fetch_result.key, value);
OnUsbIndexAvailable(fetch_result.key, product_id, std::move(cb));
}
void OnUsbVendorIdMapAvailable(std::string_view metadata_name,
int vendor_id,
GetUsbManufacturerNameCallback cb) {
DCHECK(cached_usb_vendor_id_map_.contains(metadata_name));
ParsedUsbVendorIdMap usb_vendor_id_map =
cached_usb_vendor_id_map_.at(metadata_name).value;
std::string manufacturer_name;
const auto& iter = usb_vendor_id_map.find(vendor_id);
if (iter != usb_vendor_id_map.end()) {
manufacturer_name = iter->second;
}
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), manufacturer_name));
}
void OnUsbVendorIdMapFetched(
int vendor_id,
GetUsbManufacturerNameCallback cb,
const PrinterConfigCache::FetchResult& fetch_result) {
if (!fetch_result.succeeded) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), std::string()));
return;
}
const std::optional<ParsedUsbVendorIdMap> parsed =
ParseUsbVendorIdMap(fetch_result.contents);
if (!parsed.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cb), std::string()));
return;
}
ParsedMetadataWithTimestamp<ParsedUsbVendorIdMap> value = {clock_->Now(),
parsed.value()};
cached_usb_vendor_id_map_.insert_or_assign(fetch_result.key, value);
OnUsbVendorIdMapAvailable(fetch_result.key, vendor_id, std::move(cb));
}
void OnReverseIndexAvailable(std::string_view metadata_name,
std::string_view effective_make_and_model,
PpdProvider::ReverseLookupCallback cb) {
const auto& parsed_reverse_index =
cached_reverse_indices_.at(metadata_name);
auto it = parsed_reverse_index.value.find(effective_make_and_model);
if (it == parsed_reverse_index.value.end()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb),
PpdProvider::CallbackResultCode::NOT_FOUND, "", ""));
return;
}
const ReverseIndexLeaf& leaf = it->second;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb), PpdProvider::CallbackResultCode::SUCCESS,
leaf.manufacturer, leaf.model));
}
void OnReverseIndexFetched(std::string effective_make_and_model,
PpdProvider::ReverseLookupCallback cb,
const PrinterConfigCache::FetchResult& result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!result.succeeded) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb),
PpdProvider::CallbackResultCode::SERVER_ERROR, "",
""));
return;
}
const auto parsed = ParseReverseIndex(result.contents);
if (!parsed.has_value()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(cb),
PpdProvider::CallbackResultCode::INTERNAL_ERROR, "",
""));
return;
}
ParsedMetadataWithTimestamp<ParsedReverseIndex> value = {clock_->Now(),
parsed.value()};
cached_reverse_indices_.insert_or_assign(result.key, value);
OnReverseIndexAvailable(result.key, effective_make_and_model,
std::move(cb));
}
const PpdIndexChannel channel_;
raw_ptr<const base::Clock> clock_;
std::unique_ptr<PrinterConfigCache> config_cache_;
CachedParsedMetadataMap<ParsedManufacturers> cached_manufacturers_;
CachedParsedMetadataMap<ParsedPrinters> cached_printers_;
CachedParsedMetadataMap<ParsedIndex> cached_forward_indices_;
CachedParsedMetadataMap<ParsedUsbIndex> cached_usb_indices_;
CachedParsedMetadataMap<ParsedUsbVendorIdMap> cached_usb_vendor_id_map_;
CachedParsedMetadataMap<ParsedReverseIndex> cached_reverse_indices_;
ForwardIndexSearchQueue forward_index_search_queue_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PpdMetadataManagerImpl> weak_factory_;
};
}
std::unique_ptr<PpdMetadataManager> PpdMetadataManager::Create(
PpdIndexChannel channel,
base::Clock* clock,
std::unique_ptr<PrinterConfigCache> config_cache) {
return std::make_unique<PpdMetadataManagerImpl>(channel, clock,
std::move(config_cache));
}
}