Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / utility / printing_handler.cc
blob9e282adb467725a4549b0e24ca1d5c11502f8432
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/utility/printing_handler.h"
7 #include "base/files/file_util.h"
8 #include "base/lazy_instance.h"
9 #include "base/path_service.h"
10 #include "base/scoped_native_library.h"
11 #include "chrome/common/chrome_paths.h"
12 #include "chrome/common/chrome_utility_printing_messages.h"
13 #include "chrome/utility/cloud_print/bitmap_image.h"
14 #include "chrome/utility/cloud_print/pwg_encoder.h"
15 #include "content/public/utility/utility_thread.h"
16 #include "pdf/pdf.h"
17 #include "printing/page_range.h"
18 #include "printing/pdf_render_settings.h"
20 #if defined(OS_WIN)
21 #include "printing/emf_win.h"
22 #include "ui/gfx/gdi_util.h"
23 #endif
25 #if defined(ENABLE_PRINT_PREVIEW)
26 #include "chrome/common/crash_keys.h"
27 #include "printing/backend/print_backend.h"
28 #endif
30 namespace {
32 bool Send(IPC::Message* message) {
33 return content::UtilityThread::Get()->Send(message);
36 void ReleaseProcessIfNeeded() {
37 content::UtilityThread::Get()->ReleaseProcessIfNeeded();
40 } // namespace
42 PrintingHandler::PrintingHandler() {}
44 PrintingHandler::~PrintingHandler() {}
46 bool PrintingHandler::OnMessageReceived(const IPC::Message& message) {
47 bool handled = true;
48 IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message)
49 #if defined(OS_WIN)
50 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
51 OnRenderPDFPagesToMetafile)
52 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
53 OnRenderPDFPagesToMetafileGetPage)
54 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop,
55 OnRenderPDFPagesToMetafileStop)
56 #endif // OS_WIN
57 #if defined(ENABLE_PRINT_PREVIEW)
58 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToPWGRaster,
59 OnRenderPDFPagesToPWGRaster)
60 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults,
61 OnGetPrinterCapsAndDefaults)
62 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults,
63 OnGetPrinterSemanticCapsAndDefaults)
64 #endif // ENABLE_PRINT_PREVIEW
65 IPC_MESSAGE_UNHANDLED(handled = false)
66 IPC_END_MESSAGE_MAP()
67 return handled;
70 #if defined(OS_WIN)
71 void PrintingHandler::OnRenderPDFPagesToMetafile(
72 IPC::PlatformFileForTransit pdf_transit,
73 const printing::PdfRenderSettings& settings) {
74 pdf_rendering_settings_ = settings;
75 base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit);
76 int page_count = LoadPDF(pdf_file.Pass());
77 Send(
78 new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count));
81 void PrintingHandler::OnRenderPDFPagesToMetafileGetPage(
82 int page_number,
83 IPC::PlatformFileForTransit output_file) {
84 base::File emf_file = IPC::PlatformFileForTransitToFile(output_file);
85 float scale_factor = 1.0f;
86 bool success =
87 RenderPdfPageToMetafile(page_number, emf_file.Pass(), &scale_factor);
88 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone(
89 success, scale_factor));
92 void PrintingHandler::OnRenderPDFPagesToMetafileStop() {
93 ReleaseProcessIfNeeded();
96 #endif // OS_WIN
98 #if defined(ENABLE_PRINT_PREVIEW)
99 void PrintingHandler::OnRenderPDFPagesToPWGRaster(
100 IPC::PlatformFileForTransit pdf_transit,
101 const printing::PdfRenderSettings& settings,
102 const printing::PwgRasterSettings& bitmap_settings,
103 IPC::PlatformFileForTransit bitmap_transit) {
104 base::File pdf = IPC::PlatformFileForTransitToFile(pdf_transit);
105 base::File bitmap = IPC::PlatformFileForTransitToFile(bitmap_transit);
106 if (RenderPDFPagesToPWGRaster(pdf.Pass(), settings, bitmap_settings,
107 bitmap.Pass())) {
108 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded());
109 } else {
110 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed());
112 ReleaseProcessIfNeeded();
114 #endif // ENABLE_PRINT_PREVIEW
116 #if defined(OS_WIN)
117 int PrintingHandler::LoadPDF(base::File pdf_file) {
118 int64 length64 = pdf_file.GetLength();
119 if (length64 <= 0 || length64 > std::numeric_limits<int>::max())
120 return 0;
121 int length = static_cast<int>(length64);
123 pdf_data_.resize(length);
124 if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size()))
125 return 0;
127 int total_page_count = 0;
128 if (!chrome_pdf::GetPDFDocInfo(
129 &pdf_data_.front(), pdf_data_.size(), &total_page_count, NULL)) {
130 return 0;
132 return total_page_count;
135 bool PrintingHandler::RenderPdfPageToMetafile(int page_number,
136 base::File output_file,
137 float* scale_factor) {
138 printing::Emf metafile;
139 metafile.Init();
141 // We need to scale down DC to fit an entire page into DC available area.
142 // Current metafile is based on screen DC and have current screen size.
143 // Writing outside of those boundaries will result in the cut-off output.
144 // On metafiles (this is the case here), scaling down will still record
145 // original coordinates and we'll be able to print in full resolution.
146 // Before playback we'll need to counter the scaling up that will happen
147 // in the service (print_system_win.cc).
148 *scale_factor =
149 gfx::CalculatePageScale(metafile.context(),
150 pdf_rendering_settings_.area().right(),
151 pdf_rendering_settings_.area().bottom());
152 gfx::ScaleDC(metafile.context(), *scale_factor);
154 // The underlying metafile is of type Emf and ignores the arguments passed
155 // to StartPage.
156 metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
157 if (!chrome_pdf::RenderPDFPageToDC(
158 &pdf_data_.front(),
159 pdf_data_.size(),
160 page_number,
161 metafile.context(),
162 pdf_rendering_settings_.dpi(),
163 pdf_rendering_settings_.area().x(),
164 pdf_rendering_settings_.area().y(),
165 pdf_rendering_settings_.area().width(),
166 pdf_rendering_settings_.area().height(),
167 true,
168 false,
169 true,
170 true,
171 pdf_rendering_settings_.autorotate())) {
172 return false;
174 metafile.FinishPage();
175 metafile.FinishDocument();
176 return metafile.SaveTo(&output_file);
179 #endif // OS_WIN
181 #if defined(ENABLE_PRINT_PREVIEW)
182 bool PrintingHandler::RenderPDFPagesToPWGRaster(
183 base::File pdf_file,
184 const printing::PdfRenderSettings& settings,
185 const printing::PwgRasterSettings& bitmap_settings,
186 base::File bitmap_file) {
187 bool autoupdate = true;
188 base::File::Info info;
189 if (!pdf_file.GetInfo(&info) || info.size <= 0 ||
190 info.size > std::numeric_limits<int>::max())
191 return false;
192 int data_size = static_cast<int>(info.size);
194 std::string data(data_size, 0);
195 if (pdf_file.Read(0, &data[0], data_size) != data_size)
196 return false;
198 int total_page_count = 0;
199 if (!chrome_pdf::GetPDFDocInfo(data.data(), data_size,
200 &total_page_count, NULL)) {
201 return false;
204 cloud_print::PwgEncoder encoder;
205 std::string pwg_header;
206 encoder.EncodeDocumentHeader(&pwg_header);
207 int bytes_written = bitmap_file.WriteAtCurrentPos(pwg_header.data(),
208 pwg_header.size());
209 if (bytes_written != static_cast<int>(pwg_header.size()))
210 return false;
212 cloud_print::BitmapImage image(settings.area().size(),
213 cloud_print::BitmapImage::BGRA);
214 for (int i = 0; i < total_page_count; ++i) {
215 int page_number = i;
217 if (bitmap_settings.reverse_page_order) {
218 page_number = total_page_count - 1 - page_number;
221 if (!chrome_pdf::RenderPDFPageToBitmap(data.data(),
222 data_size,
223 page_number,
224 image.pixel_data(),
225 image.size().width(),
226 image.size().height(),
227 settings.dpi(),
228 autoupdate)) {
229 return false;
232 cloud_print::PwgHeaderInfo header_info;
233 header_info.dpi = settings.dpi();
234 header_info.total_pages = total_page_count;
236 // Transform odd pages.
237 if (page_number % 2) {
238 switch (bitmap_settings.odd_page_transform) {
239 case printing::TRANSFORM_NORMAL:
240 break;
241 case printing::TRANSFORM_ROTATE_180:
242 header_info.flipx = true;
243 header_info.flipy = true;
244 break;
245 case printing::TRANSFORM_FLIP_HORIZONTAL:
246 header_info.flipx = true;
247 break;
248 case printing::TRANSFORM_FLIP_VERTICAL:
249 header_info.flipy = true;
250 break;
254 if (bitmap_settings.rotate_all_pages) {
255 header_info.flipx = !header_info.flipx;
256 header_info.flipy = !header_info.flipy;
259 std::string pwg_page;
260 if (!encoder.EncodePage(image, header_info, &pwg_page))
261 return false;
262 bytes_written = bitmap_file.WriteAtCurrentPos(pwg_page.data(),
263 pwg_page.size());
264 if (bytes_written != static_cast<int>(pwg_page.size()))
265 return false;
267 return true;
270 void PrintingHandler::OnGetPrinterCapsAndDefaults(
271 const std::string& printer_name) {
272 scoped_refptr<printing::PrintBackend> print_backend =
273 printing::PrintBackend::CreateInstance(NULL);
274 printing::PrinterCapsAndDefaults printer_info;
276 crash_keys::ScopedPrinterInfo crash_key(
277 print_backend->GetPrinterDriverInfo(printer_name));
279 if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) {
280 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(
281 printer_name, printer_info));
282 } else {
283 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed(
284 printer_name));
286 ReleaseProcessIfNeeded();
289 void PrintingHandler::OnGetPrinterSemanticCapsAndDefaults(
290 const std::string& printer_name) {
291 scoped_refptr<printing::PrintBackend> print_backend =
292 printing::PrintBackend::CreateInstance(NULL);
293 printing::PrinterSemanticCapsAndDefaults printer_info;
295 crash_keys::ScopedPrinterInfo crash_key(
296 print_backend->GetPrinterDriverInfo(printer_name));
298 if (print_backend->GetPrinterSemanticCapsAndDefaults(printer_name,
299 &printer_info)) {
300 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded(
301 printer_name, printer_info));
302 } else {
303 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed(
304 printer_name));
306 ReleaseProcessIfNeeded();
308 #endif // ENABLE_PRINT_PREVIEW