15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/print_system.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cups/cups.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/md5.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h"
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/common/crash_keys.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_service_helpers.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/cups_helper.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend_consts.h"
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Print system config options.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCUPSPrintServerURLs[] = "print_server_urls";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCUPSUpdateTimeoutMs[] = "update_timeout_ms";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCUPSNotifyDelete[] = "notify_delete";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCUPSSupportedMimeTipes[] = "supported_mime_types";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default mime types supported by CUPS
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.cups.org/articles.php?L205+TFAQ+Q
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCUPSDefaultSupportedTypes[] =
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "application/pdf,application/postscript,image/jpeg,image/png,image/gif";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Time interval to check for printer's updates.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCheckForPrinterUpdatesMinutes = 5;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job update timeout
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kJobUpdateTimeoutSeconds = 5;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job id for dry run (it should not affect CUPS job ids, since 0 job-id is
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// invalid in CUPS.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDryRunJobId = 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cloud_print {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PrintServerInfoCUPS {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<printing::PrintBackend> backend;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterList printers;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CapsMap cache PPD until the next update and give a fast access to it by
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // printer name. PPD request is relatively expensive and this should minimize
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of requests.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, printing::PrinterCapsAndDefaults> CapsMap;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapsMap caps_cache;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrintSystemCUPS : public PrintSystem {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit PrintSystemCUPS(const base::DictionaryValue* print_system_settings);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrintSystem implementation.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrintSystemResult Init() OVERRIDE;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrintSystem::PrintSystemResult EnumeratePrinters(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printing::PrinterList* printer_list) OVERRIDE;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetPrinterCapsAndDefaults(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& printer_name,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const PrinterCapsAndDefaultsCallback& callback) OVERRIDE;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool ValidatePrintTicket(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& printer_name,
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& print_ticket_data,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& print_ticket_mime_type) OVERRIDE;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetJobDetails(const std::string& printer_name,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             PlatformJobId job_id,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             PrintJobDetails *job_details) OVERRIDE;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() OVERRIDE;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& printer_name) OVERRIDE;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool UseCddAndCjt() OVERRIDE;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string GetSupportedMimeTypes() OVERRIDE;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper functions.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlatformJobId SpoolPrintJob(const std::string& print_ticket,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const base::FilePath& print_data_file_path,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& print_data_mime_type,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& printer_name,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& job_title,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::vector<std::string>& tags,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool* dry_run);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetPrinterInfo(const std::string& printer_name,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      printing::PrinterBasicInfo* info);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParsePrintTicket(const std::string& print_ticket,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        std::map<std::string, std::string>* options);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synchronous version of GetPrinterCapsAndDefaults.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetPrinterCapsAndDefaults(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& printer_name,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printing::PrinterCapsAndDefaults* printer_info);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta GetUpdateTimeout() const {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return update_timeout_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool NotifyDelete() const {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notify about deleted printers only when we
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fetched printers list without errors.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return notify_delete_ && printer_enum_succeeded_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PrintSystemCUPS() {}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Following functions are wrappers around corresponding CUPS functions.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // <functions>2()  are called when print server is specified, and plain
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // version in another case. There is an issue specifing CUPS_HTTP_DEFAULT
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the <functions>2(), it does not work in CUPS prior to 1.4.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetJobs(cups_job_t** jobs, const GURL& url,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              http_encryption_t encryption, const char* name,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              int myjobs, int whichjobs);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int PrintFile(const GURL& url, http_encryption_t encryption,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const char* name, const char* filename,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const char* title, int num_options, cups_option_t* options);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void InitPrintBackends(const base::DictionaryValue* print_system_settings);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddPrintServer(const std::string& url);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdatePrinters();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Full name contains print server url:port and printer name. Short name
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is the name of the printer in the CUPS server.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string MakeFullPrinterName(const GURL& url,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& short_printer_name);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS* FindServerByFullName(
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& full_printer_name, std::string* short_printer_name);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper method to invoke a PrinterCapsAndDefaultsCallback.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void RunCapsCallback(
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const PrinterCapsAndDefaultsCallback& callback,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool succeeded,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& printer_name,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const printing::PrinterCapsAndDefaults& printer_info);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrintServerList contains information about all print servers and backends
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this proxy is connected to.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<PrintServerInfoCUPS> PrintServerList;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerList print_servers_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta update_timeout_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialized_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool printer_enum_succeeded_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool notify_delete_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_encryption_t cups_encryption_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string supported_mime_types_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrintServerWatcherCUPS
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : public PrintSystem::PrintServerWatcher {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PrintServerWatcherCUPS(PrintSystemCUPS* print_system)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : print_system_(print_system),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_(NULL) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrintSystem::PrintServerWatcher implementation.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StartWatching(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintSystem::PrintServerWatcher::Delegate* delegate) OVERRIDE {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = delegate;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printers_hash_ = GetPrintersHash();
187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrintServerWatcherCUPS::CheckForUpdates, this),
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_system_->GetUpdateTimeout());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StopWatching() OVERRIDE {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = NULL;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckForUpdates() {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ == NULL)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Orphan call. We have been stopped already.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Checking for new printers";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string new_hash = GetPrintersHash();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (printers_hash_ != new_hash) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printers_hash_ = new_hash;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnPrinterAdded();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrintServerWatcherCUPS::CheckForUpdates, this),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_system_->GetUpdateTimeout());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PrintServerWatcherCUPS() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopWatching();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetPrintersHash() {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList printer_list;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print_system_->EnumeratePrinters(&printer_list);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sort printer names.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> printers;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList::iterator it;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (it = printer_list.begin(); it != printer_list.end(); ++it)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printers.push_back(it->printer_name);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::sort(printers.begin(), printers.end());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string to_hash;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < printers.size(); i++)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      to_hash += printers[i];
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::MD5String(to_hash);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PrintSystemCUPS> print_system_;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSystem::PrintServerWatcher::Delegate* delegate_;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string printers_hash_;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherCUPS);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrinterWatcherCUPS
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public PrintSystem::PrinterWatcher {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrinterWatcherCUPS(PrintSystemCUPS* print_system,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& printer_name)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : printer_name_(printer_name),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_(NULL),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_system_(print_system) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrintSystem::PrinterWatcher implementation.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StartWatching(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE{
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<printing::PrintBackend> print_backend(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printing::PrintBackend::CreateInstance(NULL));
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    crash_keys::ScopedPrinterInfo crash_key(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_backend->GetPrinterDriverInfo(printer_name_));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ != NULL)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StopWatching();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = delegate;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings_hash_ = GetSettingsHash();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Schedule next job status update.
267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(kJobUpdateTimeoutSeconds));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Schedule next printer check.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(gene): Randomize time for the next printer update.
273a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this),
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_system_->GetUpdateTimeout());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StopWatching() OVERRIDE{
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = NULL;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetCurrentPrinterInfo(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      printing::PrinterBasicInfo* printer_info) OVERRIDE {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(printer_info);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return print_system_->GetPrinterInfo(printer_name_, printer_info);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void JobStatusUpdate() {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ == NULL)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Orphan call. We have been stopped already.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For CUPS proxy, we are going to fire OnJobChanged notification
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // periodically. Higher level will check if there are any outstanding
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // jobs for this printer and check their status. If printer has no
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // outstanding jobs, OnJobChanged() will do nothing.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnJobChanged();
299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this),
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(kJobUpdateTimeoutSeconds));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PrinterUpdate() {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ == NULL)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Orphan call. We have been stopped already.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Checking for updates"
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", printer name: " << printer_name_;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (print_system_->NotifyDelete() &&
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !print_system_->IsValidPrinter(printer_name_)) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnPrinterDeleted();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "CP_CUPS: Printer deleted"
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << ", printer name: " << printer_name_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string new_hash = GetSettingsHash();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (settings_hash_ != new_hash) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        settings_hash_ = new_hash;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnPrinterChanged();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(1) << "CP_CUPS: Printer configuration changed"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << ", printer name: " << printer_name_;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this),
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_system_->GetUpdateTimeout());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PrinterWatcherCUPS() {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopWatching();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetSettingsHash() {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterBasicInfo info;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!print_system_->GetPrinterInfo(printer_name_, &info))
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::string();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterCapsAndDefaults caps;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps))
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::string();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string to_hash(info.printer_name);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_hash += info.printer_description;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<std::string, std::string>::const_iterator it;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (it = info.options.begin(); it != info.options.end(); ++it) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      to_hash += it->first;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      to_hash += it->second;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_hash += caps.printer_capabilities;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_hash += caps.caps_mime_type;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_hash += caps.printer_defaults;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_hash += caps.defaults_mime_type;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::MD5String(to_hash);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string printer_name_;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSystem::PrinterWatcher::Delegate* delegate_;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PrintSystemCUPS> print_system_;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string settings_hash_;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrinterWatcherCUPS);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class JobSpoolerCUPS : public PrintSystem::JobSpooler {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit JobSpoolerCUPS(PrintSystemCUPS* print_system)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : print_system_(print_system) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(print_system_.get());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrintSystem::JobSpooler implementation.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Spool(const std::string& print_ticket,
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& print_ticket_mime_type,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const base::FilePath& print_data_file_path,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& print_data_mime_type,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& printer_name,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& job_title,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::vector<std::string>& tags,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     JobSpooler::Delegate* delegate) OVERRIDE{
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(delegate);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool dry_run = false;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int job_id = print_system_->SpoolPrintJob(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_ticket, print_data_file_path, print_data_mime_type,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer_name, job_title, tags, &dry_run);
389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&JobSpoolerCUPS::NotifyDelegate, delegate, job_id, dry_run));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void NotifyDelegate(JobSpooler::Delegate* delegate,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int job_id, bool dry_run) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dry_run || job_id)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate->OnJobSpoolSucceeded(job_id);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate->OnJobSpoolFailed();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~JobSpoolerCUPS() {}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PrintSystemCUPS> print_system_;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(JobSpoolerCUPS);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrintSystemCUPS::PrintSystemCUPS(
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* print_system_settings)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : update_timeout_(base::TimeDelta::FromMinutes(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kCheckForPrinterUpdatesMinutes)),
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initialized_(false),
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_enum_succeeded_(false),
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notify_delete_(true),
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cups_encryption_(HTTP_ENCRYPT_NEVER),
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supported_mime_types_(kCUPSDefaultSupportedTypes) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_system_settings) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int timeout;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (print_system_settings->GetInteger(kCUPSUpdateTimeoutMs, &timeout))
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      update_timeout_ = base::TimeDelta::FromMilliseconds(timeout);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int encryption;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (print_system_settings->GetInteger(kCUPSEncryption, &encryption))
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cups_encryption_ =
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<http_encryption_t>(encryption);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool notify_delete = true;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (print_system_settings->GetBoolean(kCUPSNotifyDelete, &notify_delete))
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notify_delete_ = notify_delete;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string types;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (print_system_settings->GetString(kCUPSSupportedMimeTipes, &types))
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supported_mime_types_ = types;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitPrintBackends(print_system_settings);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSystemCUPS::InitPrintBackends(
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* print_system_settings) {
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* url_list;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_system_settings &&
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print_system_settings->GetList(kCUPSPrintServerURLs, &url_list)) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < url_list->GetSize(); i++) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string print_server_url;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (url_list->GetString(i, &print_server_url))
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddPrintServer(print_server_url);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If server list is empty, use default print server.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_servers_.empty())
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPrintServer(std::string());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSystemCUPS::AddPrintServer(const std::string& url) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.empty())
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "No print server specified. Using default print server.";
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get Print backend for the specific print server.
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue backend_settings;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_settings.SetString(kCUPSPrintServerURL, url);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make CUPS requests non-blocking.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_settings.SetString(kCUPSBlocking, kValueFalse);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set encryption for backend.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_settings.SetInteger(kCUPSEncryption, cups_encryption_);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS print_server;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_server.backend =
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrintBackend::CreateInstance(&backend_settings);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_server.url = GURL(url.c_str());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_servers_.push_back(print_server);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrintSystemResult PrintSystemCUPS::Init() {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePrinters();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized_ = true;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PrintSystemResult(true, std::string());
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSystemCUPS::UpdatePrinters() {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerList::iterator it;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_enum_succeeded_ = true;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = print_servers_.begin(); it != print_servers_.end(); ++it) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->backend->EnumeratePrinters(&it->printers))
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_enum_succeeded_ = false;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->caps_cache.clear();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList::iterator printer_it;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (printer_it = it->printers.begin();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer_it != it->printers.end(); ++printer_it) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_it->printer_name = MakeFullPrinterName(it->url,
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     printer_it->printer_name);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Updated printers list"
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", server: " << it->url
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", # of printers: " << it->printers.size();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule next update.
507a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
509a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&PrintSystemCUPS::UpdatePrinters, this),
510a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      GetUpdateTimeout());
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrintSystemResult PrintSystemCUPS::EnumeratePrinters(
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList* printer_list) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_list->clear();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerList::iterator it;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = print_servers_.begin(); it != print_servers_.end(); ++it) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_list->insert(printer_list->end(),
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        it->printers.begin(), it->printers.end());
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CUPS: Total printers enumerated: " << printer_list->size();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sanjeevr): Maybe some day we want to report the actual server names
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for which the enumeration failed.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PrintSystemResult(printer_enum_succeeded_, std::string());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSystemCUPS::GetPrinterCapsAndDefaults(
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PrinterCapsAndDefaultsCallback& callback) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterCapsAndDefaults printer_info;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool succeeded = GetPrinterCapsAndDefaults(printer_name, &printer_info);
533a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
535a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&PrintSystemCUPS::RunCapsCallback,
536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 callback,
537a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 succeeded,
538a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 printer_name,
539a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 printer_info));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetPrinterInfo(printer_name, NULL);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrintSystemCUPS::ValidatePrintTicket(
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& printer_name,
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& print_ticket_data,
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& print_ticket_mime_type) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> ticket_value(
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::JSONReader::Read(print_ticket_data));
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ticket_value != NULL &&
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         ticket_value->IsType(base::Value::TYPE_DICTIONARY);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Print ticket on linux is a JSON string containing only one dictionary.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemCUPS::ParsePrintTicket(
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& print_ticket,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<std::string, std::string>* options) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(options);
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> ticket_value(base::JSONReader::Read(print_ticket));
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ticket_value == NULL ||
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ticket_value->IsType(base::Value::TYPE_DICTIONARY)) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options->clear();
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* ticket_dict =
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<base::DictionaryValue*>(ticket_value.get());
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(*ticket_dict); !it.IsAtEnd();
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it.Advance()) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it.value().GetAsString(&value))
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (*options)[it.key()] = value;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemCUPS::GetPrinterCapsAndDefaults(
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterCapsAndDefaults* printer_info) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string short_printer_name;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS* server_info =
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindServerByFullName(printer_name, &short_printer_name);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_info)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS::CapsMap::iterator caps_it =
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_info->caps_cache.find(printer_name);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (caps_it != server_info->caps_cache.end()) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *printer_info = caps_it->second;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(gene): Retry multiple times in case of error.
599d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  crash_keys::ScopedPrinterInfo crash_key(
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_info->backend->GetPrinterDriverInfo(short_printer_name));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_info->backend->GetPrinterCapsAndDefaults(short_printer_name,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       printer_info) ) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_info->caps_cache[printer_name] = *printer_info;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name,
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    PlatformJobId job_id,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    PrintJobDetails *job_details) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(job_details);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string short_printer_name;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS* server_info =
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindServerByFullName(printer_name, &short_printer_name);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_info)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  crash_keys::ScopedPrinterInfo crash_key(
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_info->backend->GetPrinterDriverInfo(short_printer_name));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cups_job_t* jobs = NULL;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_jobs = GetJobs(&jobs, server_info->url, cups_encryption_,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         short_printer_name.c_str(), 1, -1);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool error = (num_jobs == 0) && (cupsLastError() > IPP_OK_EVENTS_COMPLETE);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Error getting jobs from CUPS server"
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", printer name:" << printer_name
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", error: " << static_cast<int>(cupsLastError());
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the request is for dummy dry run job.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We check this after calling GetJobs API to see if this printer is actually
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // accessible through CUPS.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (job_id == kDryRunJobId) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    job_details->status = PRINT_JOB_STATUS_COMPLETED;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Dry run job succeeded"
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", printer name: " << printer_name;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found = false;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_jobs; i++) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (jobs[i].id == job_id) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = true;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (jobs[i].state) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_PENDING :
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_HELD :
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_PROCESSING :
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_IN_PROGRESS;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_STOPPED :
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_CANCELLED :
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_ABORTED :
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_ERROR;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case IPP_JOB_COMPLETED :
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_COMPLETED;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_INVALID;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      job_details->platform_status_flags = jobs[i].state;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't have any details on the number of processed pages here.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Job found"
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", printer name: " << printer_name
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", cups job id: " << job_id
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", cups job status: " << job_details->status;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "CP_CUPS: Job not found"
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", printer name: " << printer_name
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", cups job id: " << job_id;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cupsFreeJobs(num_jobs, jobs);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     printing::PrinterBasicInfo* info) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Getting printer info"
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", printer name: " << printer_name;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string short_printer_name;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS* server_info =
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindServerByFullName(printer_name, &short_printer_name);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_info)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterList::iterator it;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = server_info->printers.begin();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != server_info->printers.end(); ++it) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->printer_name == printer_name) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (info)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *info = *it;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrintServerWatcher*
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystemCUPS::CreatePrintServerWatcher() {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrintServerWatcherCUPS(this);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrinterWatcher* PrintSystemCUPS::CreatePrinterWatcher(
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!printer_name.empty());
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrinterWatcherCUPS(this, printer_name);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::JobSpooler* PrintSystemCUPS::CreateJobSpooler() {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new JobSpoolerCUPS(this);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrintSystemCUPS::UseCddAndCjt() {
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string PrintSystemCUPS::GetSupportedMimeTypes() {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return supported_mime_types_;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* print_system_settings) {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrintSystemCUPS(print_system_settings);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PrintSystemCUPS::PrintFile(const GURL& url, http_encryption_t encryption,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const char* name, const char* filename,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const char* title, int num_options,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               cups_option_t* options) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.is_empty()) {  // Use default (local) print server.
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cupsPrintFile(name, filename, title, num_options, options);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::HttpConnectionCUPS http(url, encryption);
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http.SetBlocking(false);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cupsPrintFile2(http.http(), name, filename,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          title, num_options, options);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PrintSystemCUPS::GetJobs(cups_job_t** jobs, const GURL& url,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             http_encryption_t encryption,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const char* name, int myjobs, int whichjobs) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.is_empty()) {  // Use default (local) print server.
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cupsGetJobs(jobs, name, myjobs, whichjobs);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::HttpConnectionCUPS http(url, encryption);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http.SetBlocking(false);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cupsGetJobs2(http.http(), jobs, name, myjobs, whichjobs);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PlatformJobId PrintSystemCUPS::SpoolPrintJob(
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& print_ticket,
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& print_data_file_path,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& print_data_mime_type,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& job_title,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& tags,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* dry_run) {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CUPS: Spooling print job, printer name: " << printer_name;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string short_printer_name;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerInfoCUPS* server_info =
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindServerByFullName(printer_name, &short_printer_name);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_info)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
786d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  crash_keys::ScopedPrinterInfo crash_key(
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_info->backend->GetPrinterDriverInfo(printer_name));
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to store options as char* string for the duration of the
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cupsPrintFile2 call. We'll use map here to store options, since
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dictionary value from JSON parser returns wchat_t.
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string> options;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool res = ParsePrintTicket(print_ticket, &options);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(res);  // If print ticket is invalid we still print using defaults.
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if this is a dry run (test) job.
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *dry_run = IsDryRunJob(tags);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*dry_run) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "CP_CUPS: Dry run job spooled";
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kDryRunJobId;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<cups_option_t> cups_options;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string>::iterator it;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = options.begin(); it != options.end(); ++it) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cups_option_t opt;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opt.name = const_cast<char*>(it->first.c_str());
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opt.value = const_cast<char*>(it->second.c_str());
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cups_options.push_back(opt);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int job_id = PrintFile(server_info->url,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         cups_encryption_,
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         short_printer_name.c_str(),
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         print_data_file_path.value().c_str(),
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         job_title.c_str(),
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         cups_options.size(),
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &(cups_options[0]));
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(alexyu): Output printer id.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CUPS: Job spooled"
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", printer name: " << printer_name
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", cups job id: " << job_id;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return job_id;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string PrintSystemCUPS::MakeFullPrinterName(
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url, const std::string& short_printer_name) {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string full_name;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name += "\\\\";
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name += url.host();
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.port().empty()) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    full_name += ":";
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    full_name += url.port();
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name += "\\";
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name += short_printer_name;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return full_name;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintServerInfoCUPS* PrintSystemCUPS::FindServerByFullName(
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& full_printer_name, std::string* short_printer_name) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t front = full_printer_name.find("\\\\");
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t separator = full_printer_name.find("\\", 2);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (front == std::string::npos || separator == std::string::npos) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "CP_CUPS: Invalid UNC"
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", printer name: " << full_printer_name;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string server = full_printer_name.substr(2, separator - 2);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintServerList::iterator it;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = print_servers_.begin(); it != print_servers_.end(); ++it) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string cur_server;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_server += it->url.host();
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->url.port().empty()) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_server += ":";
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_server += it->url.port();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_server == server) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *short_printer_name = full_printer_name.substr(separator + 1);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &(*it);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "CP_CUPS: Server not found"
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ", printer name: " << full_printer_name;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSystemCUPS::RunCapsCallback(
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PrinterCapsAndDefaultsCallback& callback,
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded,
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const printing::PrinterCapsAndDefaults& printer_info) {
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(succeeded, printer_name, printer_info);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace cloud_print
882