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

Side by Side Diff: headless/lib/browser/headless_print_manager.cc

Issue 2780433002: add print to pdf for headless (Closed)
Patch Set: fix lint and style errors Created 3 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
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 #include "headless/lib/browser/headless_print_manager.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/base64.h"
11 #include "components/printing/browser/print_manager_utils.h"
12 #include "components/printing/common/print_messages.h"
13 #include "printing/pdf_metafile_skia.h"
14 #include "printing/print_settings.h"
15 #include "printing/units.h"
16
17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::HeadlessPrintManager);
18
19 namespace printing {
20
21 namespace {
22
23 // TODO(jzfeng): let the print settings to be configurable.
24 const double kTopMarginInInch = 0.25;
25 const double kBottomMarginInInch = 0.56;
26 const double kLeftMarginInInch = 0.25;
27 const double kRightMarginInInch = 0.25;
28
29 PrintSettings GetDefaultPDFPrinterSettings() {
30 int dpi = kDefaultPdfDpi;
31 gfx::Size physical_size_device_units;
32 gfx::Rect printable_area_device_units;
33 double page_width_in_pixel = kLetterWidthInch * dpi;
34 double page_height_in_pixel = kLetterHeightInch * dpi;
35 physical_size_device_units.SetSize(static_cast<int>(page_width_in_pixel),
36 static_cast<int>(page_height_in_pixel));
37 printable_area_device_units.SetRect(
38 static_cast<int>(kLeftMarginInInch * dpi),
39 static_cast<int>(kTopMarginInInch * dpi),
40 page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi,
41 page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi);
42
43 PrintSettings settings;
44 settings.set_dpi(dpi);
45 settings.SetPrinterPrintableArea(physical_size_device_units,
46 printable_area_device_units, true);
47 settings.set_should_print_backgrounds(true);
48 return settings;
49 }
50
51 } // namespace
52
53 void HeadlessPrintManager::Reset() {
Lei Zhang 2017/03/29 05:30:16 Can you put these in the same order as they are de
jzfeng 2017/03/30 03:04:57 Done.
54 printing_rfh_ = nullptr;
55 data_.clear();
56 is_active_ = false;
57 #if !defined(OS_MACOSX)
58 expecting_first_page_ = true;
59 #endif
60 number_pages_ = 0;
61 }
62
63 HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents)
64 : PrintManager(web_contents) {
65 Reset();
66 }
67
68 HeadlessPrintManager::~HeadlessPrintManager() {}
69
70 // static
71 std::string HeadlessPrintManager::PrintResultToErrMsg(PrintResult result) {
Eric Seckler 2017/03/29 11:21:20 nit: PrintResultToString
jzfeng 2017/03/30 03:04:57 Done.
72 switch (result) {
73 case kPrintSuccess:
74 return ""; // no error message
75 case kPrintingFailed:
76 return "PrintingFailed";
77 case kInvalidPrinterSettings:
78 return "ShowInvalidPrinterSettingsError";
79 case kInvalidMemoryHandle:
80 return "Invalid memory handle";
81 case kMetafileMapError:
82 return "Map to SharedMemory error";
83 case kUnexpectedValidMemoryHandle:
84 return "Unexpected valide memory handle";
85 case kMetafileInvalidHeader:
86 return "Invalid metafile header";
87 case kMetafileGetDataError:
88 return "Get data from metafile error";
89 case kDuplicatedPrintingError:
90 return "The previous printing job hasn't finished";
91 default:
92 NOTREACHED();
93 return "Unknown PrintResult";
94 }
95 }
96
97 // static
98 std::unique_ptr<base::DictionaryValue>
99 HeadlessPrintManager::PDFContentsToDictionaryValue(const std::string& data) {
100 std::string base_64_data;
101 base::Base64Encode(data, &base_64_data);
102 auto result = base::MakeUnique<base::DictionaryValue>();
103 result->SetString("data", base_64_data);
104 return result;
105 }
106
107 void HeadlessPrintManager::GetPDFContents(content::RenderFrameHost* rfh,
108 const GetPDFCallback& callback) {
Lei Zhang 2017/03/29 05:30:15 Add DCHECK(callback);
jzfeng 2017/03/30 03:04:57 Done.
109 if (is_active_) {
110 callback.Run(kDuplicatedPrintingError, "");
111 return;
112 }
113 is_active_ = true;
114 printing_rfh_ = rfh;
115 callback_ = callback;
116 rfh->Send(new PrintMsg_PrintPages(rfh->GetRoutingID()));
117 }
118
119 bool HeadlessPrintManager::OnMessageReceived(
120 const IPC::Message& message,
121 content::RenderFrameHost* render_frame_host) {
122 bool handled = true;
123 IPC_BEGIN_MESSAGE_MAP(HeadlessPrintManager, message)
124 IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
125 OnShowInvalidPrinterSettingsError)
126 IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage)
127 IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
128 OnGetDefaultPrintSettings)
129 IPC_MESSAGE_UNHANDLED(handled = false)
130 IPC_END_MESSAGE_MAP()
131 return handled || PrintManager::OnMessageReceived(message, render_frame_host);
132 }
133
134 void HeadlessPrintManager::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
135 PrintMsg_Print_Params print_params;
136 RenderParamsFromPrintSettings(GetDefaultPDFPrinterSettings(), &print_params);
137 print_params.document_cookie = PrintSettings::NewCookie();
138 PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg,
139 print_params);
140 printing_rfh_->Send(reply_msg);
141 }
142
143 void HeadlessPrintManager::OnShowInvalidPrinterSettingsError() {
144 ReleaseJob(kInvalidPrinterSettings);
145 }
146
147 void HeadlessPrintManager::OnPrintingFailed(int cookie) {
148 ReleaseJob(kPrintingFailed);
149 }
150
151 void HeadlessPrintManager::OnDidPrintPage(
152 const PrintHostMsg_DidPrintPage_Params& params) {
153 #if defined(OS_MACOSX)
154 const bool metafile_must_be_valid = true;
155 #else
156 const bool metafile_must_be_valid = expecting_first_page_;
157 expecting_first_page_ = false;
158 #endif
159
160 // Only used when |metafile_must_be_valid| is true.
161 std::unique_ptr<base::SharedMemory> shared_buf;
162 if (metafile_must_be_valid) {
163 if (!base::SharedMemory::IsHandleValid(params.metafile_data_handle)) {
164 ReleaseJob(kInvalidMemoryHandle);
165 return;
166 }
167 shared_buf =
168 base::MakeUnique<base::SharedMemory>(params.metafile_data_handle, true);
169 if (!shared_buf->Map(params.data_size)) {
170 ReleaseJob(kMetafileMapError);
171 return;
172 }
173 } else {
174 if (base::SharedMemory::IsHandleValid(params.metafile_data_handle)) {
175 base::SharedMemory::CloseHandle(params.metafile_data_handle);
176 ReleaseJob(kUnexpectedValidMemoryHandle);
177 return;
178 }
179 }
180
181 auto metafile = base::MakeUnique<PdfMetafileSkia>(PDF_SKIA_DOCUMENT_TYPE);
182 if (metafile_must_be_valid) {
183 if (!metafile->InitFromData(shared_buf->memory(), params.data_size)) {
184 ReleaseJob(kMetafileInvalidHeader);
185 return;
186 }
187 std::vector<char> buffer;
188 if (!metafile->GetDataAsVector(&buffer)) {
189 ReleaseJob(kMetafileGetDataError);
190 return;
191 }
192 data_ = std::string(buffer.data(), buffer.size());
Eric Seckler 2017/03/29 11:21:19 This seems to override whatever is in data_. What
jzfeng 2017/03/30 03:04:57 You are right. This is a temporary solution. Looks
Lei Zhang 2017/04/06 08:08:42 Under normal operations, you should get 1 per page
193 }
194
195 if (--number_pages_ == 0)
196 ReleaseJob(kPrintSuccess);
197 }
198
199 void HeadlessPrintManager::ReleaseJob(PrintResult result) {
200 if (result == kPrintSuccess)
201 callback_.Run(result, std::move(data_));
202 else
203 callback_.Run(result, "");
Eric Seckler 2017/03/29 11:21:19 nit: std::string()
jzfeng 2017/03/30 03:04:57 Done.
204 printing_rfh_->Send(new PrintMsg_PrintingDone(printing_rfh_->GetRoutingID(),
205 result == kPrintSuccess));
206 Reset();
207 }
208
209 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698