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

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: Mon Sep 15 03:22:54 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
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 OnRenderPDFPagesToMetafileSucceeded() OVERRIDE {
343 PrintJobDone(true);
344 }
345
346 virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE {
347 PrintJobDone(false);
348 }
349
350 virtual void OnChildDied() OVERRIDE { PrintJobDone(false); }
351
353 // base::win::ObjectWatcher::Delegate implementation. 352 // base::win::ObjectWatcher::Delegate implementation.
354 virtual void OnObjectSignaled(HANDLE object) OVERRIDE { 353 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
355 DCHECK(xps_print_job_); 354 DCHECK(xps_print_job_);
356 DCHECK(object == job_progress_event_.Get()); 355 DCHECK(object == job_progress_event_.Get());
357 ResetEvent(job_progress_event_.Get()); 356 ResetEvent(job_progress_event_.Get());
358 if (!delegate_) 357 if (!delegate_)
359 return; 358 return;
360 XPS_JOB_STATUS job_status = {0}; 359 XPS_JOB_STATUS job_status = {0};
361 xps_print_job_->GetJobStatus(&job_status); 360 xps_print_job_->GetJobStatus(&job_status);
362 if ((job_status.completion == XPS_JOB_CANCELLED) || 361 if ((job_status.completion == XPS_JOB_CANCELLED) ||
363 (job_status.completion == XPS_JOB_FAILED)) { 362 (job_status.completion == XPS_JOB_FAILED)) {
364 delegate_->OnJobSpoolFailed(); 363 delegate_->OnJobSpoolFailed();
365 } else if (job_status.jobId || 364 } else if (job_status.jobId ||
366 (job_status.completion == XPS_JOB_COMPLETED)) { 365 (job_status.completion == XPS_JOB_COMPLETED)) {
367 // Note: In the case of the XPS document being printed to the 366 // Note: In the case of the XPS document being printed to the
368 // Microsoft XPS Document Writer, it seems to skip spooling the job 367 // Microsoft XPS Document Writer, it seems to skip spooling the job
369 // and goes to the completed state without ever assigning a job id. 368 // and goes to the completed state without ever assigning a job id.
370 delegate_->OnJobSpoolSucceeded(job_status.jobId); 369 delegate_->OnJobSpoolSucceeded(job_status.jobId);
371 } else { 370 } else {
372 job_progress_watcher_.StopWatching(); 371 job_progress_watcher_.StopWatching();
373 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); 372 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
374 } 373 }
375 } 374 }
376 375
377 virtual void OnRenderPDFPagesToMetafileFailed() OVERRIDE {
378 PrintJobDone();
379 }
380
381 virtual void OnChildDied() OVERRIDE {
382 PrintJobDone();
383 }
384
385 private: 376 private:
386 // Helper class to allow PrintXPSDocument() to have multiple exits. 377 // Helper class to allow PrintXPSDocument() to have multiple exits.
387 class PrintJobCanceler { 378 class PrintJobCanceler {
388 public: 379 public:
389 explicit PrintJobCanceler( 380 explicit PrintJobCanceler(
390 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr) 381 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr)
391 : job_ptr_(job_ptr) { 382 : job_ptr_(job_ptr) {
392 } 383 }
393 ~PrintJobCanceler() { 384 ~PrintJobCanceler() {
394 if (job_ptr_ && *job_ptr_) { 385 if (job_ptr_ && *job_ptr_) {
395 (*job_ptr_)->Cancel(); 386 (*job_ptr_)->Cancel();
396 job_ptr_->Release(); 387 job_ptr_->Release();
397 } 388 }
398 } 389 }
399 390
400 void reset() { job_ptr_ = NULL; } 391 void reset() { job_ptr_ = NULL; }
401 392
402 private: 393 private:
403 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_; 394 base::win::ScopedComPtr<IXpsPrintJob>* job_ptr_;
404 395
405 DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler); 396 DISALLOW_COPY_AND_ASSIGN(PrintJobCanceler);
406 }; 397 };
407 398
408 void PrintJobDone() { 399 void PrintJobDone(bool success) {
409 // If there is no delegate, then there is nothing pending to process. 400 // If there is no delegate, then there is nothing pending to process.
410 if (!delegate_) 401 if (!delegate_)
411 return; 402 return;
412 RestoreDC(printer_dc_.Get(), saved_dc_); 403 RestoreDC(printer_dc_.Get(), saved_dc_);
413 EndDoc(printer_dc_.Get()); 404 EndDoc(printer_dc_.Get());
414 if (-1 == last_page_printed_) { 405 if (success) {
406 delegate_->OnJobSpoolSucceeded(job_id_);
407 } else {
415 delegate_->OnJobSpoolFailed(); 408 delegate_->OnJobSpoolFailed();
416 } else {
417 delegate_->OnJobSpoolSucceeded(job_id_);
418 } 409 }
419 delegate_ = NULL; 410 delegate_ = NULL;
420 } 411 }
421 412
422 void RenderNextPDFPages() { 413 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); 414 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
431 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH); 415 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
432 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT); 416 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
433 gfx::Rect render_area(0, 0, dc_width, dc_height); 417 gfx::Rect render_area(0, 0, dc_width, dc_height);
434 g_service_process->io_thread()->message_loop_proxy()->PostTask( 418 g_service_process->io_thread()->message_loop_proxy()->PostTask(
435 FROM_HERE, 419 FROM_HERE,
436 base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox, this, 420 base::Bind(&JobSpoolerWin::Core::RenderPDFPagesInSandbox,
437 print_data_file_path_, render_area, printer_dpi, 421 this,
438 page_ranges, base::MessageLoopProxy::current())); 422 print_data_file_path_,
423 render_area,
424 printer_dpi,
425 base::MessageLoopProxy::current()));
439 } 426 }
440 427
441 // Called on the service process IO thread. 428 // Called on the service process IO thread.
442 void RenderPDFPagesInSandbox( 429 void RenderPDFPagesInSandbox(const base::FilePath& pdf_path,
443 const base::FilePath& pdf_path, const gfx::Rect& render_area, 430 const gfx::Rect& render_area,
444 int render_dpi, const std::vector<printing::PageRange>& page_ranges, 431 int render_dpi,
445 const scoped_refptr<base::MessageLoopProxy>& 432 const scoped_refptr<base::MessageLoopProxy>&
446 client_message_loop_proxy) { 433 client_message_loop_proxy) {
447 DCHECK(g_service_process->io_thread()->message_loop_proxy()-> 434 DCHECK(g_service_process->io_thread()->message_loop_proxy()->
448 BelongsToCurrentThread()); 435 BelongsToCurrentThread());
449 scoped_ptr<ServiceUtilityProcessHost> utility_host( 436 scoped_ptr<ServiceUtilityProcessHost> utility_host(
450 new ServiceUtilityProcessHost(this, client_message_loop_proxy)); 437 new ServiceUtilityProcessHost(this, client_message_loop_proxy));
451 // TODO(gene): For now we disabling autorotation for CloudPrinting. 438 // TODO(gene): For now we disabling autorotation for CloudPrinting.
452 // Landscape/Portrait setting is passed in the print ticket and 439 // Landscape/Portrait setting is passed in the print ticket and
453 // server is generating portrait PDF always. 440 // server is generating portrait PDF always.
454 // We should enable autorotation once server will be able to generate 441 // We should enable autorotation once server will be able to generate
455 // PDF that matches paper size and orientation. 442 // PDF that matches paper size and orientation.
456 if (utility_host->StartRenderPDFPagesToMetafile( 443 if (utility_host->StartRenderPDFPagesToMetafile(
457 pdf_path, 444 pdf_path,
458 printing::PdfRenderSettings(render_area, render_dpi, false), 445 printing::PdfRenderSettings(render_area, render_dpi, false))) {
459 page_ranges)) {
460 // The object will self-destruct when the child process dies. 446 // The object will self-destruct when the child process dies.
461 utility_host.release(); 447 utility_host.release();
462 } 448 }
463 } 449 }
464 450
465 bool PrintXPSDocument(const std::string& printer_name, 451 bool PrintXPSDocument(const std::string& printer_name,
466 const std::string& job_title, 452 const std::string& job_title,
467 const base::FilePath& print_data_file_path, 453 const base::FilePath& print_data_file_path,
468 const std::string& print_ticket) { 454 const std::string& print_ticket) {
469 if (!printing::XPSPrintModule::Init()) 455 if (!printing::XPSPrintModule::Init())
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 return false; 488 return false;
503 DCHECK_EQ(document_data.length(), doc_bytes_written); 489 DCHECK_EQ(document_data.length(), doc_bytes_written);
504 if (FAILED(doc_stream->Close())) 490 if (FAILED(doc_stream->Close()))
505 return false; 491 return false;
506 492
507 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this); 493 job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
508 job_canceler.reset(); 494 job_canceler.reset();
509 return true; 495 return true;
510 } 496 }
511 497
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_; 498 PlatformJobId job_id_;
521 PrintSystem::JobSpooler::Delegate* delegate_; 499 PrintSystem::JobSpooler::Delegate* delegate_;
522 int saved_dc_; 500 int saved_dc_;
523 base::win::ScopedCreateDC printer_dc_; 501 base::win::ScopedCreateDC printer_dc_;
524 base::FilePath print_data_file_path_; 502 base::FilePath print_data_file_path_;
525 base::win::ScopedHandle job_progress_event_; 503 base::win::ScopedHandle job_progress_event_;
526 base::win::ObjectWatcher job_progress_watcher_; 504 base::win::ObjectWatcher job_progress_watcher_;
527 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_; 505 base::win::ScopedComPtr<IXpsPrintJob> xps_print_job_;
528 506
529 DISALLOW_COPY_AND_ASSIGN(Core); 507 DISALLOW_COPY_AND_ASSIGN(Core);
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 } 818 }
841 819
842 } // namespace 820 } // namespace
843 821
844 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( 822 scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
845 const base::DictionaryValue* print_system_settings) { 823 const base::DictionaryValue* print_system_settings) {
846 return new PrintSystemWin; 824 return new PrintSystemWin;
847 } 825 }
848 826
849 } // namespace cloud_print 827 } // namespace cloud_print
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698