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)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/service/cloud_print/print_system.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/command_line.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/json/json_writer.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/object_watcher.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_bstr.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_comptr.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_hdc.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_cdd_conversion.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/common/crash_keys.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/service/cloud_print/cdd_conversion_win.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/service/service_process.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/service/service_utility_process_host.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/win_helper.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "printing/emf_win.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "printing/page_range.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "printing/pdf_render_settings.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "printing/printing_utils.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/geometry/rect.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace cloud_print {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSystemWatcherWin()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : delegate_(NULL),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        did_signal_(false) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PrintSystemWatcherWin() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Stop();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Delegate {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~Delegate() {}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnPrinterAdded() = 0;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnPrinterDeleted() = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnPrinterChanged() = 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnJobChanged() = 0;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Start(const std::string& printer_name, Delegate* delegate) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<printing::PrintBackend> print_backend(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printing::PrintBackend::CreateInstance(NULL));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_info_ = print_backend->GetPrinterDriverInfo(printer_name);
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    crash_keys::ScopedPrinterInfo crash_key(printer_info_);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = delegate;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // An empty printer name means watch the current server, we need to pass
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NULL to OpenPrinter.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPTSTR printer_name_to_use = NULL;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring printer_name_wide;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!printer_name.empty()) {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printer_name_wide = base::UTF8ToWide(printer_name);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ret = false;
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (printer_.OpenPrinter(printer_name_to_use)) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_change_.Set(FindFirstPrinterChangeNotification(
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          printer_.Get(), PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (printer_change_.IsValid()) {
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ret = watcher_.StartWatching(printer_change_.Get(), this);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ret) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Stop();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Stop() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watcher_.StopWatching();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_.Close();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_change_.Close();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::ObjectWatcher::Delegate method
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnObjectSignaled(HANDLE object) {
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    crash_keys::ScopedPrinterInfo crash_key(printer_info_);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD change = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindNextPrinterChangeNotification(object, &change, NULL, NULL);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) &
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For printer connections, we get spurious change notifications with
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ignore these.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (change & PRINTER_CHANGE_ADD_PRINTER) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnPrinterAdded();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (change & PRINTER_CHANGE_DELETE_PRINTER) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnPrinterDeleted();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (change & PRINTER_CHANGE_SET_PRINTER) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnPrinterChanged();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (change & PRINTER_CHANGE_JOB) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnJobChanged();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    watcher_.StartWatching(printer_change_.Get(), this);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(printer_info);
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return InitBasicPrinterInfo(printer_.Get(), printer_info);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ObjectWatcher watcher_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::ScopedPrinterHandle printer_;  // The printer being watched
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returned by FindFirstPrinterChangeNotifier.
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  printing::ScopedPrinterChangeHandle printer_change_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Delegate* delegate_;           // Delegate to notify
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_signal_;              // DoneWaiting was called
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string printer_info_;     // For crash reporting.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class PrintServerWatcherWin
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  : public PrintSystem::PrintServerWatcher,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public PrintSystemWatcherWin::Delegate {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrintServerWatcherWin() : delegate_(NULL) {}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // PrintSystem::PrintServerWatcher implementation.
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool StartWatching(
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      PrintSystem::PrintServerWatcher::Delegate* delegate) OVERRIDE{
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_ = delegate;
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return watcher_.Start(std::string(), this);
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool StopWatching() OVERRIDE{
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool ret = watcher_.Stop();
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_ = NULL;
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return ret;
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // PrintSystemWatcherWin::Delegate implementation.
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterAdded() OVERRIDE {
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->OnPrinterAdded();
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterDeleted() OVERRIDE {}
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterChanged() OVERRIDE {}
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnJobChanged() OVERRIDE {}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected:
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~PrintServerWatcherWin() {}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrintSystem::PrintServerWatcher::Delegate* delegate_;
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrintSystemWatcherWin watcher_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin);
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class PrinterWatcherWin
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : public PrintSystem::PrinterWatcher,
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      public PrintSystemWatcherWin::Delegate {
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit PrinterWatcherWin(const std::string& printer_name)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : printer_name_(printer_name),
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        delegate_(NULL) {
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // PrintSystem::PrinterWatcher implementation.
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool StartWatching(
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE {
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_ = delegate;
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return watcher_.Start(printer_name_, this);
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool StopWatching() OVERRIDE {
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool ret = watcher_.Stop();
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_ = NULL;
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return ret;
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool GetCurrentPrinterInfo(
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      printing::PrinterBasicInfo* printer_info) OVERRIDE {
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return watcher_.GetCurrentPrinterInfo(printer_info);
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // PrintSystemWatcherWin::Delegate implementation.
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterAdded() OVERRIDE {
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NOTREACHED();
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterDeleted() OVERRIDE {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->OnPrinterDeleted();
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnPrinterChanged() OVERRIDE {
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->OnPrinterChanged();
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnJobChanged() OVERRIDE {
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->OnJobChanged();
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected:
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~PrinterWatcherWin() {}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string printer_name_;
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrintSystem::PrinterWatcher::Delegate* delegate_;
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrintSystemWatcherWin watcher_;
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class JobSpoolerWin : public PrintSystem::JobSpooler {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  JobSpoolerWin() : core_(new Core) {}
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PrintSystem::JobSpooler implementation.
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool Spool(const std::string& print_ticket,
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& print_ticket_mime_type,
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const base::FilePath& print_data_file_path,
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& print_data_mime_type,
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& printer_name,
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& job_title,
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::vector<std::string>& tags,
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     JobSpooler::Delegate* delegate) OVERRIDE {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(gene): add tags handling.
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<printing::PrintBackend> print_backend(
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        printing::PrintBackend::CreateInstance(NULL));
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    crash_keys::ScopedPrinterInfo crash_key(
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        print_backend->GetPrinterDriverInfo(printer_name));
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return core_->Spool(print_ticket, print_ticket_mime_type,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        print_data_file_path, print_data_mime_type,
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        printer_name, job_title, delegate);
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~JobSpoolerWin() {}
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We use a Core class because we want a separate RefCountedThreadSafe
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementation for ServiceUtilityProcessHost::Client.
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class Core : public ServiceUtilityProcessHost::Client,
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               public base::win::ObjectWatcher::Delegate {
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Core() : job_id_(-1), delegate_(NULL), saved_dc_(0) {}
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ~Core() {}
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool Spool(const std::string& print_ticket,
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const std::string& print_ticket_mime_type,
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const base::FilePath& print_data_file_path,
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const std::string& print_data_mime_type,
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const std::string& printer_name,
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const std::string& job_title,
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               JobSpooler::Delegate* delegate) {
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (delegate_) {
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // We are already in the process of printing.
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NOTREACHED();
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::string16 printer_wide = base::UTF8ToWide(printer_name);
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We only support PDF and XPS documents for now.
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (print_data_mime_type == kContentTypePDF) {
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode;
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (print_ticket_mime_type == kContentTypeJSON) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          dev_mode = CjtToDevMode(printer_wide, print_ticket);
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          DCHECK(print_ticket_mime_type == kContentTypeXML);
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          dev_mode = printing::XpsTicketToDevMode(printer_wide, print_ticket);
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!dev_mode) {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          NOTREACHED();
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return false;
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        HDC dc = CreateDC(L"WINSPOOL", printer_wide.c_str(), NULL,
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          dev_mode.get());
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!dc) {
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          NOTREACHED();
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return false;
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DOCINFO di = {0};
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        di.cbSize = sizeof(DOCINFO);
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::string16 doc_name = base::UTF8ToUTF16(job_title);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(printing::SimplifyDocumentTitle(doc_name) == doc_name);
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        di.lpszDocName = doc_name.c_str();
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        job_id_ = StartDoc(dc, &di);
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (job_id_ <= 0)
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return false;
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        printer_dc_.Set(dc);
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        saved_dc_ = SaveDC(printer_dc_.Get());
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        print_data_file_path_ = print_data_file_path;
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate_ = delegate;
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        RenderPDFPages();
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (print_data_mime_type == kContentTypeXPS) {
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(print_ticket_mime_type == kContentTypeXML);
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bool ret = PrintXPSDocument(printer_name,
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    job_title,
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    print_data_file_path,
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    print_ticket);
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (ret)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          delegate_ = delegate;
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return ret;
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NOTREACHED();
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    void PreparePageDCForPrinting(HDC, double scale_factor) {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Setup the matrix to translate and scale to the right place. Take in
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // account the scale factor.
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Note that the printing output is relative to printable area of
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // the page. That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int offset_x = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETX);
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int offset_y = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETY);
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      XFORM xform = {0};
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      xform.eDx = static_cast<float>(-offset_x);
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      xform.eDy = static_cast<float>(-offset_y);
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      xform.eM11 = xform.eM22 = 1.0 / scale_factor;
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetWorldTransform(printer_dc_.Get(), &xform);
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // ServiceUtilityProcessHost::Client implementation.
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual void OnRenderPDFPagesToMetafilePageDone(
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        double scale_factor,
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        const printing::MetafilePlayer& emf) OVERRIDE {
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PreparePageDCForPrinting(printer_dc_.Get(), scale_factor);
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ::StartPage(printer_dc_.Get());
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      emf.SafePlayback(printer_dc_.Get());
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ::EndPage(printer_dc_.Get());
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // ServiceUtilityProcessHost::Client implementation.
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual void OnRenderPDFPagesToMetafileDone(bool success) OVERRIDE {
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PrintJobDone(success);
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual void OnChildDied() OVERRIDE { PrintJobDone(false); }
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // base::win::ObjectWatcher::Delegate implementation.
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(xps_print_job_);
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(object == job_progress_event_.Get());
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ResetEvent(job_progress_event_.Get());
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!delegate_)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      XPS_JOB_STATUS job_status = {0};
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      xps_print_job_->GetJobStatus(&job_status);
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if ((job_status.completion == XPS_JOB_CANCELLED) ||
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          (job_status.completion == XPS_JOB_FAILED)) {
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate_->OnJobSpoolFailed();
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (job_status.jobId ||
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  (job_status.completion == XPS_JOB_COMPLETED)) {
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Note: In the case of the XPS document being printed to the
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Microsoft XPS Document Writer, it seems to skip spooling the job
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // and goes to the completed state without ever assigning a job id.
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate_->OnJobSpoolSucceeded(job_status.jobId);
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        job_progress_watcher_.StopWatching();
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   private:
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Helper class to allow PrintXPSDocument() to have multiple exits.
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    class PrintJobCanceler {
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     public:
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      explicit PrintJobCanceler(
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::win::ScopedComPtr<IXpsPrintJob>* job_ptr)
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          : job_ptr_(job_ptr) {
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ~PrintJobCanceler() {
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (job_ptr_ && *job_ptr_) {
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          (*job_ptr_)->Cancel();
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          job_ptr_->Release();
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      void reset() { job_ptr_ = NULL; }
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     private:
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_;
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler);
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    };
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void PrintJobDone(bool success) {
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // If there is no delegate, then there is nothing pending to process.
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!delegate_)
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      RestoreDC(printer_dc_.Get(), saved_dc_);
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndDoc(printer_dc_.Get());
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (success) {
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate_->OnJobSpoolSucceeded(job_id_);
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        delegate_->OnJobSpoolFailed();
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_ = NULL;
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void RenderPDFPages() {
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Rect render_area(0, 0, dc_width, dc_height);
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_service_process->io_thread()->message_loop_proxy()->PostTask(
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          FROM_HERE,
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox,
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     this,
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     print_data_file_path_,
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     render_area,
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     printer_dpi,
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     base::MessageLoopProxy::current()));
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Called on the service process IO thread.
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void RenderPDFPagesInSandbox(const base::FilePath& pdf_path,
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 const gfx::Rect& render_area,
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 int render_dpi,
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 const scoped_refptr<base::MessageLoopProxy>&
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     client_message_loop_proxy) {
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(g_service_process->io_thread()->message_loop_proxy()->
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          BelongsToCurrentThread());
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<ServiceUtilityProcessHost> utility_host(
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new ServiceUtilityProcessHost(this, client_message_loop_proxy));
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // TODO(gene): For now we disabling autorotation for CloudPrinting.
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Landscape/Portrait setting is passed in the print ticket and
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // server is generating portrait PDF always.
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We should enable autorotation once server will be able to generate
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // PDF that matches paper size and orientation.
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (utility_host->StartRenderPDFPagesToMetafile(
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              pdf_path,
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              printing::PdfRenderSettings(render_area, render_dpi, false))) {
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // The object will self-destruct when the child process dies.
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        utility_host.release();
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        client_message_loop_proxy->PostTask(
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            FROM_HERE, base::Bind(&Core::PrintJobDone, this, false));
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool PrintXPSDocument(const std::string& printer_name,
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const std::string& job_title,
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const base::FilePath& print_data_file_path,
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const std::string& print_ticket) {
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!printing::XPSPrintModule::Init())
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!job_progress_event_.Get())
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PrintJobCanceler job_canceler(&xps_print_job_);
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream;
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream;
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (FAILED(printing::XPSPrintModule::StartXpsPrintJob(
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              base::UTF8ToWide(printer_name).c_str(),
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              base::UTF8ToWide(job_title).c_str(),
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              NULL, job_progress_event_.Get(), NULL, NULL, NULL,
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              xps_print_job_.Receive(), doc_stream.Receive(),
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              print_ticket_stream.Receive())))
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ULONG print_bytes_written = 0;
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (FAILED(print_ticket_stream->Write(print_ticket.c_str(),
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            print_ticket.length(),
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            &print_bytes_written)))
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK_EQ(print_ticket.length(), print_bytes_written);
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (FAILED(print_ticket_stream->Close()))
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string document_data;
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::ReadFileToString(print_data_file_path, &document_data);
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ULONG doc_bytes_written = 0;
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (FAILED(doc_stream->Write(document_data.c_str(),
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    document_data.length(),
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &doc_bytes_written)))
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK_EQ(document_data.length(), doc_bytes_written);
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (FAILED(doc_stream->Close()))
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      job_canceler.reset();
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PlatformJobId job_id_;
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrintSystem::JobSpooler::Delegate* delegate_;
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int saved_dc_;
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedCreateDC printer_dc_;
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::FilePath print_data_file_path_;
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedHandle job_progress_event_;
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ObjectWatcher job_progress_watcher_;
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_;
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Core);
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<Core> core_;
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin);
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A helper class to handle the response from the utility process to the
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// request to fetch printer capabilities and defaults.
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PrinterCapsHandler : public ServiceUtilityProcessHost::Client {
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrinterCapsHandler(
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name,
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const PrintSystem::PrinterCapsAndDefaultsCallback& callback)
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          : printer_name_(printer_name), callback_(callback) {
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ServiceUtilityProcessHost::Client implementation.
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnChildDied() OVERRIDE {
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnGetPrinterCapsAndDefaults(false, printer_name_,
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                printing::PrinterCapsAndDefaults());
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnGetPrinterCapsAndDefaults(
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool succeeded,
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name,
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const printing::PrinterCapsAndDefaults& caps_and_defaults) OVERRIDE {
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(succeeded, printer_name, caps_and_defaults);
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Reset();
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Release();
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnGetPrinterSemanticCapsAndDefaults(
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool succeeded,
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name,
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const printing::PrinterSemanticCapsAndDefaults& semantic_info) OVERRIDE {
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    printing::PrinterCapsAndDefaults printer_info;
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (succeeded) {
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printer_info.caps_mime_type = kContentTypeJSON;
54746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_ptr<base::DictionaryValue> description(
54846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          PrinterSemanticCapsAndDefaultsToCdd(semantic_info));
54946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (description) {
55046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::JSONWriter::WriteWithOptions(
55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            description.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT,
55246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            &printer_info.printer_capabilities);
55346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(succeeded, printer_name, printer_info);
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Reset();
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Release();
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StartGetPrinterCapsAndDefaults() {
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    g_service_process->io_thread()->message_loop_proxy()->PostTask(
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&PrinterCapsHandler::GetPrinterCapsAndDefaultsImpl, this,
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    base::MessageLoopProxy::current()));
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StartGetPrinterSemanticCapsAndDefaults() {
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    g_service_process->io_thread()->message_loop_proxy()->PostTask(
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&PrinterCapsHandler::GetPrinterSemanticCapsAndDefaultsImpl,
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   this, base::MessageLoopProxy::current()));
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void GetPrinterCapsAndDefaultsImpl(
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>&
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          client_message_loop_proxy) {
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(g_service_process->io_thread()->message_loop_proxy()->
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BelongsToCurrentThread());
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<ServiceUtilityProcessHost> utility_host(
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new ServiceUtilityProcessHost(this, client_message_loop_proxy));
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (utility_host->StartGetPrinterCapsAndDefaults(printer_name_)) {
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // The object will self-destruct when the child process dies.
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      utility_host.release();
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_message_loop_proxy->PostTask(
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          FROM_HERE,
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Bind(&PrinterCapsHandler::OnChildDied, this));
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void GetPrinterSemanticCapsAndDefaultsImpl(
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>&
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          client_message_loop_proxy) {
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(g_service_process->io_thread()->message_loop_proxy()->
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BelongsToCurrentThread());
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<ServiceUtilityProcessHost> utility_host(
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new ServiceUtilityProcessHost(this, client_message_loop_proxy));
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (utility_host->StartGetPrinterSemanticCapsAndDefaults(printer_name_)) {
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // The object will self-destruct when the child process dies.
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      utility_host.release();
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_message_loop_proxy->PostTask(
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          FROM_HERE,
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Bind(&PrinterCapsHandler::OnChildDied, this));
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string printer_name_;
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrintSystem::PrinterCapsAndDefaultsCallback callback_;
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PrintSystemWin : public PrintSystem {
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrintSystemWin();
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PrintSystem implementation.
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual PrintSystemResult Init() OVERRIDE;
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual PrintSystem::PrintSystemResult EnumeratePrinters(
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printing::PrinterList* printer_list) OVERRIDE;
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void GetPrinterCapsAndDefaults(
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name,
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const PrinterCapsAndDefaultsCallback& callback) OVERRIDE;
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool ValidatePrintTicket(
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name,
6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& print_ticket_data,
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& print_ticket_data_mime_type) OVERRIDE;
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool GetJobDetails(const std::string& printer_name,
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             PlatformJobId job_id,
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             PrintJobDetails *job_details) OVERRIDE;
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() OVERRIDE;
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name) OVERRIDE;
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE;
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool UseCddAndCjt() OVERRIDE;
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual std::string GetSupportedMimeTypes() OVERRIDE;
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string PrintSystemWin::GetPrinterDriverInfo(
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& printer_name) const;
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<printing::PrintBackend> print_backend_;
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool use_cdd_;
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrintSystemWin);
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
648a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PrintSystemWin::PrintSystemWin() : use_cdd_(true) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_backend_ = printing::PrintBackend::CreateInstance(NULL);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrintSystem::PrintSystemResult PrintSystemWin::Init() {
653a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  use_cdd_ = !CommandLine::ForCurrentProcess()->HasSwitch(
654a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      switches::kEnableCloudPrintXps);
655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
656a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!use_cdd_)
657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    use_cdd_ = !printing::XPSModule::Init();
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!use_cdd_) {
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    HPTPROVIDER provider = NULL;
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    HRESULT hr = printing::XPSModule::OpenProvider(L"", 1, &provider);
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (provider)
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printing::XPSModule::CloseProvider(provider);
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Use cdd if error is different from expected.
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    use_cdd_ = (hr != HRESULT_FROM_WIN32(ERROR_INVALID_PRINTER_NAME));
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return PrintSystemResult(true, std::string());
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrintSystemResult PrintSystemWin::EnumeratePrinters(
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList* printer_list) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ret = print_backend_->EnumeratePrinters(printer_list);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PrintSystemResult(ret, std::string());
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrintSystemWin::GetPrinterCapsAndDefaults(
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& printer_name,
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PrinterCapsAndDefaultsCallback& callback) {
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Launch as child process to retrieve the capabilities and defaults because
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this involves invoking a printer driver DLL and crashes have been known to
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // occur.
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrinterCapsHandler* handler = new PrinterCapsHandler(printer_name, callback);
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  handler->AddRef();
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (use_cdd_)
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    handler->StartGetPrinterSemanticCapsAndDefaults();
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    handler->StartGetPrinterCapsAndDefaults();
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return print_backend_->IsValidPrinter(printer_name);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrintSystemWin::ValidatePrintTicket(
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& printer_name,
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& print_ticket_data,
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& print_ticket_data_mime_type) {
6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  crash_keys::ScopedPrinterInfo crash_key(GetPrinterDriverInfo(printer_name));
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (use_cdd_) {
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return print_ticket_data_mime_type == kContentTypeJSON &&
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           IsValidCjt(print_ticket_data);
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(print_ticket_data_mime_type == kContentTypeXML);
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  printing::ScopedXPSInitializer xps_initializer;
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!xps_initializer.initialized()) {
7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool ret = false;
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HPTPROVIDER provider = NULL;
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name), 1,
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &provider);
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (provider) {
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedComPtr<IStream> print_ticket_stream;
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateStreamOnHGlobal(NULL, TRUE, print_ticket_stream.Receive());
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ULONG bytes_written = 0;
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    print_ticket_stream->Write(print_ticket_data.c_str(),
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               print_ticket_data.length(),
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               &bytes_written);
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(bytes_written == print_ticket_data.length());
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LARGE_INTEGER pos = {0};
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ULARGE_INTEGER new_pos = {0};
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    print_ticket_stream->Seek(pos, STREAM_SEEK_SET, &new_pos);
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedBstr error;
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::win::ScopedComPtr<IStream> result_ticket_stream;
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.Receive());
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ret = SUCCEEDED(printing::XPSModule::MergeAndValidatePrintTicket(
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        provider,
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        print_ticket_stream.get(),
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NULL,
7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        kPTJobScope,
7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        result_ticket_stream.get(),
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        error.Receive()));
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    printing::XPSModule::CloseProvider(provider);
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ret;
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintSystemWin::GetJobDetails(const std::string& printer_name,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PlatformJobId job_id,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PrintJobDetails *job_details) {
745d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  crash_keys::ScopedPrinterInfo crash_key(
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print_backend_->GetPrinterDriverInfo(printer_name));
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(job_details);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::ScopedPrinterHandle printer_handle;
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::wstring printer_name_wide = base::UTF8ToWide(printer_name);
7507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  printer_handle.OpenPrinter(printer_name_wide.c_str());
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(printer_handle.IsValid());
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ret = false;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (printer_handle.IsValid()) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD bytes_needed = 0;
7551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    GetJob(printer_handle.Get(), job_id, 1, NULL, 0, &bytes_needed);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD last_error = GetLastError();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_INVALID_PARAMETER != last_error) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ERROR_INVALID_PARAMETER normally means that the job id is not valid.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(last_error == ERROR_INSUFFICIENT_BUFFER);
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scoped_ptr<BYTE[]> job_info_buffer(new BYTE[bytes_needed]);
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (GetJob(printer_handle.Get(), job_id, 1, job_info_buffer.get(),
7621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 bytes_needed, &bytes_needed)) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        JOB_INFO_1 *job_info =
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reinterpret_cast<JOB_INFO_1 *>(job_info_buffer.get());
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (job_info->pStatus) {
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::WideToUTF8(job_info->pStatus, wcslen(job_info->pStatus),
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           &job_details->status_message);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        job_details->platform_status_flags = job_info->Status;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((job_info->Status & JOB_STATUS_COMPLETE) ||
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (job_info->Status & JOB_STATUS_PRINTED)) {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_COMPLETED;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (job_info->Status & JOB_STATUS_ERROR) {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_ERROR;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          job_details->status = PRINT_JOB_STATUS_IN_PROGRESS;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        job_details->total_pages = job_info->TotalPages;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        job_details->pages_printed = job_info->PagesPrinted;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = true;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrintServerWatcher*
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystemWin::CreatePrintServerWatcher() {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrintServerWatcherWin();
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher(
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name) {
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!printer_name.empty());
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrinterWatcherWin(printer_name);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrintSystem::JobSpooler* PrintSystemWin::CreateJobSpooler() {
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new JobSpoolerWin();
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrintSystemWin::UseCddAndCjt() {
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return use_cdd_;
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string PrintSystemWin::GetSupportedMimeTypes() {
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string result;
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!use_cdd_) {
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = kContentTypeXPS;
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result += ",";
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result += kContentTypePDF;
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
816f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string PrintSystemWin::GetPrinterDriverInfo(
817f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& printer_name) const {
818f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return print_backend_->GetPrinterDriverInfo(printer_name);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* print_system_settings) {
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new PrintSystemWin;
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace cloud_print
829