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

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

Issue 566693002: Use file handles to interact with utility process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wed Sep 17 10:40:51 PDT 2014 Created 6 years, 3 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
« no previous file with comments | « chrome/service/BUILD.gn ('k') | chrome/service/cloud_print/printer_job_queue_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/files/file_util.h" 8 #include "base/files/file_util.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/win/object_watcher.h" 12 #include "base/win/object_watcher.h"
13 #include "base/win/scoped_bstr.h" 13 #include "base/win/scoped_bstr.h"
14 #include "base/win/scoped_comptr.h" 14 #include "base/win/scoped_comptr.h"
15 #include "base/win/scoped_hdc.h" 15 #include "base/win/scoped_hdc.h"
16 #include "chrome/common/chrome_switches.h" 16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/cloud_print/cloud_print_cdd_conversion.h" 17 #include "chrome/common/cloud_print/cloud_print_cdd_conversion.h"
18 #include "chrome/common/cloud_print/cloud_print_constants.h" 18 #include "chrome/common/cloud_print/cloud_print_constants.h"
19 #include "chrome/common/crash_keys.h" 19 #include "chrome/common/crash_keys.h"
20 #include "chrome/service/cloud_print/cdd_conversion_win.h" 20 #include "chrome/service/cloud_print/cdd_conversion_win.h"
21 #include "chrome/service/service_process.h" 21 #include "chrome/service/service_process.h"
22 #include "chrome/service/service_utility_process_host.h" 22 #include "chrome/service/service_utility_process_host.h"
23 #include "printing/backend/win_helper.h" 23 #include "printing/backend/win_helper.h"
24 #include "printing/emf_win.h" 24 #include "printing/emf_win.h"
25 #include "printing/page_range.h" 25 #include "printing/page_range.h"
26 #include "printing/pdf_render_settings.h"
26 #include "printing/printing_utils.h" 27 #include "printing/printing_utils.h"
28 #include "ui/gfx/geometry/rect.h"
27 29
28 namespace cloud_print { 30 namespace cloud_print {
29 31
30 namespace { 32 namespace {
31 33
32 class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate { 34 class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate {
33 public: 35 public:
34 PrintSystemWatcherWin() 36 PrintSystemWatcherWin()
35 : delegate_(NULL), 37 : delegate_(NULL),
36 did_signal_(false) { 38 did_signal_(false) {
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 240
239 protected: 241 protected:
240 virtual ~JobSpoolerWin() {} 242 virtual ~JobSpoolerWin() {}
241 243
242 private: 244 private:
243 // We use a Core class because we want a separate RefCountedThreadSafe 245 // We use a Core class because we want a separate RefCountedThreadSafe
244 // implementation for ServiceUtilityProcessHost::Client. 246 // implementation for ServiceUtilityProcessHost::Client.
245 class Core : public ServiceUtilityProcessHost::Client, 247 class Core : public ServiceUtilityProcessHost::Client,
246 public base::win::ObjectWatcher::Delegate { 248 public base::win::ObjectWatcher::Delegate {
247 public: 249 public:
248 Core() 250 Core() : job_id_(-1), delegate_(NULL), saved_dc_(0) {}
249 : last_page_printed_(-1),
250 job_id_(-1),
251 delegate_(NULL),
252 saved_dc_(0) {
253 }
254 251
255 ~Core() {} 252 ~Core() {}
256 253
257 bool Spool(const std::string& print_ticket, 254 bool Spool(const std::string& print_ticket,
258 const std::string& print_ticket_mime_type, 255 const std::string& print_ticket_mime_type,
259 const base::FilePath& print_data_file_path, 256 const base::FilePath& print_data_file_path,
260 const std::string& print_data_mime_type, 257 const std::string& print_data_mime_type,
261 const std::string& printer_name, 258 const std::string& printer_name,
262 const std::string& job_title, 259 const std::string& job_title,
263 JobSpooler::Delegate* delegate) { 260 JobSpooler::Delegate* delegate) {
264 if (delegate_) { 261 if (delegate_) {
265 // We are already in the process of printing. 262 // We are already in the process of printing.
266 NOTREACHED(); 263 NOTREACHED();
267 return false; 264 return false;
268 } 265 }
269 base::string16 printer_wide = base::UTF8ToWide(printer_name); 266 base::string16 printer_wide = base::UTF8ToWide(printer_name);
270 last_page_printed_ = -1;
271 // We only support PDF and XPS documents for now. 267 // We only support PDF and XPS documents for now.
272 if (print_data_mime_type == kContentTypePDF) { 268 if (print_data_mime_type == kContentTypePDF) {
273 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode; 269 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode;
274 if (print_ticket_mime_type == kContentTypeJSON) { 270 if (print_ticket_mime_type == kContentTypeJSON) {
275 dev_mode = CjtToDevMode(printer_wide, print_ticket); 271 dev_mode = CjtToDevMode(printer_wide, print_ticket);
276 } else { 272 } else {
277 DCHECK(print_ticket_mime_type == kContentTypeXML); 273 DCHECK(print_ticket_mime_type == kContentTypeXML);
278 dev_mode = printing::XpsTicketToDevMode(printer_wide, print_ticket); 274 dev_mode = printing::XpsTicketToDevMode(printer_wide, print_ticket);
279 } 275 }
280 276
(...skipping 14 matching lines...) Expand all
295 DCHECK(printing::SimplifyDocumentTitle(doc_name) == doc_name); 291 DCHECK(printing::SimplifyDocumentTitle(doc_name) == doc_name);
296 di.lpszDocName = doc_name.c_str(); 292 di.lpszDocName = doc_name.c_str();
297 job_id_ = StartDoc(dc, &di); 293 job_id_ = StartDoc(dc, &di);
298 if (job_id_ <= 0) 294 if (job_id_ <= 0)
299 return false; 295 return false;
300 296
301 printer_dc_.Set(dc); 297 printer_dc_.Set(dc);
302 saved_dc_ = SaveDC(printer_dc_.Get()); 298 saved_dc_ = SaveDC(printer_dc_.Get());
303 print_data_file_path_ = print_data_file_path; 299 print_data_file_path_ = print_data_file_path;
304 delegate_ = delegate; 300 delegate_ = delegate;
305 RenderNextPDFPages(); 301 RenderPDFPages();
306 } else if (print_data_mime_type == kContentTypeXPS) { 302 } else if (print_data_mime_type == kContentTypeXPS) {
307 DCHECK(print_ticket_mime_type == kContentTypeXML); 303 DCHECK(print_ticket_mime_type == kContentTypeXML);
308 bool ret = PrintXPSDocument(printer_name, 304 bool ret = PrintXPSDocument(printer_name,
309 job_title, 305 job_title,
310 print_data_file_path, 306 print_data_file_path,
311 print_ticket); 307 print_ticket);
312 if (ret) 308 if (ret)
313 delegate_ = delegate; 309 delegate_ = delegate;
314 return ret; 310 return ret;
315 } else { 311 } else {
(...skipping 12 matching lines...) Expand all
328 int offset_x = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETX); 324 int offset_x = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETX);
329 int offset_y = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETY); 325 int offset_y = ::GetDeviceCaps(printer_dc_.Get(), PHYSICALOFFSETY);
330 XFORM xform = {0}; 326 XFORM xform = {0};
331 xform.eDx = static_cast<float>(-offset_x); 327 xform.eDx = static_cast<float>(-offset_x);
332 xform.eDy = static_cast<float>(-offset_y); 328 xform.eDy = static_cast<float>(-offset_y);
333 xform.eM11 = xform.eM22 = 1.0 / scale_factor; 329 xform.eM11 = xform.eM22 = 1.0 / scale_factor;
334 SetWorldTransform(printer_dc_.Get(), &xform); 330 SetWorldTransform(printer_dc_.Get(), &xform);
335 } 331 }
336 332
337 // ServiceUtilityProcessHost::Client implementation. 333 // ServiceUtilityProcessHost::Client implementation.
338 virtual void OnRenderPDFPagesToMetafileSucceeded( 334 virtual void OnRenderPDFPagesToMetafilePageDone(
339 const printing::MetafilePlayer& metafile, 335 double scale_factor,
340 int highest_rendered_page_number, 336 const printing::MetafilePlayer& emf) OVERRIDE {
341 double scale_factor) OVERRIDE {
342 PreparePageDCForPrinting(printer_dc_.Get(), scale_factor); 337 PreparePageDCForPrinting(printer_dc_.Get(), scale_factor);
343 metafile.SafePlayback(printer_dc_.Get()); 338 emf.SafePlayback(printer_dc_.Get());
344 bool done_printing = (highest_rendered_page_number !=
345 last_page_printed_ + kPageCountPerBatch);
346 last_page_printed_ = highest_rendered_page_number;
347 if (done_printing)
348 PrintJobDone();
349 else
350 RenderNextPDFPages();
351 } 339 }
352 340
341 // ServiceUtilityProcessHost::Client implementation.
342 virtual void OnRenderPDFPagesToMetafileDone(bool success) OVERRIDE {
343 PrintJobDone(success);
344 }
345
346 virtual void OnChildDied() OVERRIDE { PrintJobDone(false); }
347
353 // base::win::ObjectWatcher::Delegate implementation. 348 // base::win::ObjectWatcher::Delegate implementation.
354 virtual void OnObjectSignaled(HANDLE object) OVERRIDE { 349 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
355 DCHECK(xps_print_job_); 350 DCHECK(xps_print_job_);
356 DCHECK(object == job_progress_event_.Get()); 351 DCHECK(object == job_progress_event_.Get());
357 ResetEvent(job_progress_event_.Get()); 352 ResetEvent(job_progress_event_.Get());
358 if (!delegate_) 353 if (!delegate_)
359 return; 354 return;
360 XPS_JOB_STATUS job_status = {0}; 355 XPS_JOB_STATUS job_status = {0};
361 xps_print_job_->GetJobStatus(&job_status); 356 xps_print_job_->GetJobStatus(&job_status);
362 if ((job_status.completion == XPS_JOB_CANCELLED) || 357 if ((job_status.completion == XPS_JOB_CANCELLED) ||
363 (job_status.completion == XPS_JOB_FAILED)) { 358 (job_status.completion == XPS_JOB_FAILED)) {
364 delegate_->OnJobSpoolFailed(); 359 delegate_->OnJobSpoolFailed();
365 } else if (job_status.jobId || 360 } else if (job_status.jobId ||
366 (job_status.completion == XPS_JOB_COMPLETED)) { 361 (job_status.completion == XPS_JOB_COMPLETED)) {
367 // Note: In the case of the XPS document being printed to the 362 // Note: In the case of the XPS document being printed to the
368 // Microsoft XPS Document Writer, it seems to skip spooling the job 363 // Microsoft XPS Document Writer, it seems to skip spooling the job
369 // and goes to the completed state without ever assigning a job id. 364 // and goes to the completed state without ever assigning a job id.
370 delegate_->OnJobSpoolSucceeded(job_status.jobId); 365 delegate_->OnJobSpoolSucceeded(job_status.jobId);
371 } else { 366 } else {
372 job_progress_watcher_.StopWatching(); 367 job_progress_watcher_.StopWatching();
373 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); 368 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
374 } 369 }
375 } 370 }
376 371
377 virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE {
378 PrintJobDone();
379 }
380
381 virtual void OnChildDied() OVERRIDE {
382 PrintJobDone();
383 }
384
385 private: 372 private:
386 // Helper class to allow PrintXPSDocument() to have multiple exits. 373 // Helper class to allow PrintXPSDocument() to have multiple exits.
387 class PrintJobCanceler { 374 class PrintJobCanceler {
388 public: 375 public:
389 explicit PrintJobCanceler( 376 explicit PrintJobCanceler(
390 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr) 377 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr)
391 : job_ptr_(job_ptr) { 378 : job_ptr_(job_ptr) {
392 } 379 }
393 ~PrintJobCanceler() { 380 ~PrintJobCanceler() {
394 if (job_ptr_ && *job_ptr_) { 381 if (job_ptr_ && *job_ptr_) {
395 (*job_ptr_)->Cancel(); 382 (*job_ptr_)->Cancel();
396 job_ptr_->Release(); 383 job_ptr_->Release();
397 } 384 }
398 } 385 }
399 386
400 void reset() { job_ptr_ = NULL; } 387 void reset() { job_ptr_ = NULL; }
401 388
402 private: 389 private:
403 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_; 390 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_;
404 391
405 DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler); 392 DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler);
406 }; 393 };
407 394
408 void PrintJobDone() { 395 void PrintJobDone(bool success) {
409 // If there is no delegate, then there is nothing pending to process. 396 // If there is no delegate, then there is nothing pending to process.
410 if (!delegate_) 397 if (!delegate_)
411 return; 398 return;
412 RestoreDC(printer_dc_.Get(), saved_dc_); 399 RestoreDC(printer_dc_.Get(), saved_dc_);
413 EndDoc(printer_dc_.Get()); 400 EndDoc(printer_dc_.Get());
414 if (-1 == last_page_printed_) { 401 if (success) {
402 delegate_->OnJobSpoolSucceeded(job_id_);
403 } else {
415 delegate_->OnJobSpoolFailed(); 404 delegate_->OnJobSpoolFailed();
416 } else {
417 delegate_->OnJobSpoolSucceeded(job_id_);
418 } 405 }
419 delegate_ = NULL; 406 delegate_ = NULL;
420 } 407 }
421 408
422 void RenderNextPDFPages() { 409 void RenderPDFPages() {
423 printing::PageRange range;
424 // Render 10 pages at a time.
425 range.from = last_page_printed_ + 1;
426 range.to = last_page_printed_ + kPageCountPerBatch;
427 std::vector<printing::PageRange> page_ranges;
428 page_ranges.push_back(range);
429
430 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX); 410 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
431 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH); 411 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
432 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT); 412 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
433 gfx::Rect render_area(0, 0, dc_width, dc_height); 413 gfx::Rect render_area(0, 0, dc_width, dc_height);
434 g_service_process->io_thread()->message_loop_proxy()->PostTask( 414 g_service_process->io_thread()->message_loop_proxy()->PostTask(
435 FROM_HERE, 415 FROM_HERE,
436 base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox, this, 416 base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox,
437 print_data_file_path_, render_area, printer_dpi, 417 this,
438 page_ranges, base::MessageLoopProxy::current())); 418 print_data_file_path_,
419 render_area,
420 printer_dpi,
421 base::MessageLoopProxy::current()));
439 } 422 }
440 423
441 // Called on the service process IO thread. 424 // Called on the service process IO thread.
442 void RenderPDFPagesInSandbox( 425 void RenderPDFPagesInSandbox(const base::FilePath& pdf_path,
443 const base::FilePath& pdf_path, const gfx::Rect& render_area, 426 const gfx::Rect& render_area,
444 int render_dpi, const std::vector<printing::PageRange>& page_ranges, 427 int render_dpi,
445 const scoped_refptr<base::MessageLoopProxy>& 428 const scoped_refptr<base::MessageLoopProxy>&
446 client_message_loop_proxy) { 429 client_message_loop_proxy) {
447 DCHECK(g_service_process->io_thread()->message_loop_proxy()-> 430 DCHECK(g_service_process->io_thread()->message_loop_proxy()->
448 BelongsToCurrentThread()); 431 BelongsToCurrentThread());
449 scoped_ptr<ServiceUtilityProcessHost> utility_host( 432 scoped_ptr<ServiceUtilityProcessHost> utility_host(
450 new ServiceUtilityProcessHost(this, client_message_loop_proxy)); 433 new ServiceUtilityProcessHost(this, client_message_loop_proxy));
451 // TODO(gene): For now we disabling autorotation for CloudPrinting. 434 // TODO(gene): For now we disabling autorotation for CloudPrinting.
452 // Landscape/Portrait setting is passed in the print ticket and 435 // Landscape/Portrait setting is passed in the print ticket and
453 // server is generating portrait PDF always. 436 // server is generating portrait PDF always.
454 // We should enable autorotation once server will be able to generate 437 // We should enable autorotation once server will be able to generate
455 // PDF that matches paper size and orientation. 438 // PDF that matches paper size and orientation.
456 if (utility_host->StartRenderPDFPagesToMetafile( 439 if (utility_host->StartRenderPDFPagesToMetafile(
457 pdf_path, 440 pdf_path,
458 printing::PdfRenderSettings(render_area, render_dpi, false), 441 printing::PdfRenderSettings(render_area, render_dpi, false))) {
459 page_ranges)) {
460 // The object will self-destruct when the child process dies. 442 // The object will self-destruct when the child process dies.
461 utility_host.release(); 443 utility_host.release();
444 } else {
445 client_message_loop_proxy->PostTask(
446 FROM_HERE, base::Bind(&Core::PrintJobDone, this, false));
462 } 447 }
463 } 448 }
464 449
465 bool PrintXPSDocument(const std::string& printer_name, 450 bool PrintXPSDocument(const std::string& printer_name,
466 const std::string& job_title, 451 const std::string& job_title,
467 const base::FilePath& print_data_file_path, 452 const base::FilePath& print_data_file_path,
468 const std::string& print_ticket) { 453 const std::string& print_ticket) {
469 if (!printing::XPSPrintModule::Init()) 454 if (!printing::XPSPrintModule::Init())
470 return false; 455 return false;
471 456
(...skipping 30 matching lines...) Expand all
502 return false; 487 return false;
503 DCHECK_EQ(document_data.length(), doc_bytes_written); 488 DCHECK_EQ(document_data.length(), doc_bytes_written);
504 if (FAILED(doc_stream->Close())) 489 if (FAILED(doc_stream->Close()))
505 return false; 490 return false;
506 491
507 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); 492 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
508 job_canceler.reset(); 493 job_canceler.reset();
509 return true; 494 return true;
510 } 495 }
511 496
512 // Some Cairo-generated PDFs from Chrome OS result in huge metafiles.
513 // So the PageCountPerBatch is set to 1 for now.
514 // TODO(sanjeevr): Figure out a smarter way to determine the pages per
515 // batch. Filed a bug to track this at
516 // http://code.google.com/p/chromium/issues/detail?id=57350.
517 static const int kPageCountPerBatch = 1;
518
519 int last_page_printed_;
520 PlatformJobId job_id_; 497 PlatformJobId job_id_;
521 PrintSystem::JobSpooler::Delegate* delegate_; 498 PrintSystem::JobSpooler::Delegate* delegate_;
522 int saved_dc_; 499 int saved_dc_;
523 base::win::ScopedCreateDC printer_dc_; 500 base::win::ScopedCreateDC printer_dc_;
524 base::FilePath print_data_file_path_; 501 base::FilePath print_data_file_path_;
525 base::win::ScopedHandle job_progress_event_; 502 base::win::ScopedHandle job_progress_event_;
526 base::win::ObjectWatcher job_progress_watcher_; 503 base::win::ObjectWatcher job_progress_watcher_;
527 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_; 504 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_;
528 505
529 DISALLOW_COPY_AND_ASSIGN(Core); 506 DISALLOW_COPY_AND_ASSIGN(Core);
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 } 817 }
841 818
842 } // namespace 819 } // namespace
843 820
844 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( 821 scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
845 const base::DictionaryValue* print_system_settings) { 822 const base::DictionaryValue* print_system_settings) {
846 return new PrintSystemWin; 823 return new PrintSystemWin;
847 } 824 }
848 825
849 } // namespace cloud_print 826 } // namespace cloud_print
OLDNEW
« no previous file with comments | « chrome/service/BUILD.gn ('k') | chrome/service/cloud_print/printer_job_queue_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698