diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-10 06:05:10 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-10 06:05:10 +0000 |
commit | 6ed843366f5ee413ca48f1ad245ab0000981b8f6 (patch) | |
tree | 65fdf8e17fd1497bac0ae399641984d69b1ec376 /chrome/service | |
parent | 3b260c1bc932cadfbd3b0d1aea26132488f9a842 (diff) | |
download | chromium_src-6ed843366f5ee413ca48f1ad245ab0000981b8f6.zip chromium_src-6ed843366f5ee413ca48f1ad245ab0000981b8f6.tar.gz chromium_src-6ed843366f5ee413ca48f1ad245ab0000981b8f6.tar.bz2 |
Move some nested classes out of PrintSystemWin
BUG=317027
Review URL: https://codereview.chromium.org/67753002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service')
-rw-r--r-- | chrome/service/cloud_print/print_system_win.cc | 861 |
1 files changed, 428 insertions, 433 deletions
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 408d6a9..778e97e 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc @@ -32,7 +32,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/rect.h" -#pragma comment(lib, "rpcrt4.lib") // for UuidToString & Co. +namespace cloud_print { namespace { @@ -144,10 +144,6 @@ HRESULT PrintTicketToDevMode(const std::string& printer_name, return hr; } -} // namespace - -namespace cloud_print { - class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate { public: PrintSystemWatcherWin() @@ -248,501 +244,499 @@ class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate { // PrintSystemWin watchers from wrong Delegate, giving C2664 and C2259 errors. typedef PrintSystemWatcherWin::Delegate PrintSystemWatcherWinDelegate; -class PrintSystemWin : public PrintSystem { +class PrintServerWatcherWin + : public PrintSystem::PrintServerWatcher, + public PrintSystemWatcherWinDelegate { public: - PrintSystemWin(); + PrintServerWatcherWin() : delegate_(NULL) {} - // 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; + // PrintSystem::PrintServerWatcher implementation. + virtual bool StartWatching( + PrintSystem::PrintServerWatcher::Delegate* delegate) OVERRIDE{ + delegate_ = delegate; + return watcher_.Start(std::string(), this); + } - class PrintServerWatcherWin - : public PrintSystem::PrintServerWatcher, - public PrintSystemWatcherWinDelegate { - public: - PrintServerWatcherWin() : delegate_(NULL) {} + virtual bool StopWatching() OVERRIDE{ + bool ret = watcher_.Stop(); + delegate_ = NULL; + return ret; + } - // PrintSystem::PrintServerWatcher implementation. - virtual bool StartWatching( - PrintSystem::PrintServerWatcher::Delegate* delegate) OVERRIDE{ - delegate_ = delegate; - return watcher_.Start(std::string(), this); - } + // PrintSystemWatcherWin::Delegate implementation. + virtual void OnPrinterAdded() OVERRIDE { + delegate_->OnPrinterAdded(); + } + virtual void OnPrinterDeleted() OVERRIDE {} + virtual void OnPrinterChanged() OVERRIDE {} + virtual void OnJobChanged() OVERRIDE {} - virtual bool StopWatching() OVERRIDE{ - bool ret = watcher_.Stop(); - delegate_ = NULL; - return ret; - } + protected: + virtual ~PrintServerWatcherWin() {} - // PrintSystemWatcherWin::Delegate implementation. - virtual void OnPrinterAdded() OVERRIDE { - delegate_->OnPrinterAdded(); - } - virtual void OnPrinterDeleted() OVERRIDE {} - virtual void OnPrinterChanged() OVERRIDE {} - virtual void OnJobChanged() OVERRIDE {} + private: + PrintSystem::PrintServerWatcher::Delegate* delegate_; + PrintSystemWatcherWin watcher_; - protected: - virtual ~PrintServerWatcherWin() {} + DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin); +}; - private: - PrintSystem::PrintServerWatcher::Delegate* delegate_; - PrintSystemWatcherWin watcher_; +class PrinterWatcherWin + : public PrintSystem::PrinterWatcher, + public PrintSystemWatcherWinDelegate { + public: + explicit PrinterWatcherWin(const std::string& printer_name) + : printer_name_(printer_name), + delegate_(NULL) { + } - DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin); - }; + // PrintSystem::PrinterWatcher implementation. + virtual bool StartWatching( + PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE { + delegate_ = delegate; + return watcher_.Start(printer_name_, this); + } - class PrinterWatcherWin - : public PrintSystem::PrinterWatcher, - public PrintSystemWatcherWinDelegate { - public: - explicit PrinterWatcherWin(const std::string& printer_name) - : printer_name_(printer_name), - delegate_(NULL) { - } - - // PrintSystem::PrinterWatcher implementation. - virtual bool StartWatching( - PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE { - delegate_ = delegate; - return watcher_.Start(printer_name_, this); - } + virtual bool StopWatching() OVERRIDE { + bool ret = watcher_.Stop(); + delegate_ = NULL; + return ret; + } - virtual bool StopWatching() OVERRIDE { - bool ret = watcher_.Stop(); - delegate_ = NULL; - return ret; - } + virtual bool GetCurrentPrinterInfo( + printing::PrinterBasicInfo* printer_info) OVERRIDE { + return watcher_.GetCurrentPrinterInfo(printer_info); + } - virtual bool GetCurrentPrinterInfo( - printing::PrinterBasicInfo* printer_info) OVERRIDE { - return watcher_.GetCurrentPrinterInfo(printer_info); - } + // PrintSystemWatcherWin::Delegate implementation. + virtual void OnPrinterAdded() OVERRIDE { + NOTREACHED(); + } + virtual void OnPrinterDeleted() OVERRIDE { + delegate_->OnPrinterDeleted(); + } + virtual void OnPrinterChanged() OVERRIDE { + delegate_->OnPrinterChanged(); + } + virtual void OnJobChanged() OVERRIDE { + delegate_->OnJobChanged(); + } - // PrintSystemWatcherWin::Delegate implementation. - virtual void OnPrinterAdded() OVERRIDE { - NOTREACHED(); - } - virtual void OnPrinterDeleted() OVERRIDE { - delegate_->OnPrinterDeleted(); - } - virtual void OnPrinterChanged() OVERRIDE { - delegate_->OnPrinterChanged(); - } - virtual void OnJobChanged() OVERRIDE { - delegate_->OnJobChanged(); - } + protected: + virtual ~PrinterWatcherWin() {} - protected: - virtual ~PrinterWatcherWin() {} + private: + std::string printer_name_; + PrintSystem::PrinterWatcher::Delegate* delegate_; + PrintSystemWatcherWin watcher_; - private: - std::string printer_name_; - PrintSystem::PrinterWatcher::Delegate* delegate_; - PrintSystemWatcherWin watcher_; + DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin); +}; - DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin); - }; +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() {} - class JobSpoolerWin : public PrintSystem::JobSpooler { + 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: - 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. + 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)); - 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) { + if (delegate_) { + // We are already in the process of printing. + NOTREACHED(); + return false; } - - ~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. + 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; } - 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", 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); - string16 doc_name = 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 { + + HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(), + NULL, pt_dev_mode.dm_); + if (!dc) { 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); - } + hr = E_FAIL; + DOCINFO di = {0}; + di.cbSize = sizeof(DOCINFO); + string16 doc_name = 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; - // 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(); + 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; + } - // 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); - 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 || - (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); - done = true; - } else { - job_progress_watcher_.StopWatching(); - job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); - } - if (done) - com_initializer_.reset(); - } + 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); + } - virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE { + // 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(); + } - virtual void OnChildDied() OVERRIDE { - PrintJobDone(); + // 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); + 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 || + (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); + done = true; + } else { + job_progress_watcher_.StopWatching(); + job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); } + if (done) + com_initializer_.reset(); + } - 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); - }; + virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE { + PrintJobDone(); + } - 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; - } + virtual void OnChildDied() OVERRIDE { + PrintJobDone(); + } - 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())); + 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) { } - - // 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(); + ~PrintJobCanceler() { + if (job_ptr_ && *job_ptr_) { + (*job_ptr_)->Cancel(); + job_ptr_->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; - - scoped_ptr<base::win::ScopedCOMInitializer> com_initializer( - new base::win::ScopedCOMInitializer( - base::win::ScopedCOMInitializer::kMTA)); - PrintJobCanceler job_canceler(&xps_print_job_); - base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream; - base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream; - if (FAILED(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()))) - 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; + void reset() { job_ptr_ = NULL; } - job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); - com_initializer_.swap(com_initializer); - job_canceler.reset(); - return true; - } + private: + base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_; - // 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_; - scoped_ptr<base::win::ScopedCOMInitializer> com_initializer_; - - DISALLOW_COPY_AND_ASSIGN(Core); + DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler); }; - 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 PrinterCapsAndDefaultsCallback& callback) - : printer_name_(printer_name), callback_(callback) { - } - - // ServiceUtilityProcessHost::Client implementation. - virtual void OnChildDied() OVERRIDE { - OnGetPrinterCapsAndDefaultsFailed(printer_name_); - } - - virtual void OnGetPrinterCapsAndDefaultsSucceeded( - const std::string& printer_name, - const printing::PrinterCapsAndDefaults& caps_and_defaults) OVERRIDE { - callback_.Run(true, printer_name, caps_and_defaults); - callback_.Reset(); - Release(); - } - - virtual void OnGetPrinterCapsAndDefaultsFailed( - const std::string& printer_name) OVERRIDE { - printing::PrinterCapsAndDefaults caps_and_defaults; - callback_.Run(false, printer_name, caps_and_defaults); - callback_.Reset(); - Release(); + 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 Start() { + 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(&PrinterCapsHandler::GetPrinterCapsAndDefaultsImpl, this, - base::MessageLoopProxy::current())); + base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox, this, + print_data_file_path_, render_area, printer_dpi, + page_ranges, base::MessageLoopProxy::current())); } - private: - // Called on the service process IO thread. - void GetPrinterCapsAndDefaultsImpl( + // 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)); - if (utility_host->StartGetPrinterCapsAndDefaults(printer_name_)) { + // 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(); - } else { - client_message_loop_proxy->PostTask( - FROM_HERE, - base::Bind(&PrinterCapsHandler::OnGetPrinterCapsAndDefaultsFailed, - this, printer_name_)); } } - std::string printer_name_; - PrinterCapsAndDefaultsCallback callback_; + 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; + + scoped_ptr<base::win::ScopedCOMInitializer> com_initializer( + new base::win::ScopedCOMInitializer( + base::win::ScopedCOMInitializer::kMTA)); + PrintJobCanceler job_canceler(&xps_print_job_); + base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream; + base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream; + if (FAILED(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()))) + 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); + com_initializer_.swap(com_initializer); + 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_; + scoped_ptr<base::win::ScopedCOMInitializer> com_initializer_; + + 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 { + OnGetPrinterCapsAndDefaultsFailed(printer_name_); + } + + virtual void OnGetPrinterCapsAndDefaultsSucceeded( + const std::string& printer_name, + const printing::PrinterCapsAndDefaults& caps_and_defaults) OVERRIDE { + callback_.Run(true, printer_name, caps_and_defaults); + callback_.Reset(); + Release(); + } + + virtual void OnGetPrinterCapsAndDefaultsFailed( + const std::string& printer_name) OVERRIDE { + printing::PrinterCapsAndDefaults caps_and_defaults; + callback_.Run(false, 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::OnGetPrinterCapsAndDefaultsFailed, + this, printer_name_)); + } + } + 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; @@ -897,6 +891,7 @@ std::string PrintSystemWin::GetSupportedMimeTypes() { return "application/pdf"; } +} // namespace scoped_refptr<PrintSystem> PrintSystem::CreateInstance( const base::DictionaryValue* print_system_settings) { |