-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
This document provides a detailed technical overview of the architecture of Cupsie Printer Provider, a Chrome Extension built using the Manifest V3 and the chrome.printerProvider API to integrate CUPS print queues and standalone IPP/IPPS printers directly into Chrome's native print dialog.
Chrome extensions require host permissions to interact with servers via network requests (e.g., fetch). To maintain user trust and satisfy security requirements, host permissions for printer endpoints are optional.
When a user manually adds CUPS servers or standalone IPP printers in the Options page:
- The configuration is validated in
options.js. - The extension parses the hostnames of the servers and printers to generate match patterns in the format
*://${hostname}/*. - The options page pops-up an access permission message to request accessing all the added printers and/or CUPS servers.
- If permissions are granted, settings are persisted to
chrome.storage.syncto allow the synchronization if the user multiple computers.
For enterprise deployments, prompt-free installation is critical. IT administrators can bypass the dynamic host permissions prompts using Chrome's extension management policy (ExtensionSettings):
- The extension is deployed in
force_installedinstallation mode. - The administrator defines
runtime_allowed_hostsin the policy (e.g.["<all_urls>"]or specific internal IP range patterns). - Chrome automatically grants these host permissions upon installation, allowing the background sync and printing operations to proceed seamlessly without prompting the user.
When a user has Chrome Sync enabled and sets up the extension on a new device (e.g., Computer2):
- Chrome Sync automatically restores their printer URLs and sync settings from
chrome.storage.sync. - Chrome does not synchronize previously granted optional host permissions across devices due to security boundaries.
- Upon opening the Options page on the new device, the extension aggregates the origins of all synced (and managed) CUPS servers and standalone printers and checks their availability.
- If the check fails, a persistent warning banner is displayed prompting the user: "Connection permissions for some synced printers are missing on this device. Please click 'Save Settings' to grant access."
- When the user clicks Save Settings, a local permission prompt is displayed. Once approved, the warning banner is dismissed and the background sync worker is unblocked on the new device.
To support user-level access controls, the extension identifies the currently logged-in Chrome user.
2. If the user is synced and the API returns an email address (e.g., bob@example.com), the extension extracts the username portion before the @ symbol:
return userInfo.email.split('@')[0]; // returns "bob"- If the profile email is unavailable (e.g., sync disabled), it falls back to
nullor a generic username like"Chrome User".
CUPS servers specify who is authorized to print to specific queues using user control lists. The extension enforces this at the client level across three distinct phases.
During IPP operations (e.g., CUPS-Get-Printers or Get-Printer-Attributes), the printer or CUPS server returns these lists as part of the queue attributes:
-
requesting-user-name-allowed(Allowlist) -
requesting-user-name-denied(Denylist)
The extension applies the helper isUserAllowed(username, allowedList, deniedList):
-
Discovery & Sync Phase:
During synchronization, if
isUserAllowedevaluates tofalsefor the retrieved username, the extension skips caching this queue entirely. The user will not see the printer in their print destination picker. -
Capability Query Phase:
When the user opens the Chrome print dialog and selects a printer,
onGetCapabilityRequestedis fired. The extension fetches (or reads from cache) the allow/deny lists. If the user is blocked, it blocks the capability payload, logs a warning, displays an access-denied notification, and returns an empty description. -
Print Submission Phase:
When the user submits a job,
onPrintRequestedis fired. As a final guard, the extension checks the cached lists. If the user is denied, it immediately rejects the job withFAILEDwithout sending bytes over the network.
To keep network overhead low and prevent performance degradation, the extension minimizes traffic when communicating with printers.
sequenceDiagram
participant Chrome
participant Background as Background Service Worker
participant LocalStorage as Local Storage Cache
participant CUPS as CUPS Server
Note over Background, CUPS: Sync Phase
Background->>CUPS: HTTP POST: CUPS-Get-Printers (Single Query)
CUPS-->>Background: Returns List of Queues + Basic Metadata
Background->>LocalStorage: Save Printer List to cachedPrinters
Note over Chrome, LocalStorage: User Opens Print Dialog
Chrome->>Background: onGetPrintersRequested
Background->>LocalStorage: Get cachedPrinters
LocalStorage-->>Background: List of Printers
Background->>Chrome: Returns Printers (Safe PrinterInfo)
Note over Chrome, CUPS: User Selects Printer (Capabilities Resolution)
Chrome->>Background: onGetCapabilityRequested(printerId)
alt Cache Hit (Age < 24 hours)
Background->>LocalStorage: Get cached capability for printerId
LocalStorage-->>Background: Cached CDD
Background->>Chrome: Return CDD
else Cache Miss
Background->>CUPS: HTTP POST: Get-Printer-Attributes for printerId
CUPS-->>Background: Full Printer Attributes
Background->>Background: Parse & Map to CDD
Background->>LocalStorage: Save CDD to capabilitiesCache
Background->>Chrome: Return CDD
end
Instead of querying every printer queue individually during synchronization, the extension sends a single CUPS-Get-Printers IPP request to the CUPS server. This request fetches all exposed printer queues and their basic metadata in a single network round-trip.
The full printer capabilities (resolutions, media sizes, input/output trays) are not requested during synchronization. Instead:
- Discovered printers are saved with basic details (ID, name, description) in
chrome.storage.local. - Detailed capabilities are queried only on-demand when the user selects a printer in the print dialog (
onGetCapabilityRequested).
To avoid repeated capabilities queries, retrieved capabilities are cached in capabilitiesCache with a 24-hour expiration time. A network request is only performed on a cache miss or when the cache expires.
The extension handles the low-level encoding and mapping of IPP attributes itself, without external dependencies.
The parseIppResponse(arrayBuffer) function in ipp.js decodes standard IPP binary formats.
- It reads the 8-byte IPP header:
version(2 bytes),statusCode(2 bytes), andrequestId(4 bytes). - It iterates through the remaining stream to process attributes grouped by delimiter tags (e.g.
0x04for printer attributes). - It parses each attribute by reading its tag, name length, name, value length, and value bytes.
- Values are parsed according to their tags:
-
Text/URI/Keywords/MIME Types (
0x41–0x49): Decoded viaTextDecoderas UTF-8 strings. -
Integers/Enums (
0x21,0x23): Parsed as 32-bit big-endian integers. -
Booleans (
0x22): Parsed asvalBytes[0] === 1. -
Resolutions (
0x32): Decoded intoX_DPIxY_DPIstrings. -
Ranges of Integers (
0x33): Decoded as[min, max]arrays.
-
Text/URI/Keywords/MIME Types (
The buildCDD(ippAttributes) function in cdd.js transforms raw IPP attributes into the CDD structure required by Chrome:
-
Color Mode: Maps
print-color-mode-supportedtoSTANDARD_COLORandSTANDARD_MONOCHROME. -
Duplex: Maps
sides-supportedtoNO_DUPLEX,LONG_EDGE, orSHORT_EDGE. -
Paper Sizes: Extracts size identifiers from
media-supported. Standard sizes are mapped to CDD names (e.g.,NA_LETTER,ISO_A4). Non-standard sizes are parsed to extract micron dimensions. -
Tray & Media Capabilities: Translates attributes like
media-source-supported(Input Trays),output-bin-supported(Output Bins), andmedia-type-supported(Paper Types) into standardSELECTvendor capabilities. - Finishing Options: Decodes finishing enums (like staple top-left, punch, bind) using a standard lookup map and represents them as select options.
-
Defaults: Uses IPP
defaultattributes (e.g.media-default) to set theis_defaultproperty on corresponding options.
To avoid forcing users to configure every option in Chrome's print dialog, the extension dynamically resolves defaults:
-
Explicit Server Default: If the printer has a default option set (e.g.
media-source-default), that option is selected in the print dialog. -
Fallback to Printer Default: If the printer does not expose a default option, the dropdown defaults to "Use Printer Default" (internal value
__printer_default__). -
Omitting Unused Attributes: When submitting the print job, any option set to
"Use Printer Default"is omitted from the IPP request. This allows the CUPS server/printer to use its own server-side default configuration.