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.

Note that this doc is, at present, a design for the future instead of a description of the status quo. For up-to-date information on the implementation refer to http://crbug.com/742487.

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:

  • Configured 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 Configured 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

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.

Configured 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.

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

Code structure

CupsPrintersManager

Defined in chome/browser/chromeos/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 instantiated on demand, and is not intended to be a long-lived structure; it should be destroyed when its immediate usefulness is complete.

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. CupsPrinterManager is also where the logic to determine whether a given detected printer is automatically configurable (and this 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/printer_backend_proxy_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/chromeos/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/chromeos/printing/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 Configured and Enterprise printers. Essentially, when the user changes their Configured 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 SyncedPrintersManager because it is the only long-lived piece of the printer management system. (NOTE: Is there any sort of session-persistent key-value store that can be used in the browser? If so, we can and should shift this responsibility to CupsPrintersManager directly. It appears the KeyedService is the preferred way to do this sort of thing.)

PrinterDetectors

Defined in chome/browser/chromeos/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 Configured printers become either Automatic or Discovered printers, depending on whether or not we believe they can be configured automatically.

Second, CupsPrintersManager uses the detectors to determine whether or not certain Configured printers are currently available. This impacts whether or not they appear as print targets in the print UI.

Details for the existing PrinterDetector implementations follow.

USBPrinterDetector

Defined in chome/browser/chromeos/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/chromeos/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.