blob: 86933cf2231ed26da6d7e9c3fbc31dc198396a12 [file] [log] [blame]
// Copyright 2019 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/printing/automatic_usb_printer_configurer.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "chrome/browser/chromeos/printing/usb_printer_notification_controller.h"
namespace chromeos {
namespace {
bool IsPrinterIdInList(const std::string& printer_id,
const std::vector<Printer>& printer_list) {
for (const auto& printer : printer_list) {
if (printer.id() == printer_id) {
return true;
}
}
return false;
}
} // namespace
AutomaticUsbPrinterConfigurer::AutomaticUsbPrinterConfigurer(
std::unique_ptr<PrinterConfigurer> printer_configurer,
PrinterInstallationManager* installation_manager,
UsbPrinterNotificationController* notification_controller)
: printer_configurer_(std::move(printer_configurer)),
installation_manager_(installation_manager),
notification_controller_(notification_controller) {
DCHECK(installation_manager);
}
AutomaticUsbPrinterConfigurer::~AutomaticUsbPrinterConfigurer() = default;
void AutomaticUsbPrinterConfigurer::OnPrintersChanged(
PrinterClass printer_class,
const std::vector<Printer>& printers) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
if (printer_class == PrinterClass::kAutomatic) {
// Remove any notifications for printers that are no longer in the automatic
// class and setup any USB printers we haven't seen yet.
PruneRemovedAutomaticPrinters(printers);
for (const Printer& printer : printers) {
if (!configured_printers_.contains(printer.id()) &&
printer.IsUsbProtocol()) {
SetupPrinter(printer);
}
}
return;
}
if (printer_class == PrinterClass::kDiscovered) {
// Remove any notifications for printers that are no longer in the
// discovered class and show a configuration notification for printers we
// haven't seen yet
PruneRemovedDiscoveredPrinters(printers);
for (const Printer& printer : printers) {
if (!unconfigured_printers_.contains(printer.id()) &&
printer.IsUsbProtocol()) {
notification_controller_->ShowConfigurationNotification(printer);
DCHECK(!configured_printers_.contains(printer.id()));
unconfigured_printers_.insert(printer.id());
}
}
return;
}
}
void AutomaticUsbPrinterConfigurer::SetupPrinter(const Printer& printer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
if (installation_manager_->IsPrinterInstalled(printer)) {
// Skip setup if the printer is already installed.
CompleteConfiguration(printer);
}
printer_configurer_->SetUpPrinter(
printer, base::BindOnce(&AutomaticUsbPrinterConfigurer::OnSetupComplete,
weak_factory_.GetWeakPtr(), printer));
}
void AutomaticUsbPrinterConfigurer::OnSetupComplete(const Printer& printer,
PrinterSetupResult result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
if (result == PrinterSetupResult::kPrinterIsNotAutoconfigurable) {
installation_manager_->PrinterIsNotAutoconfigurable(printer);
return;
}
if (result != PrinterSetupResult::kSuccess) {
LOG(ERROR) << "Unable to autoconfigure usb printer " << printer.id();
return;
}
installation_manager_->PrinterInstalled(printer, /*is_automatic=*/true);
PrinterConfigurer::RecordUsbPrinterSetupSource(
UsbPrinterSetupSource::kAutoconfigured);
CompleteConfiguration(printer);
}
void AutomaticUsbPrinterConfigurer::CompleteConfiguration(
const Printer& printer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
VLOG(1) << "Auto USB Printer setup successful for " << printer.id();
notification_controller_->ShowEphemeralNotification(printer);
DCHECK(!unconfigured_printers_.contains(printer.id()));
configured_printers_.insert(printer.id());
}
void AutomaticUsbPrinterConfigurer::PruneRemovedAutomaticPrinters(
const std::vector<Printer>& automatic_printers) {
PruneRemovedPrinters(automatic_printers, /*use_configured_printers=*/true);
}
void AutomaticUsbPrinterConfigurer::PruneRemovedDiscoveredPrinters(
const std::vector<Printer>& discovered_printers) {
PruneRemovedPrinters(discovered_printers, /*use_configured_printers=*/false);
}
void AutomaticUsbPrinterConfigurer::PruneRemovedPrinters(
const std::vector<Printer>& current_printers,
bool use_configured_printers) {
auto& printers =
use_configured_printers ? configured_printers_ : unconfigured_printers_;
for (auto it = printers.begin(); it != printers.end();) {
if (!IsPrinterIdInList(*it, current_printers)) {
notification_controller_->RemoveNotification(*it);
it = printers.erase(it);
} else {
++it;
}
}
}
} // namespace chromeos