Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: chrome/service/cloud_print/print_system_win.cc

Issue 3051006: Used the service utility process host to render PDFs in a sandbox for the Win... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: CUPS tweaks Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/service/cloud_print/print_system.h" 5 #include "chrome/service/cloud_print/print_system.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <objidl.h> 8 #include <objidl.h>
9 #include <ocidl.h> 9 #include <ocidl.h>
10 #include <olectl.h> 10 #include <olectl.h>
11 #include <prntvpt.h> 11 #include <prntvpt.h>
12 #include <winspool.h> 12 #include <winspool.h>
13 13
14 #include "base/lock.h" 14 #include "base/lock.h"
15 #include "base/file_util.h"
15 #include "base/object_watcher.h" 16 #include "base/object_watcher.h"
16 #include "base/scoped_bstr_win.h" 17 #include "base/scoped_bstr_win.h"
17 #include "base/scoped_comptr_win.h" 18 #include "base/scoped_comptr_win.h"
18 #include "base/scoped_handle_win.h" 19 #include "base/scoped_handle_win.h"
19 #include "base/scoped_ptr.h" 20 #include "base/scoped_ptr.h"
20 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
22 #include "chrome/service/service_process.h"
23 #include "chrome/service/service_utility_process_host.h"
24 #include "gfx/rect.h"
25 #include "printing/native_metafile.h"
26 #include "printing/page_range.h"
21 27
22 #pragma comment(lib, "prntvpt.lib") 28 #pragma comment(lib, "prntvpt.lib")
23 #pragma comment(lib, "rpcrt4.lib") 29 #pragma comment(lib, "rpcrt4.lib")
24 30
25 namespace { 31 namespace {
26 32
27 class DevMode { 33 class DevMode {
28 public: 34 public:
29 DevMode() : dm_(NULL) {} 35 DevMode() : dm_(NULL) {}
30 ~DevMode() { Free(); } 36 ~DevMode() { Free(); }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 if (SUCCEEDED(hr)) { 116 if (SUCCEEDED(hr)) {
111 dev_mode->Allocate(size); 117 dev_mode->Allocate(size);
112 memcpy(dev_mode->dm_, dm, size); 118 memcpy(dev_mode->dm_, dm, size);
113 PTReleaseMemory(dm); 119 PTReleaseMemory(dm);
114 } 120 }
115 PTCloseProvider(provider); 121 PTCloseProvider(provider);
116 } 122 }
117 return hr; 123 return hr;
118 } 124 }
119 125
120 HRESULT PrintPdf2DC(HDC dc, const FilePath& pdf_filename) {
121 HRESULT hr = E_NOTIMPL;
122 // TODO(sanjeevr): Implement this.
123 NOTIMPLEMENTED();
124 return hr;
125 }
126
127 } // namespace 126 } // namespace
128 127
129 namespace cloud_print { 128 namespace cloud_print {
130 129
131 class PrintSystemWatcherWin 130 class PrintSystemWatcherWin
132 : public base::ObjectWatcher::Delegate { 131 : public base::ObjectWatcher::Delegate {
133 public: 132 public:
134 PrintSystemWatcherWin() 133 PrintSystemWatcherWin()
135 : printer_(NULL), printer_change_(NULL), delegate_(NULL) { 134 : printer_(NULL), printer_change_(NULL), delegate_(NULL) {
136 } 135 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 class PrintSystemWin : public PrintSystem { 247 class PrintSystemWin : public PrintSystem {
249 public: 248 public:
250 virtual void EnumeratePrinters(PrinterList* printer_list); 249 virtual void EnumeratePrinters(PrinterList* printer_list);
251 250
252 virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name, 251 virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name,
253 PrinterCapsAndDefaults* printer_info); 252 PrinterCapsAndDefaults* printer_info);
254 253
255 virtual bool ValidatePrintTicket(const std::string& printer_name, 254 virtual bool ValidatePrintTicket(const std::string& printer_name,
256 const std::string& print_ticket_data); 255 const std::string& print_ticket_data);
257 256
258 virtual bool SpoolPrintJob(const std::string& print_ticket,
259 const FilePath& print_data_file_path,
260 const std::string& print_data_mime_type,
261 const std::string& printer_name,
262 const std::string& job_title,
263 PlatformJobId* job_id_ret);
264
265 virtual bool GetJobDetails(const std::string& printer_name, 257 virtual bool GetJobDetails(const std::string& printer_name,
266 PlatformJobId job_id, 258 PlatformJobId job_id,
267 PrintJobDetails *job_details); 259 PrintJobDetails *job_details);
268 260
269 virtual bool IsValidPrinter(const std::string& printer_name); 261 virtual bool IsValidPrinter(const std::string& printer_name);
270 262
271 class PrintServerWatcherWin 263 class PrintServerWatcherWin
272 : public PrintSystem::PrintServerWatcher, 264 : public PrintSystem::PrintServerWatcher,
273 public PrintSystemWatcherWinDelegate { 265 public PrintSystemWatcherWinDelegate {
274 public: 266 public:
275 PrintServerWatcherWin() {} 267 PrintServerWatcherWin() {}
276 268
277 // PrintSystem::PrintServerWatcher interface 269 // PrintSystem::PrintServerWatcher interface
278 virtual bool StartWatching( 270 virtual bool StartWatching(
279 PrintSystem::PrintServerWatcher::Delegate* delegate) { 271 PrintSystem::PrintServerWatcher::Delegate* delegate) {
280 delegate_ = delegate; 272 delegate_ = delegate;
281 return watcher_.Start(std::string(), this); 273 return watcher_.Start(std::string(), this);
282 } 274 }
283 virtual bool StopWatching() { 275 virtual bool StopWatching() {
284 bool ret = watcher_.Stop(); 276 bool ret = watcher_.Stop();
285 delegate_ = NULL; 277 delegate_ = NULL;
286 return ret; 278 return ret;
287 } 279 }
288 280
289 // PrintSystemWatcherWin::Delegate interface 281 // PrintSystemWatcherWin::Delegate interface
290 virtual void OnPrinterAdded() { 282 virtual void OnPrinterAdded() {
291 delegate_->OnPrinterAdded(); 283 delegate_->OnPrinterAdded();
292 } 284 }
293 virtual void OnPrinterDeleted() { 285 virtual void OnPrinterDeleted() {
294 NOTREACHED();
295 } 286 }
296 virtual void OnPrinterChanged() { 287 virtual void OnPrinterChanged() {
297 NOTREACHED();
298 } 288 }
299 virtual void OnJobChanged() { 289 virtual void OnJobChanged() {
300 NOTREACHED();
301 } 290 }
302 291
303 private: 292 private:
304 PrintSystem::PrintServerWatcher::Delegate* delegate_; 293 PrintSystem::PrintServerWatcher::Delegate* delegate_;
305 PrintSystemWatcherWin watcher_; 294 PrintSystemWatcherWin watcher_;
306 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin); 295 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin);
307 }; 296 };
308 297
309 class PrinterWatcherWin 298 class PrinterWatcherWin
310 : public PrintSystem::PrinterWatcher, 299 : public PrintSystem::PrinterWatcher,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 delegate_->OnJobChanged(); 331 delegate_->OnJobChanged();
343 } 332 }
344 333
345 private: 334 private:
346 std::string printer_name_; 335 std::string printer_name_;
347 PrintSystem::PrinterWatcher::Delegate* delegate_; 336 PrintSystem::PrinterWatcher::Delegate* delegate_;
348 PrintSystemWatcherWin watcher_; 337 PrintSystemWatcherWin watcher_;
349 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin); 338 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin);
350 }; 339 };
351 340
341 class JobSpoolerWin : public PrintSystem::JobSpooler {
342 public:
343 JobSpoolerWin() : core_(new Core) {}
344 // PrintSystem::JobSpooler implementation.
345 virtual bool Spool(const std::string& print_ticket,
346 const FilePath& print_data_file_path,
347 const std::string& print_data_mime_type,
348 const std::string& printer_name,
349 const std::string& job_title,
350 JobSpooler::Delegate* delegate) {
351 return core_->Spool(print_ticket, print_data_file_path,
352 print_data_mime_type, printer_name, job_title,
353 delegate);
354 }
355 private:
356 // We use a Core class because we want a separate RefCountedThreadSafe
357 // implementation for ServiceUtilityProcessHost::Client.
358 class Core : public ServiceUtilityProcessHost::Client {
359 public:
360 Core()
361 : last_page_printed_(-1), job_id_(-1), delegate_(NULL), saved_dc_(0) {
362 }
363 ~Core() {
364 }
365 bool Spool(const std::string& print_ticket,
366 const FilePath& print_data_file_path,
367 const std::string& print_data_mime_type,
368 const std::string& printer_name,
369 const std::string& job_title,
370 JobSpooler::Delegate* delegate) {
371 if (delegate_) {
372 // We are already in the process of printing.
373 NOTREACHED();
374 return false;
375 }
376 last_page_printed_ = -1;
377 // We only support PDFs for now.
378 if (print_data_mime_type != "application/pdf") {
379 NOTREACHED();
380 return false;
381 }
382
383 if (!InitXPSModule()) {
384 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
385 return false;
386 }
387 DevMode pt_dev_mode;
388 HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
389 &pt_dev_mode);
390 if (FAILED(hr)) {
391 NOTREACHED();
392 return false;
393 }
394 HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(),
395 NULL, pt_dev_mode.dm_);
396 if (!dc) {
397 NOTREACHED();
398 return false;
399 }
400 hr = E_FAIL;
401 DOCINFO di = {0};
402 di.cbSize = sizeof(DOCINFO);
403 std::wstring doc_name = UTF8ToWide(job_title);
404 di.lpszDocName = doc_name.c_str();
405 job_id_ = StartDoc(dc, &di);
406 if (SP_ERROR == job_id_)
407 return false;
408
409 printer_dc_.Set(dc);
410
411 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
412 saved_dc_ = SaveDC(printer_dc_.Get());
413 SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
414 XFORM xform = {0};
415 xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
416 static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
417 ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
418 print_data_file_path_ = print_data_file_path;
419 delegate_ = delegate;
420 RenderNextPDFPages();
421 return true;
422 }
423
424 // ServiceUtilityProcessHost::Client implementation.
425 virtual void OnRenderPDFPagesToMetafileSucceeded(
426 const printing::NativeMetafile& metafile,
427 int highest_rendered_page_number) {
428 metafile.SafePlayback(printer_dc_.Get());
429 bool done_printing = (highest_rendered_page_number !=
430 last_page_printed_ + kPageCountPerBatch);
431 last_page_printed_ = highest_rendered_page_number;
432 if (done_printing)
433 PrintJobDone();
434 else
435 RenderNextPDFPages();
436 }
437 virtual void OnRenderPDFPagesToMetafileFailed() {
438 PrintJobDone();
439 }
440 virtual void OnChildDied() {
441 PrintJobDone();
442 }
443 private:
444 void PrintJobDone() {
445 // If there is no delegate, then there is nothing pending to process.
446 if (!delegate_)
447 return;
448 RestoreDC(printer_dc_.Get(), saved_dc_);
449 EndDoc(printer_dc_.Get());
450 if (-1 == last_page_printed_) {
451 delegate_->OnJobSpoolFailed();
452 } else {
453 delegate_->OnJobSpoolSucceeded(job_id_);
454 }
455 delegate_ = NULL;
456 }
457 void RenderNextPDFPages() {
458 printing::PageRange range;
459 // Render 10 pages at a time.
460 range.from = last_page_printed_ + 1;
461 range.to = last_page_printed_ + kPageCountPerBatch;
462 std::vector<printing::PageRange> page_ranges;
463 page_ranges.push_back(range);
464
465 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
466 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
467 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
468 gfx::Rect render_area(0, 0, dc_width, dc_height);
469 g_service_process->io_thread()->message_loop_proxy()->PostTask(
470 FROM_HERE,
471 NewRunnableMethod(
472 this,
473 &JobSpoolerWin::Core::RenderPDFPagesInSandbox,
474 print_data_file_path_,
475 render_area,
476 printer_dpi,
477 page_ranges,
478 base::MessageLoopProxy::CreateForCurrentThread()));
479 }
480 // Called on the service process IO thread.
481 void RenderPDFPagesInSandbox(
482 const FilePath& pdf_path, const gfx::Rect& render_area,
483 int render_dpi, const std::vector<printing::PageRange>& page_ranges,
484 const scoped_refptr<base::MessageLoopProxy>&
485 client_message_loop_proxy) {
486 DCHECK(g_service_process->io_thread()->message_loop_proxy()->
487 BelongsToCurrentThread());
488 scoped_ptr<ServiceUtilityProcessHost> utility_host(
489 new ServiceUtilityProcessHost(this, client_message_loop_proxy));
490 if (utility_host->StartRenderPDFPagesToMetafile(pdf_path,
491 render_area,
492 render_dpi,
493 page_ranges)) {
494 // The object will self-destruct when the child process dies.
495 utility_host.release();
496 }
497 }
498 static const int kPageCountPerBatch = 10;
499 int last_page_printed_;
500 PlatformJobId job_id_;
501 PrintSystem::JobSpooler::Delegate* delegate_;
502 int saved_dc_;
503 ScopedHDC printer_dc_;
504 FilePath print_data_file_path_;
505 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin::Core);
506 };
507 scoped_refptr<Core> core_;
508 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin);
509 };
510
352 virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher(); 511 virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher();
353 virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( 512 virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
354 const std::string& printer_name); 513 const std::string& printer_name);
514 virtual PrintSystem::JobSpooler* CreateJobSpooler();
355 }; 515 };
356 516
357 void PrintSystemWin::EnumeratePrinters(PrinterList* printer_list) { 517 void PrintSystemWin::EnumeratePrinters(PrinterList* printer_list) {
358 DCHECK(printer_list); 518 DCHECK(printer_list);
359 DWORD bytes_needed = 0; 519 DWORD bytes_needed = 0;
360 DWORD count_returned = 0; 520 DWORD count_returned = 0;
361 BOOL ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, 521 BOOL ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2,
362 NULL, 0, &bytes_needed, &count_returned); 522 NULL, 0, &bytes_needed, &count_returned);
363 if (0 != bytes_needed) { 523 if (0 != bytes_needed) {
364 scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]); 524 scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 print_ticket_stream.get(), 639 print_ticket_stream.get(),
480 NULL, 640 NULL,
481 kPTJobScope, 641 kPTJobScope,
482 result_ticket_stream.get(), 642 result_ticket_stream.get(),
483 error.Receive())); 643 error.Receive()));
484 PTCloseProvider(provider); 644 PTCloseProvider(provider);
485 } 645 }
486 return ret; 646 return ret;
487 } 647 }
488 648
489 bool PrintSystemWin::SpoolPrintJob(const std::string& print_ticket,
490 const FilePath& print_data_file_path,
491 const std::string& print_data_mime_type,
492 const std::string& printer_name,
493 const std::string& job_title,
494 PlatformJobId* job_id_ret) {
495 if (!InitXPSModule()) {
496 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
497 return false;
498 }
499 DevMode pt_dev_mode;
500 HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket, &pt_dev_mode);
501 if (FAILED(hr)) {
502 NOTREACHED();
503 return false;
504 }
505 ScopedHDC dc(CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(), NULL,
506 pt_dev_mode.dm_));
507 if (!dc.Get()) {
508 NOTREACHED();
509 return false;
510 }
511 hr = E_FAIL;
512 DOCINFO di = {0};
513 di.cbSize = sizeof(DOCINFO);
514 std::wstring doc_name = UTF8ToWide(job_title);
515 di.lpszDocName = doc_name.c_str();
516 int job_id = StartDoc(dc.Get(), &di);
517 if (SP_ERROR != job_id) {
518 if (print_data_mime_type == "application/pdf") {
519 hr = PrintPdf2DC(dc.Get(), print_data_file_path);
520 } else {
521 NOTREACHED();
522 }
523 EndDoc(dc.Get());
524 if (SUCCEEDED(hr) && job_id_ret) {
525 *job_id_ret = job_id;
526 }
527 }
528 return SUCCEEDED(hr);
529 }
530
531 bool PrintSystemWin::GetJobDetails(const std::string& printer_name, 649 bool PrintSystemWin::GetJobDetails(const std::string& printer_name,
532 PlatformJobId job_id, 650 PlatformJobId job_id,
533 PrintJobDetails *job_details) { 651 PrintJobDetails *job_details) {
534 DCHECK(job_details); 652 DCHECK(job_details);
535 HANDLE printer_handle = NULL; 653 HANDLE printer_handle = NULL;
536 std::wstring printer_name_wide = UTF8ToWide(printer_name); 654 std::wstring printer_name_wide = UTF8ToWide(printer_name);
537 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle, 655 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle,
538 NULL); 656 NULL);
539 DCHECK(printer_handle); 657 DCHECK(printer_handle);
540 bool ret = false; 658 bool ret = false;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 PrintSystemWin::CreatePrintServerWatcher() { 708 PrintSystemWin::CreatePrintServerWatcher() {
591 return new PrintServerWatcherWin(); 709 return new PrintServerWatcherWin();
592 } 710 }
593 711
594 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( 712 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher(
595 const std::string& printer_name) { 713 const std::string& printer_name) {
596 DCHECK(!printer_name.empty()); 714 DCHECK(!printer_name.empty());
597 return new PrinterWatcherWin(printer_name); 715 return new PrinterWatcherWin(printer_name);
598 } 716 }
599 717
718 PrintSystem::JobSpooler*
719 PrintSystemWin::CreateJobSpooler() {
720 return new JobSpoolerWin();
721 }
722
600 std::string PrintSystem::GenerateProxyId() { 723 std::string PrintSystem::GenerateProxyId() {
601 GUID proxy_id = {0}; 724 GUID proxy_id = {0};
602 HRESULT hr = UuidCreate(&proxy_id); 725 HRESULT hr = UuidCreate(&proxy_id);
603 DCHECK(SUCCEEDED(hr)); 726 DCHECK(SUCCEEDED(hr));
604 wchar_t* proxy_id_as_string = NULL; 727 wchar_t* proxy_id_as_string = NULL;
605 UuidToString(&proxy_id, reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); 728 UuidToString(&proxy_id, reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string));
606 DCHECK(proxy_id_as_string); 729 DCHECK(proxy_id_as_string);
607 std::string ret; 730 std::string ret;
608 WideToUTF8(proxy_id_as_string, wcslen(proxy_id_as_string), &ret); 731 WideToUTF8(proxy_id_as_string, wcslen(proxy_id_as_string), &ret);
609 RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); 732 RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string));
610 return ret; 733 return ret;
611 } 734 }
612 735
613 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( 736 scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
614 const DictionaryValue* print_system_settings) { 737 const DictionaryValue* print_system_settings) {
615 return new PrintSystemWin; 738 return new PrintSystemWin;
616 } 739 }
617 740
618 } // namespace cloud_print 741 } // namespace cloud_print
619 742
OLDNEW
« no previous file with comments | « chrome/service/cloud_print/print_system_cups.cc ('k') | chrome/service/cloud_print/printer_job_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698