OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "printing/printing_context.h" | 5 #include "printing/printing_context_win.h" |
6 | 6 |
7 #include <winspool.h> | 7 #include <winspool.h> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/i18n/file_util_icu.h" | 10 #include "base/i18n/file_util_icu.h" |
11 #include "base/i18n/time_formatting.h" | 11 #include "base/i18n/time_formatting.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/time.h" | 13 #include "base/time.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "printing/printed_document.h" | 15 #include "printing/printed_document.h" |
16 #include "skia/ext/platform_device_win.h" | 16 #include "skia/ext/platform_device_win.h" |
17 | 17 |
18 using base::Time; | 18 using base::Time; |
19 | 19 |
20 namespace printing { | 20 namespace printing { |
21 | 21 |
22 class PrintingContext::CallbackHandler : public IPrintDialogCallback, | 22 class PrintingContextWin::CallbackHandler : public IPrintDialogCallback, |
23 public IObjectWithSite { | 23 public IObjectWithSite { |
24 public: | 24 public: |
25 CallbackHandler(PrintingContext& owner, HWND owner_hwnd) | 25 CallbackHandler(PrintingContextWin& owner, HWND owner_hwnd) |
26 : owner_(owner), | 26 : owner_(owner), |
27 owner_hwnd_(owner_hwnd), | 27 owner_hwnd_(owner_hwnd), |
28 services_(NULL) { | 28 services_(NULL) { |
29 } | 29 } |
30 | 30 |
31 ~CallbackHandler() { | 31 ~CallbackHandler() { |
32 if (services_) | 32 if (services_) |
33 services_->Release(); | 33 services_->Release(); |
34 } | 34 } |
35 | 35 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 DCHECK(SUCCEEDED(hr)); | 106 DCHECK(SUCCEEDED(hr)); |
107 } | 107 } |
108 return S_OK; | 108 return S_OK; |
109 } | 109 } |
110 | 110 |
111 virtual HRESULT WINAPI GetSite(REFIID riid, void** site) { | 111 virtual HRESULT WINAPI GetSite(REFIID riid, void** site) { |
112 return E_NOTIMPL; | 112 return E_NOTIMPL; |
113 } | 113 } |
114 | 114 |
115 private: | 115 private: |
116 PrintingContext& owner_; | 116 PrintingContextWin& owner_; |
117 HWND owner_hwnd_; | 117 HWND owner_hwnd_; |
118 IPrintDialogServices* services_; | 118 IPrintDialogServices* services_; |
119 | 119 |
120 DISALLOW_COPY_AND_ASSIGN(CallbackHandler); | 120 DISALLOW_COPY_AND_ASSIGN(CallbackHandler); |
121 }; | 121 }; |
122 | 122 |
123 PrintingContext::PrintingContext() | 123 // static |
124 : context_(NULL), | 124 PrintingContext* PrintingContext::Create() { |
| 125 return static_cast<PrintingContext*>(new PrintingContextWin); |
| 126 } |
| 127 |
| 128 PrintingContextWin::PrintingContextWin() |
| 129 : PrintingContext(), |
| 130 context_(NULL), |
125 dialog_box_(NULL), | 131 dialog_box_(NULL), |
126 dialog_box_dismissed_(false), | |
127 in_print_job_(false), | |
128 abort_printing_(false), | |
129 print_dialog_func_(&PrintDlgEx) { | 132 print_dialog_func_(&PrintDlgEx) { |
130 } | 133 } |
131 | 134 |
132 PrintingContext::~PrintingContext() { | 135 PrintingContextWin::~PrintingContextWin() { |
133 ResetSettings(); | 136 ReleaseContext(); |
134 } | 137 } |
135 | 138 |
136 void PrintingContext::AskUserForSettings(HWND view, | 139 void PrintingContextWin::AskUserForSettings(HWND view, |
137 int max_pages, | 140 int max_pages, |
138 bool has_selection, | 141 bool has_selection, |
139 PrintSettingsCallback* callback) { | 142 PrintSettingsCallback* callback) { |
140 DCHECK(!in_print_job_); | 143 DCHECK(!in_print_job_); |
141 dialog_box_dismissed_ = false; | 144 dialog_box_dismissed_ = false; |
142 | 145 |
143 HWND window; | 146 HWND window; |
144 if (!view || !IsWindow(view)) { | 147 if (!view || !IsWindow(view)) { |
145 // TODO(maruel): bug 1214347 Get the right browser window instead. | 148 // TODO(maruel): bug 1214347 Get the right browser window instead. |
146 window = GetDesktopWindow(); | 149 window = GetDesktopWindow(); |
147 } else { | 150 } else { |
148 window = GetAncestor(view, GA_ROOTOWNER); | 151 window = GetAncestor(view, GA_ROOTOWNER); |
149 } | 152 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 { | 190 { |
188 if ((*print_dialog_func_)(&dialog_options) != S_OK) { | 191 if ((*print_dialog_func_)(&dialog_options) != S_OK) { |
189 ResetSettings(); | 192 ResetSettings(); |
190 callback->Run(FAILED); | 193 callback->Run(FAILED); |
191 } | 194 } |
192 } | 195 } |
193 // TODO(maruel): Support PD_PRINTTOFILE. | 196 // TODO(maruel): Support PD_PRINTTOFILE. |
194 callback->Run(ParseDialogResultEx(dialog_options)); | 197 callback->Run(ParseDialogResultEx(dialog_options)); |
195 } | 198 } |
196 | 199 |
197 PrintingContext::Result PrintingContext::UseDefaultSettings() { | 200 PrintingContext::Result PrintingContextWin::UseDefaultSettings() { |
198 DCHECK(!in_print_job_); | 201 DCHECK(!in_print_job_); |
199 | 202 |
200 PRINTDLG dialog_options = { sizeof(PRINTDLG) }; | 203 PRINTDLG dialog_options = { sizeof(PRINTDLG) }; |
201 dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT; | 204 dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT; |
202 if (PrintDlg(&dialog_options) == 0) { | 205 if (PrintDlg(&dialog_options) == 0) { |
203 ResetSettings(); | 206 ResetSettings(); |
204 return FAILED; | 207 return FAILED; |
205 } | 208 } |
206 return ParseDialogResult(dialog_options); | 209 return ParseDialogResult(dialog_options); |
207 } | 210 } |
208 | 211 |
209 PrintingContext::Result PrintingContext::InitWithSettings( | 212 PrintingContext::Result PrintingContextWin::InitWithSettings( |
210 const PrintSettings& settings) { | 213 const PrintSettings& settings) { |
211 DCHECK(!in_print_job_); | 214 DCHECK(!in_print_job_); |
212 settings_ = settings; | 215 settings_ = settings; |
213 // TODO(maruel): settings_->ToDEVMODE() | 216 // TODO(maruel): settings_->ToDEVMODE() |
214 HANDLE printer; | 217 HANDLE printer; |
215 if (!OpenPrinter(const_cast<wchar_t*>(settings_.device_name().c_str()), | 218 if (!OpenPrinter(const_cast<wchar_t*>(settings_.device_name().c_str()), |
216 &printer, | 219 &printer, |
217 NULL)) | 220 NULL)) |
218 return FAILED; | 221 return FAILED; |
219 | 222 |
220 Result status = OK; | 223 Result status = OK; |
221 | 224 |
222 if (!GetPrinterSettings(printer, settings_.device_name())) | 225 if (!GetPrinterSettings(printer, settings_.device_name())) |
223 status = FAILED; | 226 status = FAILED; |
224 | 227 |
225 // Close the printer after retrieving the context. | 228 // Close the printer after retrieving the context. |
226 ClosePrinter(printer); | 229 ClosePrinter(printer); |
227 | 230 |
228 if (status != OK) | 231 if (status != OK) |
229 ResetSettings(); | 232 ResetSettings(); |
230 return status; | 233 return status; |
231 } | 234 } |
232 | 235 |
233 void PrintingContext::ResetSettings() { | 236 PrintingContext::Result PrintingContextWin::NewDocument( |
234 if (context_ != NULL) { | |
235 DeleteDC(context_); | |
236 context_ = NULL; | |
237 } | |
238 settings_.Clear(); | |
239 in_print_job_ = false; | |
240 } | |
241 | |
242 PrintingContext::Result PrintingContext::NewDocument( | |
243 const string16& document_name) { | 237 const string16& document_name) { |
244 DCHECK(!in_print_job_); | 238 DCHECK(!in_print_job_); |
245 if (!context_) | 239 if (!context_) |
246 return OnError(); | 240 return OnError(); |
247 | 241 |
248 // Set the flag used by the AbortPrintJob dialog procedure. | 242 // Set the flag used by the AbortPrintJob dialog procedure. |
249 abort_printing_ = false; | 243 abort_printing_ = false; |
250 | 244 |
251 in_print_job_ = true; | 245 in_print_job_ = true; |
252 | 246 |
(...skipping 29 matching lines...) Expand all Loading... |
282 | 276 |
283 // Begin a print job by calling the StartDoc function. | 277 // Begin a print job by calling the StartDoc function. |
284 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with | 278 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with |
285 // IPC. Make sure recursive task processing is disabled. | 279 // IPC. Make sure recursive task processing is disabled. |
286 if (StartDoc(context_, &di) <= 0) | 280 if (StartDoc(context_, &di) <= 0) |
287 return OnError(); | 281 return OnError(); |
288 | 282 |
289 return OK; | 283 return OK; |
290 } | 284 } |
291 | 285 |
292 PrintingContext::Result PrintingContext::NewPage() { | 286 PrintingContext::Result PrintingContextWin::NewPage() { |
293 if (abort_printing_) | 287 if (abort_printing_) |
294 return CANCEL; | 288 return CANCEL; |
295 | 289 |
296 DCHECK(context_); | 290 DCHECK(context_); |
297 DCHECK(in_print_job_); | 291 DCHECK(in_print_job_); |
298 | 292 |
299 // Inform the driver that the application is about to begin sending data. | 293 // Inform the driver that the application is about to begin sending data. |
300 if (StartPage(context_) <= 0) | 294 if (StartPage(context_) <= 0) |
301 return OnError(); | 295 return OnError(); |
302 | 296 |
303 return OK; | 297 return OK; |
304 } | 298 } |
305 | 299 |
306 PrintingContext::Result PrintingContext::PageDone() { | 300 PrintingContext::Result PrintingContextWin::PageDone() { |
307 if (abort_printing_) | 301 if (abort_printing_) |
308 return CANCEL; | 302 return CANCEL; |
309 DCHECK(in_print_job_); | 303 DCHECK(in_print_job_); |
310 | 304 |
311 if (EndPage(context_) <= 0) | 305 if (EndPage(context_) <= 0) |
312 return OnError(); | 306 return OnError(); |
313 return OK; | 307 return OK; |
314 } | 308 } |
315 | 309 |
316 PrintingContext::Result PrintingContext::DocumentDone() { | 310 PrintingContext::Result PrintingContextWin::DocumentDone() { |
317 if (abort_printing_) | 311 if (abort_printing_) |
318 return CANCEL; | 312 return CANCEL; |
319 DCHECK(in_print_job_); | 313 DCHECK(in_print_job_); |
320 DCHECK(context_); | 314 DCHECK(context_); |
321 | 315 |
322 // Inform the driver that document has ended. | 316 // Inform the driver that document has ended. |
323 if (EndDoc(context_) <= 0) | 317 if (EndDoc(context_) <= 0) |
324 return OnError(); | 318 return OnError(); |
325 | 319 |
326 ResetSettings(); | 320 ResetSettings(); |
327 return OK; | 321 return OK; |
328 } | 322 } |
329 | 323 |
330 void PrintingContext::Cancel() { | 324 void PrintingContextWin::Cancel() { |
331 abort_printing_ = true; | 325 abort_printing_ = true; |
332 in_print_job_ = false; | 326 in_print_job_ = false; |
333 if (context_) | 327 if (context_) |
334 CancelDC(context_); | 328 CancelDC(context_); |
335 DismissDialog(); | 329 DismissDialog(); |
336 } | 330 } |
337 | 331 |
338 void PrintingContext::DismissDialog() { | 332 void PrintingContextWin::DismissDialog() { |
339 if (dialog_box_) { | 333 if (dialog_box_) { |
340 DestroyWindow(dialog_box_); | 334 DestroyWindow(dialog_box_); |
341 dialog_box_dismissed_ = true; | 335 dialog_box_dismissed_ = true; |
342 } | 336 } |
343 } | 337 } |
344 | 338 |
345 PrintingContext::Result PrintingContext::OnError() { | 339 void PrintingContextWin::ReleaseContext() { |
346 // This will close context_ and clear settings_. | 340 if (context_) { |
347 ResetSettings(); | 341 DeleteDC(context_); |
348 return abort_printing_ ? CANCEL : FAILED; | 342 context_ = NULL; |
| 343 } |
| 344 } |
| 345 |
| 346 gfx::NativeDrawingContext PrintingContextWin::context() const { |
| 347 return context_; |
349 } | 348 } |
350 | 349 |
351 // static | 350 // static |
352 BOOL PrintingContext::AbortProc(HDC hdc, int nCode) { | 351 BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { |
353 if (nCode) { | 352 if (nCode) { |
354 // TODO(maruel): Need a way to find the right instance to set. Should | 353 // TODO(maruel): Need a way to find the right instance to set. Should |
355 // leverage PrintJobManager here? | 354 // leverage PrintJobManager here? |
356 // abort_printing_ = true; | 355 // abort_printing_ = true; |
357 } | 356 } |
358 return true; | 357 return true; |
359 } | 358 } |
360 | 359 |
361 bool PrintingContext::InitializeSettings(const DEVMODE& dev_mode, | 360 bool PrintingContextWin::InitializeSettings(const DEVMODE& dev_mode, |
362 const std::wstring& new_device_name, | 361 const std::wstring& new_device_name, |
363 const PRINTPAGERANGE* ranges, | 362 const PRINTPAGERANGE* ranges, |
364 int number_ranges, | 363 int number_ranges, |
365 bool selection_only) { | 364 bool selection_only) { |
366 skia::PlatformDevice::InitializeDC(context_); | 365 skia::PlatformDevice::InitializeDC(context_); |
367 DCHECK(GetDeviceCaps(context_, CLIPCAPS)); | 366 DCHECK(GetDeviceCaps(context_, CLIPCAPS)); |
368 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB); | 367 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB); |
369 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64); | 368 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64); |
370 // Some printers don't advertise these. | 369 // Some printers don't advertise these. |
371 // DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING); | 370 // DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING); |
372 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA); | 371 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA); |
373 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA); | 372 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA); |
374 | 373 |
375 // StretchDIBits() support is needed for printing. | 374 // StretchDIBits() support is needed for printing. |
(...skipping 19 matching lines...) Expand all Loading... |
395 } | 394 } |
396 } | 395 } |
397 settings_.Init(context_, | 396 settings_.Init(context_, |
398 dev_mode, | 397 dev_mode, |
399 ranges_vector, | 398 ranges_vector, |
400 new_device_name, | 399 new_device_name, |
401 selection_only); | 400 selection_only); |
402 return true; | 401 return true; |
403 } | 402 } |
404 | 403 |
405 bool PrintingContext::GetPrinterSettings(HANDLE printer, | 404 bool PrintingContextWin::GetPrinterSettings(HANDLE printer, |
406 const std::wstring& device_name) { | 405 const std::wstring& device_name) { |
407 DCHECK(!in_print_job_); | 406 DCHECK(!in_print_job_); |
408 scoped_array<uint8> buffer; | 407 scoped_array<uint8> buffer; |
409 | 408 |
410 // A PRINTER_INFO_9 structure specifying the per-user default printer | 409 // A PRINTER_INFO_9 structure specifying the per-user default printer |
411 // settings. | 410 // settings. |
412 GetPrinterHelper(printer, 9, &buffer); | 411 GetPrinterHelper(printer, 9, &buffer); |
413 if (buffer.get()) { | 412 if (buffer.get()) { |
414 PRINTER_INFO_9* info_9 = reinterpret_cast<PRINTER_INFO_9*>(buffer.get()); | 413 PRINTER_INFO_9* info_9 = reinterpret_cast<PRINTER_INFO_9*>(buffer.get()); |
415 if (info_9->pDevMode != NULL) { | 414 if (info_9->pDevMode != NULL) { |
416 if (!AllocateContext(device_name, info_9->pDevMode, &context_)) { | 415 if (!AllocateContext(device_name, info_9->pDevMode, &context_)) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 return InitializeSettings(*info_2->pDevMode, device_name, NULL, 0, false); | 448 return InitializeSettings(*info_2->pDevMode, device_name, NULL, 0, false); |
450 } | 449 } |
451 buffer.reset(); | 450 buffer.reset(); |
452 } | 451 } |
453 // Failed to retrieve the printer settings. | 452 // Failed to retrieve the printer settings. |
454 ResetSettings(); | 453 ResetSettings(); |
455 return false; | 454 return false; |
456 } | 455 } |
457 | 456 |
458 // static | 457 // static |
459 bool PrintingContext::AllocateContext(const std::wstring& printer_name, | 458 bool PrintingContextWin::AllocateContext(const std::wstring& printer_name, |
460 const DEVMODE* dev_mode, | 459 const DEVMODE* dev_mode, |
461 gfx::NativeDrawingContext* context) { | 460 gfx::NativeDrawingContext* context) { |
462 *context = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); | 461 *context = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); |
463 DCHECK(*context); | 462 DCHECK(*context); |
464 return *context != NULL; | 463 return *context != NULL; |
465 } | 464 } |
466 | 465 |
467 PrintingContext::Result PrintingContext::ParseDialogResultEx( | 466 PrintingContext::Result PrintingContextWin::ParseDialogResultEx( |
468 const PRINTDLGEX& dialog_options) { | 467 const PRINTDLGEX& dialog_options) { |
469 // If the user clicked OK or Apply then Cancel, but not only Cancel. | 468 // If the user clicked OK or Apply then Cancel, but not only Cancel. |
470 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) { | 469 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) { |
471 // Start fresh. | 470 // Start fresh. |
472 ResetSettings(); | 471 ResetSettings(); |
473 | 472 |
474 DEVMODE* dev_mode = NULL; | 473 DEVMODE* dev_mode = NULL; |
475 if (dialog_options.hDevMode) { | 474 if (dialog_options.hDevMode) { |
476 dev_mode = | 475 dev_mode = |
477 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); | 476 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 return context_ ? OK : FAILED; | 535 return context_ ? OK : FAILED; |
537 case PD_RESULT_APPLY: | 536 case PD_RESULT_APPLY: |
538 return context_ ? CANCEL : FAILED; | 537 return context_ ? CANCEL : FAILED; |
539 case PD_RESULT_CANCEL: | 538 case PD_RESULT_CANCEL: |
540 return CANCEL; | 539 return CANCEL; |
541 default: | 540 default: |
542 return FAILED; | 541 return FAILED; |
543 } | 542 } |
544 } | 543 } |
545 | 544 |
546 PrintingContext::Result PrintingContext::ParseDialogResult( | 545 PrintingContext::Result PrintingContextWin::ParseDialogResult( |
547 const PRINTDLG& dialog_options) { | 546 const PRINTDLG& dialog_options) { |
548 // If the user clicked OK or Apply then Cancel, but not only Cancel. | 547 // If the user clicked OK or Apply then Cancel, but not only Cancel. |
549 // Start fresh. | 548 // Start fresh. |
550 ResetSettings(); | 549 ResetSettings(); |
551 | 550 |
552 DEVMODE* dev_mode = NULL; | 551 DEVMODE* dev_mode = NULL; |
553 if (dialog_options.hDevMode) { | 552 if (dialog_options.hDevMode) { |
554 dev_mode = | 553 dev_mode = |
555 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); | 554 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); |
556 DCHECK(dev_mode); | 555 DCHECK(dev_mode); |
(...skipping 30 matching lines...) Expand all Loading... |
587 | 586 |
588 if (dialog_options.hDevMode != NULL) | 587 if (dialog_options.hDevMode != NULL) |
589 GlobalFree(dialog_options.hDevMode); | 588 GlobalFree(dialog_options.hDevMode); |
590 if (dialog_options.hDevNames != NULL) | 589 if (dialog_options.hDevNames != NULL) |
591 GlobalFree(dialog_options.hDevNames); | 590 GlobalFree(dialog_options.hDevNames); |
592 | 591 |
593 return context_ ? OK : FAILED; | 592 return context_ ? OK : FAILED; |
594 } | 593 } |
595 | 594 |
596 // static | 595 // static |
597 void PrintingContext::GetPrinterHelper(HANDLE printer, int level, | 596 void PrintingContextWin::GetPrinterHelper(HANDLE printer, int level, |
598 scoped_array<uint8>* buffer) { | 597 scoped_array<uint8>* buffer) { |
599 DWORD buf_size = 0; | 598 DWORD buf_size = 0; |
600 GetPrinter(printer, level, NULL, 0, &buf_size); | 599 GetPrinter(printer, level, NULL, 0, &buf_size); |
601 if (buf_size) { | 600 if (buf_size) { |
602 buffer->reset(new uint8[buf_size]); | 601 buffer->reset(new uint8[buf_size]); |
603 memset(buffer->get(), 0, buf_size); | 602 memset(buffer->get(), 0, buf_size); |
604 if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) { | 603 if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) { |
605 buffer->reset(); | 604 buffer->reset(); |
606 } | 605 } |
607 } | 606 } |
608 } | 607 } |
609 | 608 |
610 } // namespace printing | 609 } // namespace printing |
OLD | NEW |