chromium/chromeos/printing/ppd_provider.h

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_PRINTING_PPD_PROVIDER_H_
#define CHROMEOS_PRINTING_PPD_PROVIDER_H_

#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/version.h"
#include "chromeos/printing/printer_configuration.h"
#include "chromeos/printing/usb_printer_id.h"

namespace network::mojom {
class URLLoaderFactory;
}

namespace chromeos {

class PpdCache;
class PrinterConfigCache;
class PpdMetadataManager;
class RemotePpdFetcher;

// Everything we might know about a printer when looking for a
// driver for it.  All of the default values for fields in this struct
// mean we *don't* have that piece of information.
//
// Fields are listed in search order preference -- we use earlier
// fields first to attempt to find a match.
struct COMPONENT_EXPORT(CHROMEOS_PRINTING) PrinterSearchData {
  PrinterSearchData();
  PrinterSearchData(const PrinterSearchData& other);
  ~PrinterSearchData();

  // Make-and-model string guesses.
  std::vector<std::string> make_and_model;

  // 16-bit usb identifiers.
  int usb_vendor_id = 0;
  int usb_product_id = 0;

  // Original make and model for USB printer. Note, it is used only in metrics
  // for USB printers (in printer_event_tracker.cc).
  std::string usb_manufacturer;
  std::string usb_model;

  // Method of printer discovery.
  enum PrinterDiscoveryType {
    kUnknown = 0,
    kManual = 1,
    kUsb = 2,
    kZeroconf = 3,
    kDiscoveryTypeMax
  };
  PrinterDiscoveryType discovery_type;

  // Set of MIME types supported by this printer.
  std::vector<std::string> supported_document_formats;

  // Representation of IEEE1284 standard printing device ID.
  // Contains a set of languages this printer understands.
  UsbPrinterId printer_id;
};

// PpdProvider is responsible for mapping printer descriptions to
// CUPS-PostScript Printer Description (PPD) files.  It provides PPDs that a
// user previously identified for use, and falls back to querying quirksserver
// based on manufacturer/model of the printer.
//
// All functions in this class must be called from a sequenced context.
class COMPONENT_EXPORT(CHROMEOS_PRINTING) PpdProvider
    : public base::RefCounted<PpdProvider> {
 public:
  // Possible result codes of a Resolve*() call.
  enum CallbackResultCode {
    SUCCESS,

    // Looked for a PPD for this configuration, but couldn't find a match.
    // Never returned for QueryAvailable().
    NOT_FOUND,

    // Failed to contact an external server needed to finish resolution.
    SERVER_ERROR,

    // Other error that is not expected to be transient.
    INTERNAL_ERROR,

    // The provided PPD was too large to be processed.
    PPD_TOO_LARGE,
  };

  // Defines the limitations on when we show a particular PPD
  // Not to be confused with the new Restrictions struct used in the
  // v3 PpdProvider, defined in ppd_metadata_parser.h
  struct LegacyRestrictions {
    // Minimum milestone for ChromeOS build
    base::Version min_milestone = base::Version("0.0");

    // Maximum milestone for ChromeOS build
    base::Version max_milestone = base::Version("0.0");
  };

  struct ResolvedPpdReference {
    // The name of the model of printer or printer line
    std::string name;

    // Correct PpdReferece to be used with this printer
    Printer::PpdReference ppd_ref;
  };

  // Result of a ResolvePpd() call.
  // If the result code is SUCCESS, then:
  //    string holds the contents of a PPD (that may or may not be gzipped).
  // Otherwise, these fields will be empty.
  using ResolvePpdCallback =
      base::OnceCallback<void(CallbackResultCode, const std::string&)>;

  // Result of a ResolveManufacturers() call.  If the result code is SUCCESS,
  // then the vector contains a sorted list of manufacturers for which we have
  // at least one printer driver.
  using ResolveManufacturersCallback =
      base::OnceCallback<void(CallbackResultCode,
                              const std::vector<std::string>&)>;

  // A list of printer names paired with the PpdReference that should be used
  // for that printer.
  using ResolvedPrintersList = std::vector<ResolvedPpdReference>;

  // Result of a ResolvePrinters() call.  If the result code is SUCCESS, then
  // the vector contains a sorted list <model_name, PpdReference> tuples of all
  // printer models from the given manufacturer for which we have a driver,
  // sorted by model_name.
  using ResolvePrintersCallback =
      base::OnceCallback<void(CallbackResultCode, const ResolvedPrintersList&)>;

  // Result of a ResolvePpdReference call.  If the result code is SUCCESS, then
  // the second argument contains the a PpdReference that we have high
  // confidence can be used to obtain a driver for the printer.  NOT_FOUND means
  // we couldn't confidently figure out a driver for the printer.  If we got
  // NOT_FOUND from a USB printer, we may have been able to determine the
  // manufacturer name which is the third argument.
  using ResolvePpdReferenceCallback =
      base::OnceCallback<void(CallbackResultCode,
                              const Printer::PpdReference& ref,
                              const std::string& manufacturer)>;

  // Result of a ResolvePpdLicense call. If |result| is SUCCESS, then
  // |license_name| will be used to indicate the license associated with the
  // requested PPD. If |license_name| is empty, then the requested PPD does not
  // require a license.
  using ResolvePpdLicenseCallback =
      base::OnceCallback<void(CallbackResultCode result,
                              const std::string& license_name)>;

  // Result of a ReverseLookup call.  If the result code is SUCCESS, then
  // |manufactuer| and |model| contain the strings that could have generated
  // the reference being looked up.
  using ReverseLookupCallback =
      base::OnceCallback<void(CallbackResultCode,
                              const std::string& manufacturer,
                              const std::string& model)>;

  // Called to get the current URLLoaderFactory on demand. Needs to be
  // Repeating since it gets called once per fetch.
  using LoaderFactoryGetter =
      base::RepeatingCallback<network::mojom::URLLoaderFactory*()>;

  // Create and return a new PpdProvider with the given cache and options.
  // A references to |url_context_getter| is taken.
  static scoped_refptr<PpdProvider> Create(
      const base::Version& current_version,
      scoped_refptr<PpdCache> cache,
      std::unique_ptr<PpdMetadataManager> metadata_manager,
      std::unique_ptr<PrinterConfigCache> config_cache,
      std::unique_ptr<RemotePpdFetcher> remote_ppd_fetcher);

  // Return a printable name for |code|.
  static std::string_view CallbackResultCodeName(CallbackResultCode code);

  // Get all manufacturers for which we have drivers.  Keys of the map will be
  // localized in the default browser locale or the closest available fallback.
  //
  // |cb| will be called on the invoking thread, and will be sequenced.
  //
  // PpdProvider will enqueue calls to this method and answer them in
  // the order received; it will opt to invoke |cb| with failure if the
  // queue grows overlong, failing the oldest calls first. The exact
  // queue length at which this occurs is unspecified.
  virtual void ResolveManufacturers(ResolveManufacturersCallback cb) = 0;

  // Get all models from a given manufacturer, localized in the
  // default browser locale or the closest available fallback.
  // |manufacturer| must be a value returned from a successful
  // ResolveManufacturers() call performed from this PpdProvider
  // instance.
  //
  // |cb| will be called on the invoking thread, and will be sequenced.
  virtual void ResolvePrinters(const std::string& manufacturer,
                               ResolvePrintersCallback cb) = 0;

  // Attempt to find a PpdReference for the given printer.  You should supply
  // as much information in search_data as you can.
  virtual void ResolvePpdReference(const PrinterSearchData& search_data,
                                   ResolvePpdReferenceCallback cb) = 0;

  // Given a PpdReference, attempt to get the PPD for printing.
  //
  // |cb| will be called on the invoking thread, and will be sequenced.
  virtual void ResolvePpd(const Printer::PpdReference& reference,
                          ResolvePpdCallback cb) = 0;

  // Retrieves the name of the PPD license associated with the given printer
  // |effective_make_and_model|. If the name of the retrieved license is empty,
  // then the PPD does not require a license. If |effective_make_and_model| is
  // already present in the cache, then |cb| will fire immediately. Otherwise,
  // the PpdIndex will be fetched in order to retrieve the associated license.
  //
  // |cb| will be called on the invoking thread, and will be sequenced.
  virtual void ResolvePpdLicense(std::string_view effective_make_and_model,
                                 ResolvePpdLicenseCallback cb) = 0;

  // For a given PpdReference, retrieve the make and model strings used to
  // construct that reference.
  //
  // PpdProvider will enqueue calls to this method and answer them in
  // the order received; it will opt to invoke |cb| with failure if the
  // queue grows overlong, failing the oldest calls first. The exact
  // queue length at which this occurs is unspecified.
  virtual void ReverseLookup(const std::string& effective_make_and_model,
                             ReverseLookupCallback cb) = 0;

  // Transform from ppd reference to ppd cache key.  This is exposed for
  // testing, and should not be used by other code.
  static std::string PpdReferenceToCacheKey(
      const Printer::PpdReference& reference);

  // Used to "dereference" the PPD previously named by the cache key from
  // Printer::PpdReference::effective_make_and_model.
  static std::string PpdBasenameToCacheKey(std::string_view ppd_basename);

 protected:
  friend class base::RefCounted<PpdProvider>;
  virtual ~PpdProvider() {}
};

}  // namespace chromeos

#endif  // CHROMEOS_PRINTING_PPD_PROVIDER_H_