summaryrefslogtreecommitdiffstats
path: root/chrome/service
diff options
context:
space:
mode:
authorvitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 19:29:59 +0000
committervitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 19:29:59 +0000
commitc05c8d1e4b6f9b261acab5b22e74ad4d0c161191 (patch)
tree68a01154139a8b7821a831c63e02681ae4345b53 /chrome/service
parenteafbd05a88cd1b8fa050d1f0a2b68d65a2b70472 (diff)
downloadchromium_src-c05c8d1e4b6f9b261acab5b22e74ad4d0c161191.zip
chromium_src-c05c8d1e4b6f9b261acab5b22e74ad4d0c161191.tar.gz
chromium_src-c05c8d1e4b6f9b261acab5b22e74ad4d0c161191.tar.bz2
Revert 234174 "Extract XPS code from PrintSystemWin"
No need in this split. > Extract XPS code from PrintSystemWin. > > BUG=317027 > > Review URL: https://codereview.chromium.org/61673004 TBR=noamsml BUG=317027 Review URL: https://codereview.chromium.org/144003022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249471 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service')
-rw-r--r--chrome/service/cloud_print/print_system_win.cc571
-rw-r--r--chrome/service/cloud_print/print_system_win.h37
-rw-r--r--chrome/service/cloud_print/print_system_xps_win.cc583
3 files changed, 568 insertions, 623 deletions
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index f46c2af..1d4d902 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -2,17 +2,105 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/service/cloud_print/print_system_win.h"
+#include "chrome/service/cloud_print/print_system.h"
+#include "base/file_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/object_watcher.h"
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/scoped_hdc.h"
#include "chrome/common/crash_keys.h"
+#include "chrome/service/service_process.h"
+#include "chrome/service/service_utility_process_host.h"
+#include "grit/generated_resources.h"
#include "printing/backend/win_helper.h"
+#include "printing/emf_win.h"
+#include "printing/page_range.h"
+#include "printing/printing_utils.h"
+#include "ui/base/l10n/l10n_util.h"
namespace cloud_print {
namespace {
+class DevMode {
+ public:
+ DevMode() : dm_(NULL) {}
+ ~DevMode() { Free(); }
+
+ void Allocate(int size) {
+ Free();
+ dm_ = reinterpret_cast<DEVMODE*>(new char[size]);
+ }
+
+ void Free() {
+ if (dm_)
+ delete [] dm_;
+ dm_ = NULL;
+ }
+
+ DEVMODE* dm_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DevMode);
+};
+
+HRESULT StreamFromPrintTicket(const std::string& print_ticket,
+ IStream** stream) {
+ DCHECK(stream);
+ HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ ULONG bytes_written = 0;
+ (*stream)->Write(print_ticket.c_str(), print_ticket.length(), &bytes_written);
+ DCHECK(bytes_written == print_ticket.length());
+ LARGE_INTEGER pos = {0};
+ ULARGE_INTEGER new_pos = {0};
+ (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos);
+ return S_OK;
+}
+
+HRESULT PrintTicketToDevMode(const std::string& printer_name,
+ const std::string& print_ticket,
+ DevMode* dev_mode) {
+ DCHECK(dev_mode);
+ printing::ScopedXPSInitializer xps_initializer;
+ if (!xps_initializer.initialized()) {
+ // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
+ return E_FAIL;
+ }
+
+ base::win::ScopedComPtr<IStream> pt_stream;
+ HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ HPTPROVIDER provider = NULL;
+ hr = printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name), 1,
+ &provider);
+ if (SUCCEEDED(hr)) {
+ ULONG size = 0;
+ DEVMODE* dm = NULL;
+ // Use kPTJobScope, because kPTDocumentScope breaks duplex.
+ hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider,
+ pt_stream,
+ kUserDefaultDevmode,
+ kPTJobScope,
+ &size,
+ &dm,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ dev_mode->Allocate(size);
+ memcpy(dev_mode->dm_, dm, size);
+ printing::XPSModule::ReleaseMemory(dm);
+ }
+ printing::XPSModule::CloseProvider(provider);
+ }
+ return hr;
+}
+
class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate {
public:
PrintSystemWatcherWin()
@@ -197,13 +285,421 @@ class PrinterWatcherWin
DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin);
};
-} // namespace
+class JobSpoolerWin : public PrintSystem::JobSpooler {
+ public:
+ JobSpoolerWin() : core_(new Core) {}
+
+ // PrintSystem::JobSpooler implementation.
+ virtual bool Spool(const std::string& print_ticket,
+ const base::FilePath& print_data_file_path,
+ const std::string& print_data_mime_type,
+ const std::string& printer_name,
+ const std::string& job_title,
+ const std::vector<std::string>& tags,
+ JobSpooler::Delegate* delegate) OVERRIDE {
+ // TODO(gene): add tags handling.
+ scoped_refptr<printing::PrintBackend> print_backend(
+ printing::PrintBackend::CreateInstance(NULL));
+ crash_keys::ScopedPrinterInfo crash_key(
+ print_backend->GetPrinterDriverInfo(printer_name));
+ return core_->Spool(print_ticket, print_data_file_path,
+ print_data_mime_type, printer_name, job_title,
+ delegate);
+ }
+
+ protected:
+ virtual ~JobSpoolerWin() {}
+
+ private:
+ // We use a Core class because we want a separate RefCountedThreadSafe
+ // implementation for ServiceUtilityProcessHost::Client.
+ class Core : public ServiceUtilityProcessHost::Client,
+ public base::win::ObjectWatcher::Delegate {
+ public:
+ Core()
+ : last_page_printed_(-1),
+ job_id_(-1),
+ delegate_(NULL),
+ saved_dc_(0) {
+ }
+
+ ~Core() {}
+
+ bool Spool(const std::string& print_ticket,
+ const base::FilePath& print_data_file_path,
+ const std::string& print_data_mime_type,
+ const std::string& printer_name,
+ const std::string& job_title,
+ JobSpooler::Delegate* delegate) {
+ scoped_refptr<printing::PrintBackend> print_backend(
+ printing::PrintBackend::CreateInstance(NULL));
+ crash_keys::ScopedPrinterInfo crash_key(
+ print_backend->GetPrinterDriverInfo(printer_name));
+ if (delegate_) {
+ // We are already in the process of printing.
+ NOTREACHED();
+ return false;
+ }
+ last_page_printed_ = -1;
+ // We only support PDF and XPS documents for now.
+ if (print_data_mime_type == "application/pdf") {
+ DevMode pt_dev_mode;
+ HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
+ &pt_dev_mode);
+ if (FAILED(hr)) {
+ NOTREACHED();
+ return false;
+ }
+
+ HDC dc = CreateDC(L"WINSPOOL", base::UTF8ToWide(printer_name).c_str(),
+ NULL, pt_dev_mode.dm_);
+ if (!dc) {
+ NOTREACHED();
+ return false;
+ }
+ hr = E_FAIL;
+ DOCINFO di = {0};
+ di.cbSize = sizeof(DOCINFO);
+ base::string16 doc_name = base::UTF8ToUTF16(job_title);
+ DCHECK(printing::SimplifyDocumentTitle(doc_name) == doc_name);
+ di.lpszDocName = doc_name.c_str();
+ job_id_ = StartDoc(dc, &di);
+ if (job_id_ <= 0)
+ return false;
+
+ printer_dc_.Set(dc);
+ saved_dc_ = SaveDC(printer_dc_.Get());
+ print_data_file_path_ = print_data_file_path;
+ delegate_ = delegate;
+ RenderNextPDFPages();
+ } else if (print_data_mime_type == "application/vnd.ms-xpsdocument") {
+ bool ret = PrintXPSDocument(printer_name,
+ job_title,
+ print_data_file_path,
+ print_ticket);
+ if (ret)
+ delegate_ = delegate;
+ return ret;
+ } else {
+ NOTREACHED();
+ return false;
+ }
+ return true;
+ }
+
+ void PreparePageDCForPrinting(HDC, double scale_factor) {
+ SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
+ // Setup the matrix to translate and scale to the right place. Take in
+ // account the scale factor.
+ // Note that the printing output is relative to printable area of
+ // the page. That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
+ int offset_x = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETX);
+ int offset_y = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETY);
+ XFORM xform = {0};
+ xform.eDx = static_cast<float>(-offset_x);
+ xform.eDy = static_cast<float>(-offset_y);
+ xform.eM11 = xform.eM22 = 1.0 / scale_factor;
+ SetWorldTransform(printer_dc_.Get(), &xform);
+ }
+
+ // ServiceUtilityProcessHost::Client implementation.
+ virtual void OnRenderPDFPagesToMetafileSucceeded(
+ const printing::Emf& metafile,
+ int highest_rendered_page_number,
+ double scale_factor) OVERRIDE {
+ PreparePageDCForPrinting(printer_dc_.Get(), scale_factor);
+ metafile.SafePlayback(printer_dc_.Get());
+ bool done_printing = (highest_rendered_page_number !=
+ last_page_printed_ + kPageCountPerBatch);
+ last_page_printed_ = highest_rendered_page_number;
+ if (done_printing)
+ PrintJobDone();
+ else
+ RenderNextPDFPages();
+ }
+
+ // base::win::ObjectWatcher::Delegate implementation.
+ virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
+ DCHECK(xps_print_job_);
+ DCHECK(object == job_progress_event_.Get());
+ ResetEvent(job_progress_event_.Get());
+ if (!delegate_)
+ return;
+ XPS_JOB_STATUS job_status = {0};
+ xps_print_job_->GetJobStatus(&job_status);
+ if ((job_status.completion == XPS_JOB_CANCELLED) ||
+ (job_status.completion == XPS_JOB_FAILED)) {
+ delegate_->OnJobSpoolFailed();
+ } else if (job_status.jobId ||
+ (job_status.completion == XPS_JOB_COMPLETED)) {
+ // Note: In the case of the XPS document being printed to the
+ // Microsoft XPS Document Writer, it seems to skip spooling the job
+ // and goes to the completed state without ever assigning a job id.
+ delegate_->OnJobSpoolSucceeded(job_status.jobId);
+ } else {
+ job_progress_watcher_.StopWatching();
+ job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
+ }
+ }
+
+ virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE {
+ PrintJobDone();
+ }
+
+ virtual void OnChildDied() OVERRIDE {
+ PrintJobDone();
+ }
+
+ private:
+ // Helper class to allow PrintXPSDocument() to have multiple exits.
+ class PrintJobCanceler {
+ public:
+ explicit PrintJobCanceler(
+ base::win::ScopedComPtr<IXpsPrintJob>* job_ptr)
+ : job_ptr_(job_ptr) {
+ }
+ ~PrintJobCanceler() {
+ if (job_ptr_ && *job_ptr_) {
+ (*job_ptr_)->Cancel();
+ job_ptr_->Release();
+ }
+ }
+
+ void reset() { job_ptr_ = NULL; }
+
+ private:
+ base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler);
+ };
+
+ void PrintJobDone() {
+ // If there is no delegate, then there is nothing pending to process.
+ if (!delegate_)
+ return;
+ RestoreDC(printer_dc_.Get(), saved_dc_);
+ EndDoc(printer_dc_.Get());
+ if (-1 == last_page_printed_) {
+ delegate_->OnJobSpoolFailed();
+ } else {
+ delegate_->OnJobSpoolSucceeded(job_id_);
+ }
+ delegate_ = NULL;
+ }
+
+ void RenderNextPDFPages() {
+ printing::PageRange range;
+ // Render 10 pages at a time.
+ range.from = last_page_printed_ + 1;
+ range.to = last_page_printed_ + kPageCountPerBatch;
+ std::vector<printing::PageRange> page_ranges;
+ page_ranges.push_back(range);
+
+ int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
+ int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
+ int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
+ gfx::Rect render_area(0, 0, dc_width, dc_height);
+ g_service_process->io_thread()->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox, this,
+ print_data_file_path_, render_area, printer_dpi,
+ page_ranges, base::MessageLoopProxy::current()));
+ }
+
+ // Called on the service process IO thread.
+ void RenderPDFPagesInSandbox(
+ const base::FilePath& pdf_path, const gfx::Rect& render_area,
+ int render_dpi, const std::vector<printing::PageRange>& page_ranges,
+ const scoped_refptr<base::MessageLoopProxy>&
+ client_message_loop_proxy) {
+ DCHECK(g_service_process->io_thread()->message_loop_proxy()->
+ BelongsToCurrentThread());
+ scoped_ptr<ServiceUtilityProcessHost> utility_host(
+ new ServiceUtilityProcessHost(this, client_message_loop_proxy));
+ // TODO(gene): For now we disabling autorotation for CloudPrinting.
+ // Landscape/Portrait setting is passed in the print ticket and
+ // server is generating portrait PDF always.
+ // We should enable autorotation once server will be able to generate
+ // PDF that matches paper size and orientation.
+ if (utility_host->StartRenderPDFPagesToMetafile(
+ pdf_path,
+ printing::PdfRenderSettings(render_area, render_dpi, false),
+ page_ranges)) {
+ // The object will self-destruct when the child process dies.
+ utility_host.release();
+ }
+ }
+
+ bool PrintXPSDocument(const std::string& printer_name,
+ const std::string& job_title,
+ const base::FilePath& print_data_file_path,
+ const std::string& print_ticket) {
+ if (!printing::XPSPrintModule::Init())
+ return false;
+
+ job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
+ if (!job_progress_event_.Get())
+ return false;
+
+ PrintJobCanceler job_canceler(&xps_print_job_);
+ base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream;
+ base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream;
+ if (FAILED(printing::XPSPrintModule::StartXpsPrintJob(
+ base::UTF8ToWide(printer_name).c_str(),
+ base::UTF8ToWide(job_title).c_str(),
+ NULL, job_progress_event_.Get(), NULL, NULL, NULL,
+ xps_print_job_.Receive(), doc_stream.Receive(),
+ print_ticket_stream.Receive())))
+ return false;
+
+ ULONG print_bytes_written = 0;
+ if (FAILED(print_ticket_stream->Write(print_ticket.c_str(),
+ print_ticket.length(),
+ &print_bytes_written)))
+ return false;
+ DCHECK_EQ(print_ticket.length(), print_bytes_written);
+ if (FAILED(print_ticket_stream->Close()))
+ return false;
+
+ std::string document_data;
+ base::ReadFileToString(print_data_file_path, &document_data);
+ ULONG doc_bytes_written = 0;
+ if (FAILED(doc_stream->Write(document_data.c_str(),
+ document_data.length(),
+ &doc_bytes_written)))
+ return false;
+ DCHECK_EQ(document_data.length(), doc_bytes_written);
+ if (FAILED(doc_stream->Close()))
+ return false;
+
+ job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
+ job_canceler.reset();
+ return true;
+ }
+
+ // Some Cairo-generated PDFs from Chrome OS result in huge metafiles.
+ // So the PageCountPerBatch is set to 1 for now.
+ // TODO(sanjeevr): Figure out a smarter way to determine the pages per
+ // batch. Filed a bug to track this at
+ // http://code.google.com/p/chromium/issues/detail?id=57350.
+ static const int kPageCountPerBatch = 1;
+
+ int last_page_printed_;
+ PlatformJobId job_id_;
+ PrintSystem::JobSpooler::Delegate* delegate_;
+ int saved_dc_;
+ base::win::ScopedCreateDC printer_dc_;
+ base::FilePath print_data_file_path_;
+ base::win::ScopedHandle job_progress_event_;
+ base::win::ObjectWatcher job_progress_watcher_;
+ base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+ };
+ scoped_refptr<Core> core_;
+
+ DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin);
+};
+
+// A helper class to handle the response from the utility process to the
+// request to fetch printer capabilities and defaults.
+class PrinterCapsHandler : public ServiceUtilityProcessHost::Client {
+ public:
+ PrinterCapsHandler(
+ const std::string& printer_name,
+ const PrintSystem::PrinterCapsAndDefaultsCallback& callback)
+ : printer_name_(printer_name), callback_(callback) {
+ }
+
+ // ServiceUtilityProcessHost::Client implementation.
+ virtual void OnChildDied() OVERRIDE {
+ OnGetPrinterCapsAndDefaults(false, printer_name_,
+ printing::PrinterCapsAndDefaults());
+ }
+
+ virtual void OnGetPrinterCapsAndDefaults(
+ bool succeeded,
+ const std::string& printer_name,
+ const printing::PrinterCapsAndDefaults& caps_and_defaults) OVERRIDE {
+ callback_.Run(succeeded, printer_name, caps_and_defaults);
+ callback_.Reset();
+ Release();
+ }
+
+ void Start() {
+ g_service_process->io_thread()->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrinterCapsHandler::GetPrinterCapsAndDefaultsImpl, this,
+ base::MessageLoopProxy::current()));
+ }
+
+ private:
+ // Called on the service process IO thread.
+ void GetPrinterCapsAndDefaultsImpl(
+ const scoped_refptr<base::MessageLoopProxy>&
+ client_message_loop_proxy) {
+ DCHECK(g_service_process->io_thread()->message_loop_proxy()->
+ BelongsToCurrentThread());
+ scoped_ptr<ServiceUtilityProcessHost> utility_host(
+ new ServiceUtilityProcessHost(this, client_message_loop_proxy));
+ if (utility_host->StartGetPrinterCapsAndDefaults(printer_name_)) {
+ // The object will self-destruct when the child process dies.
+ utility_host.release();
+ } else {
+ client_message_loop_proxy->PostTask(
+ FROM_HERE,
+ base::Bind(&PrinterCapsHandler::OnChildDied, this));
+ }
+ }
+
+ std::string printer_name_;
+ PrintSystem::PrinterCapsAndDefaultsCallback callback_;
+};
+
+class PrintSystemWin : public PrintSystem {
+ public:
+ PrintSystemWin();
+
+ // PrintSystem implementation.
+ virtual PrintSystemResult Init() OVERRIDE;
+ virtual PrintSystem::PrintSystemResult EnumeratePrinters(
+ printing::PrinterList* printer_list) OVERRIDE;
+ virtual void GetPrinterCapsAndDefaults(
+ const std::string& printer_name,
+ const PrinterCapsAndDefaultsCallback& callback) OVERRIDE;
+ virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;
+ virtual bool ValidatePrintTicket(
+ const std::string& printer_name,
+ const std::string& print_ticket_data) OVERRIDE;
+ virtual bool GetJobDetails(const std::string& printer_name,
+ PlatformJobId job_id,
+ PrintJobDetails *job_details) OVERRIDE;
+ virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() OVERRIDE;
+ virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
+ const std::string& printer_name) OVERRIDE;
+ virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE;
+ virtual std::string GetSupportedMimeTypes() OVERRIDE;
+
+ private:
+ std::string PrintSystemWin::GetPrinterDriverInfo(
+ const std::string& printer_name) const;
+
+ scoped_refptr<printing::PrintBackend> print_backend_;
+ DISALLOW_COPY_AND_ASSIGN(PrintSystemWin);
+};
PrintSystemWin::PrintSystemWin() {
print_backend_ = printing::PrintBackend::CreateInstance(NULL);
}
-PrintSystemWin::~PrintSystemWin() {
+PrintSystem::PrintSystemResult PrintSystemWin::Init() {
+ if (!printing::XPSModule::Init()) {
+ std::string message = l10n_util::GetStringFUTF8(
+ IDS_CLOUD_PRINT_XPS_UNAVAILABLE,
+ l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
+ return PrintSystemResult(false, message);
+ }
+ return PrintSystemResult(true, std::string());
}
PrintSystem::PrintSystemResult PrintSystemWin::EnumeratePrinters(
@@ -212,10 +708,62 @@ PrintSystem::PrintSystemResult PrintSystemWin::EnumeratePrinters(
return PrintSystemResult(ret, std::string());
}
+void PrintSystemWin::GetPrinterCapsAndDefaults(
+ const std::string& printer_name,
+ const PrinterCapsAndDefaultsCallback& callback) {
+ // Launch as child process to retrieve the capabilities and defaults because
+ // this involves invoking a printer driver DLL and crashes have been known to
+ // occur.
+ PrinterCapsHandler* handler =
+ new PrinterCapsHandler(printer_name, callback);
+ handler->AddRef();
+ handler->Start();
+}
+
bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) {
return print_backend_->IsValidPrinter(printer_name);
}
+bool PrintSystemWin::ValidatePrintTicket(
+ const std::string& printer_name,
+ const std::string& print_ticket_data) {
+ crash_keys::ScopedPrinterInfo crash_key(GetPrinterDriverInfo(printer_name));
+ printing::ScopedXPSInitializer xps_initializer;
+ if (!xps_initializer.initialized()) {
+ // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
+ return false;
+ }
+ bool ret = false;
+ HPTPROVIDER provider = NULL;
+ printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name.c_str()),
+ 1,
+ &provider);
+ if (provider) {
+ base::win::ScopedComPtr<IStream> print_ticket_stream;
+ CreateStreamOnHGlobal(NULL, TRUE, print_ticket_stream.Receive());
+ ULONG bytes_written = 0;
+ print_ticket_stream->Write(print_ticket_data.c_str(),
+ print_ticket_data.length(),
+ &bytes_written);
+ DCHECK(bytes_written == print_ticket_data.length());
+ LARGE_INTEGER pos = {0};
+ ULARGE_INTEGER new_pos = {0};
+ print_ticket_stream->Seek(pos, STREAM_SEEK_SET, &new_pos);
+ base::win::ScopedBstr error;
+ base::win::ScopedComPtr<IStream> result_ticket_stream;
+ CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.Receive());
+ ret = SUCCEEDED(printing::XPSModule::MergeAndValidatePrintTicket(
+ provider,
+ print_ticket_stream.get(),
+ NULL,
+ kPTJobScope,
+ result_ticket_stream.get(),
+ error.Receive()));
+ printing::XPSModule::CloseProvider(provider);
+ }
+ return ret;
+}
+
bool PrintSystemWin::GetJobDetails(const std::string& printer_name,
PlatformJobId job_id,
PrintJobDetails *job_details) {
@@ -272,9 +820,26 @@ PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher(
return new PrinterWatcherWin(printer_name);
}
+PrintSystem::JobSpooler* PrintSystemWin::CreateJobSpooler() {
+ return new JobSpoolerWin();
+}
+
+std::string PrintSystemWin::GetSupportedMimeTypes() {
+ if (printing::XPSPrintModule::Init())
+ return "application/vnd.ms-xpsdocument,application/pdf";
+ return "application/pdf";
+}
+
std::string PrintSystemWin::GetPrinterDriverInfo(
const std::string& printer_name) const {
return print_backend_->GetPrinterDriverInfo(printer_name);
}
+} // namespace
+
+scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
+ const base::DictionaryValue* print_system_settings) {
+ return new PrintSystemWin;
+}
+
} // namespace cloud_print
diff --git a/chrome/service/cloud_print/print_system_win.h b/chrome/service/cloud_print/print_system_win.h
deleted file mode 100644
index b98ba89..0000000
--- a/chrome/service/cloud_print/print_system_win.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_WIN_H_
-#define CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_WIN_H_
-
-#include "chrome/service/cloud_print/print_system.h"
-
-namespace cloud_print {
-
-class PrintSystemWin : public PrintSystem {
- public:
- PrintSystemWin();
- virtual ~PrintSystemWin();
-
- // PrintSystem implementation.
- virtual PrintSystem::PrintSystemResult EnumeratePrinters(
- printing::PrinterList* printer_list) OVERRIDE;
- virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;
- virtual bool GetJobDetails(const std::string& printer_name,
- PlatformJobId job_id,
- PrintJobDetails *job_details) OVERRIDE;
- virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() OVERRIDE;
- virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
- const std::string& printer_name) OVERRIDE;
-
- protected:
- std::string GetPrinterDriverInfo(const std::string& printer_name) const;
-
- private:
- scoped_refptr<printing::PrintBackend> print_backend_;
-};
-
-} // namespace cloud_print
-
-#endif // CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_WIN_H_
diff --git a/chrome/service/cloud_print/print_system_xps_win.cc b/chrome/service/cloud_print/print_system_xps_win.cc
deleted file mode 100644
index 30c04bf..0000000
--- a/chrome/service/cloud_print/print_system_xps_win.cc
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/file_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/object_watcher.h"
-#include "base/win/scoped_bstr.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/scoped_hdc.h"
-#include "chrome/common/crash_keys.h"
-#include "chrome/service/cloud_print/print_system_win.h"
-#include "chrome/service/service_process.h"
-#include "chrome/service/service_utility_process_host.h"
-#include "grit/generated_resources.h"
-#include "printing/backend/win_helper.h"
-#include "printing/emf_win.h"
-#include "printing/page_range.h"
-#include "printing/printing_utils.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace cloud_print {
-
-namespace {
-
-class DevMode {
- public:
- DevMode() : dm_(NULL) {}
- ~DevMode() { Free(); }
-
- void Allocate(int size) {
- Free();
- dm_ = reinterpret_cast<DEVMODE*>(new char[size]);
- }
-
- void Free() {
- if (dm_)
- delete [] dm_;
- dm_ = NULL;
- }
-
- DEVMODE* dm_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DevMode);
-};
-
-HRESULT StreamFromPrintTicket(const std::string& print_ticket,
- IStream** stream) {
- DCHECK(stream);
- HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
- if (FAILED(hr)) {
- return hr;
- }
- ULONG bytes_written = 0;
- (*stream)->Write(print_ticket.c_str(), print_ticket.length(), &bytes_written);
- DCHECK(bytes_written == print_ticket.length());
- LARGE_INTEGER pos = {0};
- ULARGE_INTEGER new_pos = {0};
- (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos);
- return S_OK;
-}
-
-HRESULT PrintTicketToDevMode(const std::string& printer_name,
- const std::string& print_ticket,
- DevMode* dev_mode) {
- DCHECK(dev_mode);
- printing::ScopedXPSInitializer xps_initializer;
- if (!xps_initializer.initialized()) {
- // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
- return E_FAIL;
- }
-
- base::win::ScopedComPtr<IStream> pt_stream;
- HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive());
- if (FAILED(hr))
- return hr;
-
- HPTPROVIDER provider = NULL;
- hr = printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name), 1,
- &provider);
- if (SUCCEEDED(hr)) {
- ULONG size = 0;
- DEVMODE* dm = NULL;
- // Use kPTJobScope, because kPTDocumentScope breaks duplex.
- hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider,
- pt_stream,
- kUserDefaultDevmode,
- kPTJobScope,
- &size,
- &dm,
- NULL);
- if (SUCCEEDED(hr)) {
- dev_mode->Allocate(size);
- memcpy(dev_mode->dm_, dm, size);
- printing::XPSModule::ReleaseMemory(dm);
- }
- printing::XPSModule::CloseProvider(provider);
- }
- return hr;
-}
-
-class JobSpoolerWin : public PrintSystem::JobSpooler {
- public:
- JobSpoolerWin() : core_(new Core) {}
-
- // PrintSystem::JobSpooler implementation.
- virtual bool Spool(const std::string& print_ticket,
- const base::FilePath& print_data_file_path,
- const std::string& print_data_mime_type,
- const std::string& printer_name,
- const std::string& job_title,
- const std::vector<std::string>& tags,
- JobSpooler::Delegate* delegate) OVERRIDE {
- // TODO(gene): add tags handling.
- scoped_refptr<printing::PrintBackend> print_backend(
- printing::PrintBackend::CreateInstance(NULL));
- crash_keys::ScopedPrinterInfo crash_key(
- print_backend->GetPrinterDriverInfo(printer_name));
- return core_->Spool(print_ticket, print_data_file_path,
- print_data_mime_type, printer_name, job_title,
- delegate);
- }
-
- protected:
- virtual ~JobSpoolerWin() {}
-
- private:
- // We use a Core class because we want a separate RefCountedThreadSafe
- // implementation for ServiceUtilityProcessHost::Client.
- class Core : public ServiceUtilityProcessHost::Client,
- public base::win::ObjectWatcher::Delegate {
- public:
- Core()
- : last_page_printed_(-1),
- job_id_(-1),
- delegate_(NULL),
- saved_dc_(0) {
- }
-
- ~Core() {}
-
- bool Spool(const std::string& print_ticket,
- const base::FilePath& print_data_file_path,
- const std::string& print_data_mime_type,
- const std::string& printer_name,
- const std::string& job_title,
- JobSpooler::Delegate* delegate) {
- scoped_refptr<printing::PrintBackend> print_backend(
- printing::PrintBackend::CreateInstance(NULL));
- crash_keys::ScopedPrinterInfo crash_key(
- print_backend->GetPrinterDriverInfo(printer_name));
- if (delegate_) {
- // We are already in the process of printing.
- NOTREACHED();
- return false;
- }
- last_page_printed_ = -1;
- // We only support PDF and XPS documents for now.
- if (print_data_mime_type == "application/pdf") {
- DevMode pt_dev_mode;
- HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
- &pt_dev_mode);
- if (FAILED(hr)) {
- NOTREACHED();
- return false;
- }
-
- HDC dc = CreateDC(L"WINSPOOL", base::UTF8ToWide(printer_name).c_str(),
- NULL, pt_dev_mode.dm_);
- if (!dc) {
- NOTREACHED();
- return false;
- }
- hr = E_FAIL;
- DOCINFO di = {0};
- di.cbSize = sizeof(DOCINFO);
- base::string16 doc_name = base::UTF8ToUTF16(job_title);
- DCHECK(printing::SimplifyDocumentTitle(doc_name) == doc_name);
- di.lpszDocName = doc_name.c_str();
- job_id_ = StartDoc(dc, &di);
- if (job_id_ <= 0)
- return false;
-
- printer_dc_.Set(dc);
- saved_dc_ = SaveDC(printer_dc_.Get());
- print_data_file_path_ = print_data_file_path;
- delegate_ = delegate;
- RenderNextPDFPages();
- } else if (print_data_mime_type == "application/vnd.ms-xpsdocument") {
- bool ret = PrintXPSDocument(printer_name,
- job_title,
- print_data_file_path,
- print_ticket);
- if (ret)
- delegate_ = delegate;
- return ret;
- } else {
- NOTREACHED();
- return false;
- }
- return true;
- }
-
- void PreparePageDCForPrinting(HDC, double scale_factor) {
- SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
- // Setup the matrix to translate and scale to the right place. Take in
- // account the scale factor.
- // Note that the printing output is relative to printable area of
- // the page. That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
- int offset_x = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETX);
- int offset_y = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETY);
- XFORM xform = {0};
- xform.eDx = static_cast<float>(-offset_x);
- xform.eDy = static_cast<float>(-offset_y);
- xform.eM11 = xform.eM22 = 1.0 / scale_factor;
- SetWorldTransform(printer_dc_.Get(), &xform);
- }
-
- // ServiceUtilityProcessHost::Client implementation.
- virtual void OnRenderPDFPagesToMetafileSucceeded(
- const printing::Emf& metafile,
- int highest_rendered_page_number,
- double scale_factor) OVERRIDE {
- PreparePageDCForPrinting(printer_dc_.Get(), scale_factor);
- metafile.SafePlayback(printer_dc_.Get());
- bool done_printing = (highest_rendered_page_number !=
- last_page_printed_ + kPageCountPerBatch);
- last_page_printed_ = highest_rendered_page_number;
- if (done_printing)
- PrintJobDone();
- else
- RenderNextPDFPages();
- }
-
- // base::win::ObjectWatcher::Delegate implementation.
- virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
- DCHECK(xps_print_job_);
- DCHECK(object == job_progress_event_.Get());
- ResetEvent(job_progress_event_.Get());
- if (!delegate_)
- return;
- XPS_JOB_STATUS job_status = {0};
- xps_print_job_->GetJobStatus(&job_status);
- if ((job_status.completion == XPS_JOB_CANCELLED) ||
- (job_status.completion == XPS_JOB_FAILED)) {
- delegate_->OnJobSpoolFailed();
- } else if (job_status.jobId ||
- (job_status.completion == XPS_JOB_COMPLETED)) {
- // Note: In the case of the XPS document being printed to the
- // Microsoft XPS Document Writer, it seems to skip spooling the job
- // and goes to the completed state without ever assigning a job id.
- delegate_->OnJobSpoolSucceeded(job_status.jobId);
- } else {
- job_progress_watcher_.StopWatching();
- job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
- }
- }
-
- virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE {
- PrintJobDone();
- }
-
- virtual void OnChildDied() OVERRIDE {
- PrintJobDone();
- }
-
- private:
- // Helper class to allow PrintXPSDocument() to have multiple exits.
- class PrintJobCanceler {
- public:
- explicit PrintJobCanceler(
- base::win::ScopedComPtr<IXpsPrintJob>* job_ptr)
- : job_ptr_(job_ptr) {
- }
- ~PrintJobCanceler() {
- if (job_ptr_ && *job_ptr_) {
- (*job_ptr_)->Cancel();
- job_ptr_->Release();
- }
- }
-
- void reset() { job_ptr_ = NULL; }
-
- private:
- base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler);
- };
-
- void PrintJobDone() {
- // If there is no delegate, then there is nothing pending to process.
- if (!delegate_)
- return;
- RestoreDC(printer_dc_.Get(), saved_dc_);
- EndDoc(printer_dc_.Get());
- if (-1 == last_page_printed_) {
- delegate_->OnJobSpoolFailed();
- } else {
- delegate_->OnJobSpoolSucceeded(job_id_);
- }
- delegate_ = NULL;
- }
-
- void RenderNextPDFPages() {
- printing::PageRange range;
- // Render 10 pages at a time.
- range.from = last_page_printed_ + 1;
- range.to = last_page_printed_ + kPageCountPerBatch;
- std::vector<printing::PageRange> page_ranges;
- page_ranges.push_back(range);
-
- int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
- int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
- int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
- gfx::Rect render_area(0, 0, dc_width, dc_height);
- g_service_process->io_thread()->message_loop_proxy()->PostTask(
- FROM_HERE,
- base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox, this,
- print_data_file_path_, render_area, printer_dpi,
- page_ranges, base::MessageLoopProxy::current()));
- }
-
- // Called on the service process IO thread.
- void RenderPDFPagesInSandbox(
- const base::FilePath& pdf_path, const gfx::Rect& render_area,
- int render_dpi, const std::vector<printing::PageRange>& page_ranges,
- const scoped_refptr<base::MessageLoopProxy>&
- client_message_loop_proxy) {
- DCHECK(g_service_process->io_thread()->message_loop_proxy()->
- BelongsToCurrentThread());
- scoped_ptr<ServiceUtilityProcessHost> utility_host(
- new ServiceUtilityProcessHost(this, client_message_loop_proxy));
- // TODO(gene): For now we disabling autorotation for CloudPrinting.
- // Landscape/Portrait setting is passed in the print ticket and
- // server is generating portrait PDF always.
- // We should enable autorotation once server will be able to generate
- // PDF that matches paper size and orientation.
- if (utility_host->StartRenderPDFPagesToMetafile(
- pdf_path,
- printing::PdfRenderSettings(render_area, render_dpi, false),
- page_ranges)) {
- // The object will self-destruct when the child process dies.
- utility_host.release();
- }
- }
-
- bool PrintXPSDocument(const std::string& printer_name,
- const std::string& job_title,
- const base::FilePath& print_data_file_path,
- const std::string& print_ticket) {
- if (!printing::XPSPrintModule::Init())
- return false;
-
- job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
- if (!job_progress_event_.Get())
- return false;
-
- PrintJobCanceler job_canceler(&xps_print_job_);
- base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream;
- base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream;
- if (FAILED(printing::XPSPrintModule::StartXpsPrintJob(
- base::UTF8ToWide(printer_name).c_str(),
- base::UTF8ToWide(job_title).c_str(),
- NULL, job_progress_event_.Get(), NULL, NULL, NULL,
- xps_print_job_.Receive(), doc_stream.Receive(),
- print_ticket_stream.Receive())))
- return false;
-
- ULONG print_bytes_written = 0;
- if (FAILED(print_ticket_stream->Write(print_ticket.c_str(),
- print_ticket.length(),
- &print_bytes_written)))
- return false;
- DCHECK_EQ(print_ticket.length(), print_bytes_written);
- if (FAILED(print_ticket_stream->Close()))
- return false;
-
- std::string document_data;
- base::ReadFileToString(print_data_file_path, &document_data);
- ULONG doc_bytes_written = 0;
- if (FAILED(doc_stream->Write(document_data.c_str(),
- document_data.length(),
- &doc_bytes_written)))
- return false;
- DCHECK_EQ(document_data.length(), doc_bytes_written);
- if (FAILED(doc_stream->Close()))
- return false;
-
- job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
- job_canceler.reset();
- return true;
- }
-
- // Some Cairo-generated PDFs from Chrome OS result in huge metafiles.
- // So the PageCountPerBatch is set to 1 for now.
- // TODO(sanjeevr): Figure out a smarter way to determine the pages per
- // batch. Filed a bug to track this at
- // http://code.google.com/p/chromium/issues/detail?id=57350.
- static const int kPageCountPerBatch = 1;
-
- int last_page_printed_;
- PlatformJobId job_id_;
- PrintSystem::JobSpooler::Delegate* delegate_;
- int saved_dc_;
- base::win::ScopedCreateDC printer_dc_;
- base::FilePath print_data_file_path_;
- base::win::ScopedHandle job_progress_event_;
- base::win::ObjectWatcher job_progress_watcher_;
- base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
- };
- scoped_refptr<Core> core_;
-
- DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin);
-};
-
-// A helper class to handle the response from the utility process to the
-// request to fetch printer capabilities and defaults.
-class PrinterCapsHandler : public ServiceUtilityProcessHost::Client {
- public:
- PrinterCapsHandler(
- const std::string& printer_name,
- const PrintSystem::PrinterCapsAndDefaultsCallback& callback)
- : printer_name_(printer_name), callback_(callback) {
- }
-
- // ServiceUtilityProcessHost::Client implementation.
- virtual void OnChildDied() OVERRIDE {
- OnGetPrinterCapsAndDefaults(false, printer_name_,
- printing::PrinterCapsAndDefaults());
- }
-
- virtual void OnGetPrinterCapsAndDefaults(
- bool succeeded,
- const std::string& printer_name,
- const printing::PrinterCapsAndDefaults& caps_and_defaults) OVERRIDE {
- callback_.Run(succeeded, printer_name, caps_and_defaults);
- callback_.Reset();
- Release();
- }
-
- void Start() {
- g_service_process->io_thread()->message_loop_proxy()->PostTask(
- FROM_HERE,
- base::Bind(&PrinterCapsHandler::GetPrinterCapsAndDefaultsImpl, this,
- base::MessageLoopProxy::current()));
- }
-
- private:
- // Called on the service process IO thread.
- void GetPrinterCapsAndDefaultsImpl(
- const scoped_refptr<base::MessageLoopProxy>&
- client_message_loop_proxy) {
- DCHECK(g_service_process->io_thread()->message_loop_proxy()->
- BelongsToCurrentThread());
- scoped_ptr<ServiceUtilityProcessHost> utility_host(
- new ServiceUtilityProcessHost(this, client_message_loop_proxy));
- if (utility_host->StartGetPrinterCapsAndDefaults(printer_name_)) {
- // The object will self-destruct when the child process dies.
- utility_host.release();
- } else {
- client_message_loop_proxy->PostTask(
- FROM_HERE,
- base::Bind(&PrinterCapsHandler::OnChildDied, this));
- }
- }
-
- std::string printer_name_;
- PrintSystem::PrinterCapsAndDefaultsCallback callback_;
-};
-
-class PrintSystemWinXPS : public PrintSystemWin {
- public:
- PrintSystemWinXPS();
- virtual ~PrintSystemWinXPS();
-
- // PrintSystem implementation.
- virtual PrintSystemResult Init() OVERRIDE;
-
- virtual void GetPrinterCapsAndDefaults(
- const std::string& printer_name,
- const PrinterCapsAndDefaultsCallback& callback) OVERRIDE;
-
- virtual bool PrintSystemWinXPS::ValidatePrintTicket(
- const std::string& printer_name,
- const std::string& print_ticket_data) OVERRIDE;
-
- virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE;
-
- virtual std::string GetSupportedMimeTypes() OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PrintSystemWinXPS);
-};
-
-PrintSystemWinXPS::PrintSystemWinXPS() {
-}
-
-PrintSystemWinXPS::~PrintSystemWinXPS() {
-}
-
-PrintSystem::PrintSystemResult PrintSystemWinXPS::Init() {
- if (!printing::XPSModule::Init()) {
- std::string message = l10n_util::GetStringFUTF8(
- IDS_CLOUD_PRINT_XPS_UNAVAILABLE,
- l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
- return PrintSystemResult(false, message);
- }
- return PrintSystemResult(true, std::string());
-}
-
-void PrintSystemWinXPS::GetPrinterCapsAndDefaults(
- const std::string& printer_name,
- const PrinterCapsAndDefaultsCallback& callback) {
- // Launch as child process to retrieve the capabilities and defaults because
- // this involves invoking a printer driver DLL and crashes have been known to
- // occur.
- PrinterCapsHandler* handler =
- new PrinterCapsHandler(printer_name, callback);
- handler->AddRef();
- handler->Start();
-}
-
-bool PrintSystemWinXPS::ValidatePrintTicket(
- const std::string& printer_name,
- const std::string& print_ticket_data) {
- crash_keys::ScopedPrinterInfo crash_key(GetPrinterDriverInfo(printer_name));
- printing::ScopedXPSInitializer xps_initializer;
- if (!xps_initializer.initialized()) {
- // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
- return false;
- }
- bool ret = false;
- HPTPROVIDER provider = NULL;
- printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name.c_str()),
- 1,
- &provider);
- if (provider) {
- base::win::ScopedComPtr<IStream> print_ticket_stream;
- CreateStreamOnHGlobal(NULL, TRUE, print_ticket_stream.Receive());
- ULONG bytes_written = 0;
- print_ticket_stream->Write(print_ticket_data.c_str(),
- print_ticket_data.length(),
- &bytes_written);
- DCHECK(bytes_written == print_ticket_data.length());
- LARGE_INTEGER pos = {0};
- ULARGE_INTEGER new_pos = {0};
- print_ticket_stream->Seek(pos, STREAM_SEEK_SET, &new_pos);
- base::win::ScopedBstr error;
- base::win::ScopedComPtr<IStream> result_ticket_stream;
- CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.Receive());
- ret = SUCCEEDED(printing::XPSModule::MergeAndValidatePrintTicket(
- provider,
- print_ticket_stream.get(),
- NULL,
- kPTJobScope,
- result_ticket_stream.get(),
- error.Receive()));
- printing::XPSModule::CloseProvider(provider);
- }
- return ret;
-}
-
-PrintSystem::JobSpooler* PrintSystemWinXPS::CreateJobSpooler() {
- return new JobSpoolerWin();
-}
-
-std::string PrintSystemWinXPS::GetSupportedMimeTypes() {
- if (printing::XPSPrintModule::Init())
- return "application/vnd.ms-xpsdocument,application/pdf";
- return "application/pdf";
-}
-
-} // namespace
-
-scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
- const base::DictionaryValue* print_system_settings) {
- return new PrintSystemWinXPS;
-}
-
-} // namespace cloud_print