OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <objidl.h> | 7 #include <objidl.h> |
8 #include <winspool.h> | 8 #include <winspool.h> |
9 #include <xpsprint.h> | 9 #include <xpsprint.h> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/file_path.h" | 12 #include "base/file_path.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
16 #include "base/win/object_watcher.h" | 16 #include "base/win/object_watcher.h" |
17 #include "base/win/scoped_bstr.h" | 17 #include "base/win/scoped_bstr.h" |
| 18 #include "base/win/scoped_com_initializer.h" |
18 #include "base/win/scoped_comptr.h" | 19 #include "base/win/scoped_comptr.h" |
19 #include "base/win/scoped_hdc.h" | 20 #include "base/win/scoped_hdc.h" |
20 #include "chrome/common/child_process_logging.h" | 21 #include "chrome/common/child_process_logging.h" |
21 #include "chrome/service/service_process.h" | 22 #include "chrome/service/service_process.h" |
22 #include "chrome/service/service_utility_process_host.h" | 23 #include "chrome/service/service_utility_process_host.h" |
23 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
24 #include "printing/backend/print_backend.h" | 25 #include "printing/backend/print_backend.h" |
25 #include "printing/backend/print_backend_consts.h" | 26 #include "printing/backend/print_backend_consts.h" |
26 #include "printing/backend/win_helper.h" | 27 #include "printing/backend/win_helper.h" |
27 #include "printing/emf_win.h" | 28 #include "printing/emf_win.h" |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 private: | 383 private: |
383 // We use a Core class because we want a separate RefCountedThreadSafe | 384 // We use a Core class because we want a separate RefCountedThreadSafe |
384 // implementation for ServiceUtilityProcessHost::Client. | 385 // implementation for ServiceUtilityProcessHost::Client. |
385 class Core : public ServiceUtilityProcessHost::Client, | 386 class Core : public ServiceUtilityProcessHost::Client, |
386 public base::win::ObjectWatcher::Delegate { | 387 public base::win::ObjectWatcher::Delegate { |
387 public: | 388 public: |
388 Core() | 389 Core() |
389 : last_page_printed_(-1), | 390 : last_page_printed_(-1), |
390 job_id_(-1), | 391 job_id_(-1), |
391 delegate_(NULL), | 392 delegate_(NULL), |
392 saved_dc_(0), | 393 saved_dc_(0) { |
393 should_couninit_(false) { | |
394 } | 394 } |
395 | 395 |
396 ~Core() {} | 396 ~Core() {} |
397 | 397 |
398 bool Spool(const std::string& print_ticket, | 398 bool Spool(const std::string& print_ticket, |
399 const FilePath& print_data_file_path, | 399 const FilePath& print_data_file_path, |
400 const std::string& print_data_mime_type, | 400 const std::string& print_data_mime_type, |
401 const std::string& printer_name, | 401 const std::string& printer_name, |
402 const std::string& job_title, | 402 const std::string& job_title, |
403 JobSpooler::Delegate* delegate) { | 403 JobSpooler::Delegate* delegate) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 (job_status.completion == XPS_JOB_COMPLETED)) { | 507 (job_status.completion == XPS_JOB_COMPLETED)) { |
508 // Note: In the case of the XPS document being printed to the | 508 // Note: In the case of the XPS document being printed to the |
509 // Microsoft XPS Document Writer, it seems to skip spooling the job | 509 // Microsoft XPS Document Writer, it seems to skip spooling the job |
510 // and goes to the completed state without ever assigning a job id. | 510 // and goes to the completed state without ever assigning a job id. |
511 delegate_->OnJobSpoolSucceeded(job_status.jobId); | 511 delegate_->OnJobSpoolSucceeded(job_status.jobId); |
512 done = true; | 512 done = true; |
513 } else { | 513 } else { |
514 job_progress_watcher_.StopWatching(); | 514 job_progress_watcher_.StopWatching(); |
515 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); | 515 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); |
516 } | 516 } |
517 if (done && should_couninit_) { | 517 if (done) |
518 CoUninitialize(); | 518 com_initializer_.reset(); |
519 should_couninit_ = false; | |
520 } | |
521 } | 519 } |
522 | 520 |
523 virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE { | 521 virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE { |
524 PrintJobDone(); | 522 PrintJobDone(); |
525 } | 523 } |
526 | 524 |
527 virtual void OnChildDied() OVERRIDE { | 525 virtual void OnChildDied() OVERRIDE { |
528 PrintJobDone(); | 526 PrintJobDone(); |
529 } | 527 } |
530 | 528 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 | 586 |
589 bool PrintXPSDocument(const std::string& printer_name, | 587 bool PrintXPSDocument(const std::string& printer_name, |
590 const std::string& job_title, | 588 const std::string& job_title, |
591 const FilePath& print_data_file_path, | 589 const FilePath& print_data_file_path, |
592 const std::string& print_ticket) { | 590 const std::string& print_ticket) { |
593 if (!printing::XPSPrintModule::Init()) | 591 if (!printing::XPSPrintModule::Init()) |
594 return false; | 592 return false; |
595 job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); | 593 job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); |
596 if (!job_progress_event_.Get()) | 594 if (!job_progress_event_.Get()) |
597 return false; | 595 return false; |
598 should_couninit_ = SUCCEEDED(CoInitializeEx(NULL, | 596 scoped_ptr<base::win::ScopedCOMInitializer> com_initializer( |
599 COINIT_MULTITHREADED)); | 597 new base::win::ScopedCOMInitializer( |
| 598 base::win::ScopedCOMInitializer::kMTA)); |
600 base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream; | 599 base::win::ScopedComPtr<IXpsPrintJobStream> doc_stream; |
601 base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream; | 600 base::win::ScopedComPtr<IXpsPrintJobStream> print_ticket_stream; |
602 bool ret = false; | 601 bool ret = false; |
603 // Use nested SUCCEEDED checks because we want a common return point. | 602 // Use nested SUCCEEDED checks because we want a common return point. |
604 if (SUCCEEDED(printing::XPSPrintModule::StartXpsPrintJob( | 603 if (SUCCEEDED(printing::XPSPrintModule::StartXpsPrintJob( |
605 UTF8ToWide(printer_name).c_str(), | 604 UTF8ToWide(printer_name).c_str(), |
606 UTF8ToWide(job_title).c_str(), | 605 UTF8ToWide(job_title).c_str(), |
607 NULL, | 606 NULL, |
608 job_progress_event_.Get(), | 607 job_progress_event_.Get(), |
609 NULL, | 608 NULL, |
(...skipping 11 matching lines...) Expand all Loading... |
621 std::string document_data; | 620 std::string document_data; |
622 file_util::ReadFileToString(print_data_file_path, &document_data); | 621 file_util::ReadFileToString(print_data_file_path, &document_data); |
623 bytes_written = 0; | 622 bytes_written = 0; |
624 if (SUCCEEDED(doc_stream->Write(document_data.c_str(), | 623 if (SUCCEEDED(doc_stream->Write(document_data.c_str(), |
625 document_data.length(), | 624 document_data.length(), |
626 &bytes_written))) { | 625 &bytes_written))) { |
627 DCHECK(bytes_written == document_data.length()); | 626 DCHECK(bytes_written == document_data.length()); |
628 if (SUCCEEDED(doc_stream->Close())) { | 627 if (SUCCEEDED(doc_stream->Close())) { |
629 job_progress_watcher_.StartWatching(job_progress_event_.Get(), | 628 job_progress_watcher_.StartWatching(job_progress_event_.Get(), |
630 this); | 629 this); |
| 630 com_initializer_.swap(com_initializer); |
631 ret = true; | 631 ret = true; |
632 } | 632 } |
633 } | 633 } |
634 } | 634 } |
635 } | 635 } |
636 } | 636 } |
637 if (!ret) { | 637 if (!ret) { |
638 if (xps_print_job_) { | 638 if (xps_print_job_) { |
639 xps_print_job_->Cancel(); | 639 xps_print_job_->Cancel(); |
640 xps_print_job_.Release(); | 640 xps_print_job_.Release(); |
641 } | 641 } |
642 if (should_couninit_) { | |
643 CoUninitialize(); | |
644 should_couninit_ = false; | |
645 } | |
646 } | 642 } |
647 return ret; | 643 return ret; |
648 } | 644 } |
649 | 645 |
650 // Some Cairo-generated PDFs from Chrome OS result in huge metafiles. | 646 // Some Cairo-generated PDFs from Chrome OS result in huge metafiles. |
651 // So the PageCountPerBatch is set to 1 for now. | 647 // So the PageCountPerBatch is set to 1 for now. |
652 // TODO(sanjeevr): Figure out a smarter way to determine the pages per | 648 // TODO(sanjeevr): Figure out a smarter way to determine the pages per |
653 // batch. Filed a bug to track this at | 649 // batch. Filed a bug to track this at |
654 // http://code.google.com/p/chromium/issues/detail?id=57350. | 650 // http://code.google.com/p/chromium/issues/detail?id=57350. |
655 static const int kPageCountPerBatch = 1; | 651 static const int kPageCountPerBatch = 1; |
656 int last_page_printed_; | 652 int last_page_printed_; |
657 PlatformJobId job_id_; | 653 PlatformJobId job_id_; |
658 PrintSystem::JobSpooler::Delegate* delegate_; | 654 PrintSystem::JobSpooler::Delegate* delegate_; |
659 int saved_dc_; | 655 int saved_dc_; |
660 base::win::ScopedCreateDC printer_dc_; | 656 base::win::ScopedCreateDC printer_dc_; |
661 FilePath print_data_file_path_; | 657 FilePath print_data_file_path_; |
662 base::win::ScopedHandle job_progress_event_; | 658 base::win::ScopedHandle job_progress_event_; |
663 base::win::ObjectWatcher job_progress_watcher_; | 659 base::win::ObjectWatcher job_progress_watcher_; |
664 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_; | 660 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_; |
665 bool should_couninit_; | 661 scoped_ptr<base::win::ScopedCOMInitializer> com_initializer_; |
666 | 662 |
667 DISALLOW_COPY_AND_ASSIGN(Core); | 663 DISALLOW_COPY_AND_ASSIGN(Core); |
668 }; | 664 }; |
669 scoped_refptr<Core> core_; | 665 scoped_refptr<Core> core_; |
670 | 666 |
671 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin); | 667 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin); |
672 }; | 668 }; |
673 | 669 |
674 // A helper class to handle the response from the utility process to the | 670 // A helper class to handle the response from the utility process to the |
675 // request to fetch printer capabilities and defaults. | 671 // request to fetch printer capabilities and defaults. |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 return "application/pdf"; | 885 return "application/pdf"; |
890 } | 886 } |
891 | 887 |
892 | 888 |
893 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( | 889 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( |
894 const base::DictionaryValue* print_system_settings) { | 890 const base::DictionaryValue* print_system_settings) { |
895 return new PrintSystemWin; | 891 return new PrintSystemWin; |
896 } | 892 } |
897 | 893 |
898 } // namespace cloud_print | 894 } // namespace cloud_print |
OLD | NEW |