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

Side by Side Diff: chrome/browser/printing/print_view_manager_base.cc

Issue 255543006: Printing on Windows via PDF (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: almost working; SafePlayback failing in final print Created 6 years, 8 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/browser/printing/print_view_manager_base.h" 5 #include "chrome/browser/printing/print_view_manager_base.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/memory/ref_counted_memory.h"
10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
11 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
13 #include "base/timer/timer.h" 14 #include "base/timer/timer.h"
14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/printing/pdf_to_emf_converter.h"
16 #include "chrome/browser/printing/print_job.h" 18 #include "chrome/browser/printing/print_job.h"
17 #include "chrome/browser/printing/print_job_manager.h" 19 #include "chrome/browser/printing/print_job_manager.h"
18 #include "chrome/browser/printing/printer_query.h" 20 #include "chrome/browser/printing/printer_query.h"
19 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/simple_message_box.h" 22 #include "chrome/browser/ui/simple_message_box.h"
21 #include "chrome/common/pref_names.h" 23 #include "chrome/common/pref_names.h"
22 #include "chrome/common/print_messages.h" 24 #include "chrome/common/print_messages.h"
23 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_details.h" 26 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/notification_source.h" 28 #include "content/public/browser/notification_source.h"
27 #include "content/public/browser/render_view_host.h" 29 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h" 30 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_view.h" 31 #include "content/public/browser/web_contents_view.h"
30 #include "grit/generated_resources.h" 32 #include "grit/generated_resources.h"
31 #include "printing/metafile_impl.h" 33 #include "printing/metafile_impl.h"
34 #include "printing/pdf_render_settings.h"
32 #include "printing/printed_document.h" 35 #include "printing/printed_document.h"
33 #include "ui/base/l10n/l10n_util.h" 36 #include "ui/base/l10n/l10n_util.h"
34 37
35 #if defined(OS_WIN) 38 #if defined(OS_WIN)
36 #include "base/command_line.h" 39 #include "base/command_line.h"
37 #include "chrome/common/chrome_switches.h" 40 #include "chrome/common/chrome_switches.h"
38 #endif 41 #endif
39 42
40 #if defined(ENABLE_FULL_PRINTING) 43 #if defined(ENABLE_FULL_PRINTING)
41 #include "chrome/browser/printing/print_error_dialog.h" 44 #include "chrome/browser/printing/print_error_dialog.h"
42 #endif 45 #endif
43 46
44 using base::TimeDelta; 47 using base::TimeDelta;
45 using content::BrowserThread; 48 using content::BrowserThread;
46 49
47 #if defined(OS_WIN) 50 #if !defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
48 // Limits memory usage by raster to 64 MiB. 51 // Limits memory usage by raster to 64 MiB.
49 const int kMaxRasterSizeInPixels = 16*1024*1024; 52 const int kMaxRasterSizeInPixels = 16*1024*1024;
50 #endif 53 #endif
51 54
52 namespace printing { 55 namespace printing {
53 56
54 PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) 57 PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
55 : content::WebContentsObserver(web_contents), 58 : content::WebContentsObserver(web_contents),
56 number_pages_(0), 59 number_pages_(0),
57 printing_succeeded_(false), 60 printing_succeeded_(false),
58 inside_inner_message_loop_(false), 61 inside_inner_message_loop_(false),
59 cookie_(0), 62 cookie_(0),
60 queue_(g_browser_process->print_job_manager()->queue()) { 63 queue_(g_browser_process->print_job_manager()->queue()) {
61 DCHECK(queue_); 64 DCHECK(queue_);
62 #if defined(OS_POSIX) && !defined(OS_MACOSX) 65 #if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \
66 defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
63 expecting_first_page_ = true; 67 expecting_first_page_ = true;
64 #endif 68 #endif
65 Profile* profile = 69 Profile* profile =
66 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 70 Profile::FromBrowserContext(web_contents->GetBrowserContext());
67 printing_enabled_.Init( 71 printing_enabled_.Init(
68 prefs::kPrintingEnabled, 72 prefs::kPrintingEnabled,
69 profile->GetPrefs(), 73 profile->GetPrefs(),
70 base::Bind(&PrintViewManagerBase::UpdateScriptedPrintingBlocked, 74 base::Bind(&PrintViewManagerBase::UpdateScriptedPrintingBlocked,
71 base::Unretained(this))); 75 base::Unretained(this)));
72 } 76 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 DCHECK_GT(cookie, 0); 122 DCHECK_GT(cookie, 0);
119 DCHECK_GT(number_pages, 0); 123 DCHECK_GT(number_pages, 0);
120 number_pages_ = number_pages; 124 number_pages_ = number_pages;
121 OpportunisticallyCreatePrintJob(cookie); 125 OpportunisticallyCreatePrintJob(cookie);
122 } 126 }
123 127
124 void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) { 128 void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) {
125 cookie_ = cookie; 129 cookie_ = cookie;
126 } 130 }
127 131
132 #if defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
133 void PrintViewManagerBase::OnPdfToEmfConverted(
134 const PrintHostMsg_DidPrintPage_Params& params,
135 bool success,
136 const base::FilePath& emf_file) {
137 PrintedDocument* document = print_job_->document();
Vitaly Buka (NO REVIEWS) 2014/04/25 22:35:24 this metafile could be multi paged. it's likely in
Vitaly Buka (NO REVIEWS) 2014/04/25 22:42:16 single string -> single stream of concatenated pag
scottmg 2014/04/25 22:45:10 This is only called from OnDidPrintPage, where it'
138 if (!document)
139 return;
140 scoped_ptr<printing::Emf> metafile(new printing::Emf);
141 if (!metafile->InitFromFile(emf_file)) {
142 NOTREACHED() << "Invalid metafile";
143 web_contents()->Stop();
144 return;
145 }
146 // Update the rendered document. It will send notifications to the listener.
147 document->SetPage(params.page_number,
148 metafile.release(),
149 params.actual_shrink,
150 params.page_size,
151 params.content_area);
152
153 ShouldQuitFromInnerMessageLoop();
154 }
155 #endif // PRINTING_WIN_USES_PDF_AS_METAFILE
156
128 void PrintViewManagerBase::OnDidPrintPage( 157 void PrintViewManagerBase::OnDidPrintPage(
129 const PrintHostMsg_DidPrintPage_Params& params) { 158 const PrintHostMsg_DidPrintPage_Params& params) {
130 if (!OpportunisticallyCreatePrintJob(params.document_cookie)) 159 if (!OpportunisticallyCreatePrintJob(params.document_cookie))
131 return; 160 return;
132 161
133 PrintedDocument* document = print_job_->document(); 162 PrintedDocument* document = print_job_->document();
134 if (!document || params.document_cookie != document->cookie()) { 163 if (!document || params.document_cookie != document->cookie()) {
135 // Out of sync. It may happen since we are completely asynchronous. Old 164 // Out of sync. It may happen since we are completely asynchronous. Old
136 // spurious messages can be received if one of the processes is overloaded. 165 // spurious messages can be received if one of the processes is overloaded.
137 return; 166 return;
138 } 167 }
139 168
140 #if defined(OS_WIN) || defined(OS_MACOSX) 169 #if !defined(PRINTING_WIN_USES_PDF_AS_METAFILE) || defined(OS_MACOSX)
141 const bool metafile_must_be_valid = true; 170 const bool metafile_must_be_valid = true;
142 #elif defined(OS_POSIX) 171 #elif defined(OS_POSIX) || defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
143 const bool metafile_must_be_valid = expecting_first_page_; 172 const bool metafile_must_be_valid = expecting_first_page_;
144 expecting_first_page_ = false; 173 expecting_first_page_ = false;
145 #endif 174 #endif
146 175
147 base::SharedMemory shared_buf(params.metafile_data_handle, true); 176 base::SharedMemory shared_buf(params.metafile_data_handle, true);
148 if (metafile_must_be_valid) { 177 if (metafile_must_be_valid) {
149 if (!shared_buf.Map(params.data_size)) { 178 if (!shared_buf.Map(params.data_size)) {
150 NOTREACHED() << "couldn't map"; 179 NOTREACHED() << "couldn't map";
151 web_contents()->Stop(); 180 web_contents()->Stop();
152 return; 181 return;
153 } 182 }
154 } 183 }
155 184
185 #if !defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
156 scoped_ptr<NativeMetafile> metafile(new NativeMetafile); 186 scoped_ptr<NativeMetafile> metafile(new NativeMetafile);
157 if (metafile_must_be_valid) { 187 if (metafile_must_be_valid) {
158 if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { 188 if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
159 NOTREACHED() << "Invalid metafile header"; 189 NOTREACHED() << "Invalid metafile header";
160 web_contents()->Stop(); 190 web_contents()->Stop();
161 return; 191 return;
162 } 192 }
163 } 193 }
164 194
165 #if defined(OS_WIN)
166 bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize); 195 bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize);
167 int raster_size = std::min(params.page_size.GetArea(), 196 int raster_size = std::min(params.page_size.GetArea(),
168 kMaxRasterSizeInPixels); 197 kMaxRasterSizeInPixels);
169 if (big_emf) { 198 if (big_emf) {
170 scoped_ptr<NativeMetafile> raster_metafile( 199 scoped_ptr<NativeMetafile> raster_metafile(
171 metafile->RasterizeMetafile(raster_size)); 200 metafile->RasterizeMetafile(raster_size));
172 if (raster_metafile.get()) { 201 if (raster_metafile.get()) {
173 metafile.swap(raster_metafile); 202 metafile.swap(raster_metafile);
174 } else if (big_emf) { 203 } else if (big_emf) {
175 // Don't fall back to emf here. 204 // Don't fall back to emf here.
176 NOTREACHED() << "size:" << params.data_size; 205 NOTREACHED() << "size:" << params.data_size;
177 TerminatePrintJob(true); 206 TerminatePrintJob(true);
178 web_contents()->Stop(); 207 web_contents()->Stop();
179 return; 208 return;
180 } 209 }
181 } 210 }
182 #endif
183 211
184 // Update the rendered document. It will send notifications to the listener. 212 // Update the rendered document. It will send notifications to the listener.
185 document->SetPage(params.page_number, 213 document->SetPage(params.page_number,
186 metafile.release(), 214 metafile.release(),
187 params.actual_shrink, 215 params.actual_shrink,
188 params.page_size, 216 params.page_size,
189 params.content_area); 217 params.content_area);
190 218
191 ShouldQuitFromInnerMessageLoop(); 219 ShouldQuitFromInnerMessageLoop();
220 #elif defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
221 base::RefCountedBytes* bytes = new base::RefCountedBytes(
222 reinterpret_cast<const unsigned char*>(shared_buf.memory()),
223 params.data_size);
224
225 if (!pdf_to_emf_converter_)
226 pdf_to_emf_converter_ = PdfToEmfConverter::CreateDefault();
227
228 /* XXX
scottmg 2014/04/25 20:47:18 Not sure what the correct way to get a printer DC
Vitaly Buka (NO REVIEWS) 2014/04/25 22:35:24 you don't need dc here, params.printable_area is p
scottmg 2014/04/25 22:45:10 Ah! Thanks.
229 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
230 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
231 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
232 */
233 int printer_dpi = 300;
234 int dc_width = 300*8.5;
235 int dc_height = 300*11;
236 gfx::Rect render_area(0, 0, dc_width, dc_height);
237 pdf_to_emf_converter_->Start(
238 bytes,
239 printing::PdfRenderSettings(render_area, printer_dpi, false),
240 base::Bind(&PrintViewManagerBase::OnPdfToEmfConverted,
241 base::Unretained(this),
242 params));
243 #endif
192 } 244 }
193 245
194 void PrintViewManagerBase::OnPrintingFailed(int cookie) { 246 void PrintViewManagerBase::OnPrintingFailed(int cookie) {
195 if (cookie != cookie_) { 247 if (cookie != cookie_) {
196 NOTREACHED(); 248 NOTREACHED();
197 return; 249 return;
198 } 250 }
199 251
200 #if defined(ENABLE_FULL_PRINTING) 252 #if defined(ENABLE_FULL_PRINTING)
201 chrome::ShowPrintErrorDialog(); 253 chrome::ShowPrintErrorDialog();
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 if (print_job_.get() && 440 if (print_job_.get() &&
389 print_job_->document() && 441 print_job_->document() &&
390 !print_job_->document()->IsComplete()) { 442 !print_job_->document()->IsComplete()) {
391 DCHECK(!result); 443 DCHECK(!result);
392 // That failed. 444 // That failed.
393 TerminatePrintJob(true); 445 TerminatePrintJob(true);
394 } else { 446 } else {
395 // DO NOT wait for the job to finish. 447 // DO NOT wait for the job to finish.
396 ReleasePrintJob(); 448 ReleasePrintJob();
397 } 449 }
398 #if defined(OS_POSIX) && !defined(OS_MACOSX) 450 #if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \
451 defined(PRINTING_WIN_USES_PDF_AS_METAFILE)
399 expecting_first_page_ = true; 452 expecting_first_page_ = true;
400 #endif 453 #endif
401 } 454 }
402 455
403 void PrintViewManagerBase::PrintingDone(bool success) { 456 void PrintViewManagerBase::PrintingDone(bool success) {
404 if (!print_job_.get()) 457 if (!print_job_.get())
405 return; 458 return;
406 Send(new PrintMsg_PrintingDone(routing_id(), success)); 459 Send(new PrintMsg_PrintingDone(routing_id(), success));
407 } 460 }
408 461
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 scoped_refptr<printing::PrinterQuery> printer_query; 585 scoped_refptr<printing::PrinterQuery> printer_query;
533 printer_query = queue_->PopPrinterQuery(cookie); 586 printer_query = queue_->PopPrinterQuery(cookie);
534 if (!printer_query) 587 if (!printer_query)
535 return; 588 return;
536 BrowserThread::PostTask( 589 BrowserThread::PostTask(
537 BrowserThread::IO, FROM_HERE, 590 BrowserThread::IO, FROM_HERE,
538 base::Bind(&PrinterQuery::StopWorker, printer_query.get())); 591 base::Bind(&PrinterQuery::StopWorker, printer_query.get()));
539 } 592 }
540 593
541 } // namespace printing 594 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698