blob: 9a8ef43cd814ba40a9178988619dfe6a807e41f4 [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 <vector>
#include "base/containers/flat_set.h"
#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
#include "chrome/browser/chromeos/printing/printers_map.h"
#include "chrome/browser/chromeos/printing/test_printer_configurer.h"
#include "chrome/browser/chromeos/printing/usb_printer_notification_controller.h"
#include "chrome/common/chrome_features.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
Printer CreateUsbPrinter(const std::string& id) {
Printer printer;
printer.set_id(id);
printer.set_uri("usb:printer");
return printer;
}
Printer CreateIppUsbPrinter(const std::string& id) {
Printer printer;
printer.set_id(id);
printer.set_uri("ippusb:printer");
return printer;
}
Printer CreateIppPrinter(const std::string& id) {
Printer printer;
printer.set_id(id);
printer.set_uri("ipp:printer");
return printer;
}
} // namespace
// Provides a mechanism to interact with AutomaticPrinterConfigurer.
// Adding a printer causes the observer's OnPrintersChanged() method to run.
class FakeObservablePrintersManager {
public:
void SetObserver(CupsPrintersManager::Observer* observer) {
DCHECK(observer);
observer_ = observer;
}
// Simulates a nearby kAutomatic printer.
void AddNearbyAutomaticPrinter(const Printer& printer) {
AddPrinter(PrinterClass::kAutomatic, printer);
}
// Simulates a nearby kDiscovered printer.
void AddNearbyDiscoveredPrinter(const Printer& printer) {
AddPrinter(PrinterClass::kDiscovered, printer);
}
void RemoveAutomaticPrinter(const std::string& printer_id) {
RemovePrinter(PrinterClass::kAutomatic, printer_id);
}
void RemoveDiscoveredPrinter(const std::string& printer_id) {
RemovePrinter(PrinterClass::kDiscovered, printer_id);
}
private:
// Add |printer| to the corresponding list in |printers_| bases on the given
// |printer_class|.
void AddPrinter(PrinterClass printer_class, const Printer& printer) {
printers_.Insert(printer_class, printer);
observer_->OnPrintersChanged(printer_class, printers_.Get(printer_class));
}
// Remove |printer_id| from |printer_class|.
void RemovePrinter(PrinterClass printer_class,
const std::string& printer_id) {
printers_.Remove(printer_class, printer_id);
observer_->OnPrintersChanged(printer_class, printers_.Get(printer_class));
}
CupsPrintersManager::Observer* observer_;
PrintersMap printers_;
};
class FakePrinterInstallationManager : public PrinterInstallationManager {
public:
FakePrinterInstallationManager() = default;
~FakePrinterInstallationManager() override = default;
// CupsPrintersManager overrides
void PrinterInstalled(const Printer& printer, bool is_automatic) override {
DCHECK(is_automatic);
installed_printers_.insert(printer.id());
}
bool IsPrinterInstalled(const Printer& printer) const override {
return installed_printers_.contains(printer.id());
}
private:
base::flat_set<std::string> installed_printers_;
};
class FakeUsbPrinterNotificationController
: public UsbPrinterNotificationController {
public:
FakeUsbPrinterNotificationController() = default;
~FakeUsbPrinterNotificationController() override = default;
void ShowEphemeralNotification(const Printer& printer) override {
open_notifications_.insert(printer.id());
}
void ShowSavedNotification(const Printer& printer) override {
NOTIMPLEMENTED();
}
void ShowConfigurationNotification(const Printer& printer) override {
open_notifications_.insert(printer.id());
}
void RemoveNotification(const std::string& printer_id) override {
open_notifications_.erase(printer_id);
}
bool IsNotificationDisplayed(const std::string& printer_id) const override {
return open_notifications_.contains(printer_id);
}
private:
base::flat_set<std::string> open_notifications_;
};
class AutomaticUsbPrinterConfigurerTest : public testing::Test {
public:
AutomaticUsbPrinterConfigurerTest() {
scoped_feature_list_.InitAndEnableFeature(
features::kStreamlinedUsbPrinterSetup);
fake_installation_manager_ =
std::make_unique<FakePrinterInstallationManager>();
auto printer_configurer = std::make_unique<TestPrinterConfigurer>();
fake_printer_configurer_ = printer_configurer.get();
fake_notification_controller_ =
std::make_unique<FakeUsbPrinterNotificationController>();
auto_usb_printer_configurer_ =
std::make_unique<AutomaticUsbPrinterConfigurer>(
std::move(printer_configurer), fake_installation_manager_.get(),
fake_notification_controller_.get());
fake_observable_printers_manager_.SetObserver(
auto_usb_printer_configurer_.get());
}
~AutomaticUsbPrinterConfigurerTest() override = default;
protected:
FakeObservablePrintersManager fake_observable_printers_manager_;
TestPrinterConfigurer* fake_printer_configurer_; // not owned.
std::unique_ptr<FakePrinterInstallationManager> fake_installation_manager_;
std::unique_ptr<FakeUsbPrinterNotificationController>
fake_notification_controller_;
std::unique_ptr<AutomaticUsbPrinterConfigurer> auto_usb_printer_configurer_;
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(AutomaticUsbPrinterConfigurerTest);
};
TEST_F(AutomaticUsbPrinterConfigurerTest,
AutoUsbPrinterInstalledAutomatically) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
// Adding an automatic USB printer should result in the printer becoming
// configured and getting marked as installed.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer));
EXPECT_TRUE(fake_printer_configurer_->IsConfigured(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest,
AutoIppUsbPrinterInstalledAutomatically) {
const std::string printer_id = "id";
const Printer printer = CreateIppUsbPrinter(printer_id);
// Adding an automatic IPPUSB printer should result in the printer becoming
// configured and getting marked as installed.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer));
EXPECT_TRUE(fake_printer_configurer_->IsConfigured(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest, AutoIppPrinterNotInstalled) {
const std::string printer_id = "id";
const Printer printer = CreateIppPrinter(printer_id);
// Adding an automatic Ipp printer should *not* result in the printer becoming
// configured and getting marked as installed.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_FALSE(fake_installation_manager_->IsPrinterInstalled(printer));
EXPECT_FALSE(fake_printer_configurer_->IsConfigured(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest, DiscoveredUsbPrinterNotInstalled) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
// Adding a discovered USB printer should not result in the printer getting
// installed.
fake_observable_printers_manager_.AddNearbyDiscoveredPrinter(printer);
EXPECT_FALSE(fake_installation_manager_->IsPrinterInstalled(printer));
EXPECT_FALSE(fake_printer_configurer_->IsConfigured(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest,
ConfiguredAutoUsbPrinterGetsInstalled) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
fake_printer_configurer_->MarkConfigured(printer_id);
// Adding an automatic USB printer that's already configured should still
// result in the printer getting marked as installed.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer));
}
TEST_F(AutomaticUsbPrinterConfigurerTest, UsbPrinterAddedToSet) {
const std::string automatic_printer_id = "auto_id";
const Printer automatic_printer = CreateUsbPrinter(automatic_printer_id);
const std::string discovered_printer_id = "disco_id";
const Printer discovered_printer = CreateUsbPrinter(discovered_printer_id);
// Adding an automatic USB printer should result in the printer getting added
// to |auto_usb_printer_configurer_::configured_printers_|.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(
automatic_printer);
EXPECT_TRUE(auto_usb_printer_configurer_->configured_printers_.contains(
automatic_printer_id));
// Adding a discovered USB printer should result in the printer getting added
// to |auto_usb_printer_configurer_::unconfigured_printers_|.
fake_observable_printers_manager_.AddNearbyDiscoveredPrinter(
discovered_printer);
EXPECT_TRUE(auto_usb_printer_configurer_->unconfigured_printers_.contains(
discovered_printer_id));
EXPECT_EQ(1u, auto_usb_printer_configurer_->configured_printers_.size());
EXPECT_EQ(1u, auto_usb_printer_configurer_->unconfigured_printers_.size());
// Removing the automatic printer should result in the printer getting
// removed from |auto_usb_printer_configurer_::unconfigured_printers_|.
fake_observable_printers_manager_.RemoveDiscoveredPrinter(
discovered_printer_id);
EXPECT_EQ(0u, auto_usb_printer_configurer_->unconfigured_printers_.size());
// Removing the automatic printer should result in the printer getting
// removed from |auto_usb_printer_configurer_::configured_printers_|.
fake_observable_printers_manager_.RemoveAutomaticPrinter(
automatic_printer_id);
EXPECT_EQ(0u, auto_usb_printer_configurer_->configured_printers_.size());
}
TEST_F(AutomaticUsbPrinterConfigurerTest, NotificationOpenedForNewAutomatic) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(
fake_notification_controller_->IsNotificationDisplayed(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest,
NotificationOpenedForPreviouslyConfigured) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
// Mark the printer as configured.
fake_printer_configurer_->MarkConfigured(printer_id);
// Even though the printer is already configured, adding the printer should
// result in a notification being shown.
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(
fake_notification_controller_->IsNotificationDisplayed(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest, NotificationClosed) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(
fake_notification_controller_->IsNotificationDisplayed(printer_id));
fake_observable_printers_manager_.RemoveAutomaticPrinter(printer_id);
EXPECT_FALSE(
fake_notification_controller_->IsNotificationDisplayed(printer_id));
}
TEST_F(AutomaticUsbPrinterConfigurerTest, NotificationOpenedForNewDiscovered) {
const std::string printer_id = "id";
const Printer printer = CreateUsbPrinter(printer_id);
fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer);
EXPECT_TRUE(
fake_notification_controller_->IsNotificationDisplayed(printer_id));
}
} // namespace chromeos