chromium/chrome/browser/chromeos/printing/doc/cups_printer_management.md

# CUPS Printer Management in ChromeOS

One of the goals of CUPS printing in ChromeOS is to provide as smooth an
experience as possible to users who wish to print to CUPS printers.  This means
we want to avoid extra setup steps where they are not necessary, and provide
help to the user when setup steps are necessary.  This document covers several
different ways we might discover printers, and how they integrate into the
printing flows.

## Categorizing printers
The fact that CUPS supports many printing modalities means that we have a
mishmash of ways we could print.  Within ChromeOS, we divide CUPS printers into
4 categories:

*  *Saved* printers - These are printers that are saved as a part of a users'
   settings and are synced across devices.  They show up in the list of printers
   in printer settings.

*  *Enterprise* printers - Printers that are provided by an enterprise
   environment.  These are synced one-way to ChromeOS devices.  If you work for
   a company/attend a school using ChromeOS, these are the printers that your
   administrator set up for you ahead of time.  (These are currently called
   "Recommended" printers in some APIs).

*  *Automatic* printers - Printers that this user has never printed to, but we
   believe the user *could* print to without needing to go through any manual
   setup steps.  Examples include Zeroconf printers and USB printers that either
   do not need a PPD or for which we have identified with high confidence an
   available PPD that can be installed if the user wants to print to this
   device.  If a user uses one of these printers, we automatically migrate it to
   be a Saved printer, as the user has shown that this is a printer of
   interest to them.

*  *Discovered* printers - Printers that have been detected, but that we believe
   will need user intervention to set up properly.  Examples would be an
   advertised zeroconf printer that can't be identified, or an unknown USB
   printer.


The flow of printers through theses states is illustrated here:
![Printer Flow Chart](printer_flow_chart.png)

In terms of usage, the categories combine in these ways:

*Automatic* and *Discovered* printers appear in the settings Discovery dialog as
available printers to be added.

*Saved* printers appear in the list of printers in the settings dialog. The
plan of record is that we do *not* support user-configurability for *Enterprise*
printers, which means these will either not appear in settings, or appear there
in an uneditable way.

*Saved*, *Enterprise*, and *Automatic* printers appear in the print preview
dialog as available targets for printing.


## Code structure

### CupsPrintersManager

Defined in `chome/browser/ash/printing/cups_printers_manager.[cc|h]`.

The `CupsPrintersManager` class is the top-level object responsible for
providing information about available printers of all 4 types to all consumers.
It is a BrowserContextKeyedService; only one exists for the duration of the
browser session. It's destroyed at the end of the current browser session.

It provides this information both via an Observer interface, for consumers that
require live updates to changes in availability, and also via a simpler "Give me
all the printers of this type" interface for simpler consumers that just need to
know the state of the world at a given point in time.  `CupsPrintersManager` is
also where the logic to determine whether a given detected printer is
automatically configurable (and thus belongs in the *Automatic* category) or not
(and thus belongs in the *Discovered* category).

There are 4 primary consumers of `CupsPrintersManager` information:

* The ChromeOS Print Backend implementation
  (`printing/backend/print_backend_chromeos.cc`).  This is the ChromeOS
  implementation of the backend print API used by Chrome.
* The PrintPreview dialog proxy
  (`chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc`).
  This is mostly a thread workaround to access the stuff in the print backend.
* The ChromeOS printers settings
  page. (`chrome/browser/ui/webui/settings/ash/cups_printers_handler.cc`
  and related code).  This is the primary place the user manages available
  printers.
* `CupsPrintJobManager`.  Requires printer information for the display and
  management of print job notifications.

Currently the needs of these sites are served by a combination of
`PrintersManager` and direct access to `Detector` classes.  Going forward, we
should make `CupsPrintersManager` the combined interface used by all of these
sites.

### SyncedPrintersManager

`SyncedPrintersManager` (nee `PrintersManager`) is a KeyedService Defined in
`chome/browser/ash/printers_sync_manager.[cc|h]`.
`SyncedPrintersManager` manages the persistent data about printers that is
synced across devices.  It serves as a two-way bridge between the sync systems
and `CupsPrintersManager` for both Saved and Enterprise printers.
Essentially, when the user changes their Saved printers list,
`SyncedPrintersManager` is what makes sure that propagates upstream, and when
changes from upstream come in, `SyncedPrintersManager` is responsible for
notifying `CupsPrintersManager` of the changes.

`SyncedPrintersManager` carries the additional responsibility for caching which
print destinations have been created in CUPS in the current session.  CrOS
differs from most CUPS installations in that configuration information lives in
the user profile, and is only made available to CUPS as needed.  In other words,
when a user wants to print, at that point Chrome tells CUPS to create the
relevant print queue, if needed.  Print queues don’t persist across logins, and
are recreated as needed.

Additionally, although recreating the same print queue with the same options is
theoretically a null operation, cupsd can get somewhat unhappy if you attempt to
create the same destination too many times quickly.  Thus, we need to cache
which destinations have been created in the current session.
This responsibility is given to  `CupsPrintersManager`.

### PrinterDetectors

Defined in `chome/browser/ash/printing/printer_detector.h` `PrinterDetector`
provides an interface implemented by subsystems that can automatically detect
the existence of printers.

These detections are used in two ways.  First, detected printers that are not
previously-known Saved printers become either Automatic or Discovered
printers, depending on whether or not we believe they can be configured
automatically.

Details for the existing PrinterDetector implementations follow.

#### USBPrinterDetector

Defined in `chome/browser/ash/printing/usb_printer_detector.[cc|h]`, this
interacts with the USB subsystem to turn USB device detection events into
printers.  Both cold- and hot-plugged printers are supported.

#### ZeroconfPrinterDetector

Defined in `chome/browser/ash/printing/zeroconf_printer_detector.[cc|h]`,
this interacts with the DNS-SD and mDNS systems to detect printers that
advertise themselves on the local network.