| Index: chrome/service/cloud_print/print_system_win.cc
|
| ===================================================================
|
| --- chrome/service/cloud_print/print_system_win.cc (revision 74874)
|
| +++ chrome/service/cloud_print/print_system_win.cc (working copy)
|
| @@ -6,8 +6,14 @@
|
|
|
| #include <objidl.h>
|
| #include <winspool.h>
|
| +#if defined(_WIN32_WINNT)
|
| +#undef _WIN32_WINNT
|
| +#endif // defined(_WIN32_WINNT)
|
| +#define _WIN32_WINNT _WIN32_WINNT_WIN7
|
| +#include <xpsprint.h>
|
|
|
| #include "base/file_path.h"
|
| +#include "base/file_util.h"
|
| #include "base/scoped_ptr.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "base/win/object_watcher.h"
|
| @@ -366,10 +372,15 @@
|
| private:
|
| // We use a Core class because we want a separate RefCountedThreadSafe
|
| // implementation for ServiceUtilityProcessHost::Client.
|
| - class Core : public 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) {
|
| + : last_page_printed_(-1),
|
| + job_id_(-1),
|
| + delegate_(NULL),
|
| + saved_dc_(0),
|
| + should_couninit_(false) {
|
| }
|
| ~Core() {
|
| }
|
| @@ -385,47 +396,54 @@
|
| return false;
|
| }
|
| last_page_printed_ = -1;
|
| - // We only support PDFs for now.
|
| - if (print_data_mime_type != "application/pdf") {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| + // 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;
|
| + }
|
|
|
| - 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", 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);
|
| + std::wstring doc_name = UTF8ToWide(job_title);
|
| + di.lpszDocName = doc_name.c_str();
|
| + job_id_ = StartDoc(dc, &di);
|
| + if (job_id_ <= 0)
|
| + return false;
|
|
|
| - HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(),
|
| - NULL, pt_dev_mode.dm_);
|
| - if (!dc) {
|
| + printer_dc_.Set(dc);
|
| + int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
|
| + saved_dc_ = SaveDC(printer_dc_.Get());
|
| + SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
|
| + XFORM xform = {0};
|
| + xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
|
| + static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
|
| + ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
|
| + 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;
|
| }
|
| - hr = E_FAIL;
|
| - DOCINFO di = {0};
|
| - di.cbSize = sizeof(DOCINFO);
|
| - std::wstring doc_name = UTF8ToWide(job_title);
|
| - di.lpszDocName = doc_name.c_str();
|
| - job_id_ = StartDoc(dc, &di);
|
| - if (job_id_ <= 0)
|
| - return false;
|
| -
|
| - printer_dc_.Set(dc);
|
| -
|
| - int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
|
| - saved_dc_ = SaveDC(printer_dc_.Get());
|
| - SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
|
| - XFORM xform = {0};
|
| - xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
|
| - static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
|
| - ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
|
| - print_data_file_path_ = print_data_file_path;
|
| - delegate_ = delegate;
|
| - RenderNextPDFPages();
|
| return true;
|
| }
|
|
|
| @@ -442,6 +460,33 @@
|
| else
|
| RenderNextPDFPages();
|
| }
|
| +
|
| + // base::win::ObjectWatcher::Delegate inplementation.
|
| + virtual void OnObjectSignaled(HANDLE object) {
|
| + DCHECK(xps_print_job_);
|
| + if (!delegate_)
|
| + return;
|
| + XPS_JOB_STATUS job_status = {0};
|
| + xps_print_job_->GetJobStatus(&job_status);
|
| + bool done = false;
|
| + if ((job_status.completion == XPS_JOB_CANCELLED) ||
|
| + (job_status.completion == XPS_JOB_FAILED)) {
|
| + delegate_->OnJobSpoolFailed();
|
| + done = true;
|
| + } else if (job_status.jobId) {
|
| + delegate_->OnJobSpoolSucceeded(job_status.jobId);
|
| + done = true;
|
| + } else {
|
| + ResetEvent(job_progress_event_.Get());
|
| + job_progress_watcher_.StopWatching();
|
| + job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
|
| + }
|
| + if (done && should_couninit_) {
|
| + CoUninitialize();
|
| + should_couninit_ = false;
|
| + }
|
| + }
|
| +
|
| virtual void OnRenderPDFPagesToMetafileFailed() {
|
| PrintJobDone();
|
| }
|
| @@ -503,6 +548,67 @@
|
| utility_host.release();
|
| }
|
| }
|
| + bool PrintXPSDocument(const std::string& printer_name,
|
| + const std::string& job_title,
|
| + const 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;
|
| + should_couninit_ = SUCCEEDED(CoInitializeEx(NULL,
|
| + COINIT_MULTITHREADED));
|
| + ScopedComPtr<IXpsPrintJobStream> doc_stream;
|
| + ScopedComPtr<IXpsPrintJobStream> print_ticket_stream;
|
| + bool ret = false;
|
| + // Use nested SUCCEEDED checks because we want a common return point.
|
| + if (SUCCEEDED(printing::XPSPrintModule::StartXpsPrintJob(
|
| + UTF8ToWide(printer_name).c_str(),
|
| + UTF8ToWide(job_title).c_str(),
|
| + NULL,
|
| + job_progress_event_.Get(),
|
| + NULL,
|
| + NULL,
|
| + NULL,
|
| + xps_print_job_.Receive(),
|
| + doc_stream.Receive(),
|
| + print_ticket_stream.Receive()))) {
|
| + ULONG bytes_written = 0;
|
| + if (SUCCEEDED(print_ticket_stream->Write(print_ticket.c_str(),
|
| + print_ticket.length(),
|
| + &bytes_written))) {
|
| + DCHECK(bytes_written == print_ticket.length());
|
| + if (SUCCEEDED(print_ticket_stream->Close())) {
|
| + std::string document_data;
|
| + file_util::ReadFileToString(print_data_file_path, &document_data);
|
| + bytes_written = 0;
|
| + if (SUCCEEDED(doc_stream->Write(document_data.c_str(),
|
| + document_data.length(),
|
| + &bytes_written))) {
|
| + DCHECK(bytes_written == document_data.length());
|
| + if (SUCCEEDED(doc_stream->Close())) {
|
| + job_progress_watcher_.StartWatching(job_progress_event_.Get(),
|
| + this);
|
| + ret = true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (!ret) {
|
| + if (xps_print_job_) {
|
| + xps_print_job_->Cancel();
|
| + xps_print_job_.Release();
|
| + }
|
| + if (should_couninit_) {
|
| + CoUninitialize();
|
| + should_couninit_ = false;
|
| + }
|
| + }
|
| + return ret;
|
| + }
|
| +
|
| // 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
|
| @@ -515,6 +621,10 @@
|
| int saved_dc_;
|
| base::win::ScopedHDC printer_dc_;
|
| FilePath print_data_file_path_;
|
| + base::win::ScopedHandle job_progress_event_;
|
| + base::win::ObjectWatcher job_progress_watcher_;
|
| + ScopedComPtr<IXpsPrintJob> xps_print_job_;
|
| + bool should_couninit_;
|
| DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin::Core);
|
| };
|
| scoped_refptr<Core> core_;
|
| @@ -588,7 +698,9 @@
|
| virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
|
| const std::string& printer_name);
|
| virtual PrintSystem::JobSpooler* CreateJobSpooler();
|
| + virtual std::string GetSupportedMimeTypes();
|
|
|
| +
|
| private:
|
| scoped_refptr<printing::PrintBackend> print_backend_;
|
| };
|
| @@ -728,6 +840,13 @@
|
| return new JobSpoolerWin();
|
| }
|
|
|
| +std::string PrintSystemWin::GetSupportedMimeTypes() {
|
| + if (printing::XPSPrintModule::Init())
|
| + return "application/vnd.ms-xpsdocument,application/pdf";
|
| + return "application/pdf";
|
| +}
|
| +
|
| +
|
| std::string PrintSystem::GenerateProxyId() {
|
| GUID proxy_id = {0};
|
| HRESULT hr = UuidCreate(&proxy_id);
|
|
|