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

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

Issue 2829973002: add customized printing setting for headless (Closed)
Patch Set: adjust command interface and add unit tests Created 3 years, 7 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 2017 The Chromium Authors. All rights reserved. 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 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 "headless/lib/browser/headless_print_manager.h" 5 #include "headless/lib/browser/headless_print_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_piece.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/utf_string_conversions.h"
11 #include "components/printing/browser/print_manager_utils.h" 16 #include "components/printing/browser/print_manager_utils.h"
12 #include "components/printing/common/print_messages.h" 17 #include "components/printing/common/print_messages.h"
13 #include "printing/pdf_metafile_skia.h" 18 #include "printing/pdf_metafile_skia.h"
14 #include "printing/print_settings.h" 19 #include "printing/print_job_constants.h"
15 #include "printing/units.h" 20 #include "printing/units.h"
21 #include "ui/gfx/geometry/size_f.h"
16 22
17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::HeadlessPrintManager); 23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::HeadlessPrintManager);
18 24
19 namespace printing { 25 namespace printing {
20 26
21 namespace { 27 HeadlessPrintSettings::HeadlessPrintSettings()
28 : paper_type(NA_LETTER),
Sami 2017/04/27 17:54:55 Looks like not all fields are being initialized (y
jzfeng 2017/05/02 07:50:56 Done. This part is moved into header with all the
29 margin_type(DEFAULT_MARGINS),
30 landscape(false),
31 display_header_footer(false),
32 should_print_backgrounds(false),
33 scale(1) {}
22 34
23 // TODO(jzfeng): let the print settings to be configurable. 35 HeadlessPrintSettings::HeadlessPrintSettings(const HeadlessPrintSettings& obj) =
24 const double kTopMarginInInch = 0.25; 36 default;
25 const double kBottomMarginInInch = 0.56; 37 HeadlessPrintSettings::~HeadlessPrintSettings() = default;
26 const double kLeftMarginInInch = 0.25;
27 const double kRightMarginInInch = 0.25;
28 38
29 PrintSettings GetDefaultPDFPrinterSettings() { 39 gfx::Size HeadlessPrintSettings::PaperSizeInPoints() {
30 #if defined(OS_MACOSX) 40 gfx::SizeF paper_size(paper_width_in_inch, paper_height_in_inch);
31 // On the Mac, the printable area is in points, use kPointsPerInch to compute 41 switch (paper_type) {
32 // its bounds. 42 case NA_LETTER:
33 int dpi = kPointsPerInch; 43 paper_size.SetSize(kLetterWidthInch, kLetterHeightInch);
34 #else 44 break;
35 int dpi = kDefaultPdfDpi; 45 case NA_LEGAL:
36 #endif 46 paper_size.SetSize(kLegalWidthInch, kLegalHeightInch);
37 gfx::Size physical_size_device_units; 47 break;
38 gfx::Rect printable_area_device_units; 48 case ISO_A4:
39 double page_width_in_pixel = kLetterWidthInch * dpi; 49 paper_size.SetSize(kA4WidthInch, kA4HeightInch);
40 double page_height_in_pixel = kLetterHeightInch * dpi; 50 break;
41 physical_size_device_units.SetSize(static_cast<int>(page_width_in_pixel), 51 case ISO_A3:
42 static_cast<int>(page_height_in_pixel)); 52 paper_size.SetSize(kA3WidthInch, kA3HeightInch);
43 printable_area_device_units.SetRect( 53 break;
44 static_cast<int>(kLeftMarginInInch * dpi), 54 default: // Customized paper size
45 static_cast<int>(kTopMarginInInch * dpi), 55 break;
46 page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi, 56 }
47 page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi); 57 return gfx::Size(paper_size.width() * kPointsPerInch,
48 58 paper_size.height() * kPointsPerInch);
49 PrintSettings settings;
50 settings.set_dpi(dpi);
51 settings.SetPrinterPrintableArea(physical_size_device_units,
52 printable_area_device_units, true);
53 settings.set_should_print_backgrounds(true);
54 return settings;
55 } 59 }
56 60
57 } // namespace 61 PageMargins HeadlessPrintSettings::MarginInPoints() {
62 PageMargins margins_in_points;
63 margins_in_points.top = margin_top_in_inch * kPointsPerInch;
64 margins_in_points.bottom = margin_bottom_in_inch * kPointsPerInch;
65 margins_in_points.left = margin_left_in_inch * kPointsPerInch;
66 margins_in_points.right = margin_right_in_inch * kPointsPerInch;
67 return margins_in_points;
68 }
58 69
59 HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents) 70 HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents)
60 : PrintManager(web_contents) { 71 : PrintManager(web_contents) {
61 Reset(); 72 Reset();
62 } 73 }
63 74
64 HeadlessPrintManager::~HeadlessPrintManager() {} 75 HeadlessPrintManager::~HeadlessPrintManager() {}
65 76
66 // static 77 // static
67 std::string HeadlessPrintManager::PrintResultToString(PrintResult result) { 78 std::string HeadlessPrintManager::PrintResultToString(PrintResult result) {
68 switch (result) { 79 switch (result) {
69 case PRINT_SUCCESS: 80 case PRINT_SUCCESS:
70 return std::string(); // no error message 81 return std::string(); // no error message
71 case PRINTING_FAILED: 82 case PRINTING_FAILED:
72 return "Printing failed"; 83 return "Printing failed";
73 case INVALID_PRINTER_SETTINGS: 84 case INVALID_PRINTER_SETTINGS:
74 return "Show invalid printer settings error"; 85 return "Show invalid printer settings error";
75 case INVALID_MEMORY_HANDLE: 86 case INVALID_MEMORY_HANDLE:
76 return "Invalid memory handle"; 87 return "Invalid memory handle";
77 case METAFILE_MAP_ERROR: 88 case METAFILE_MAP_ERROR:
78 return "Map to shared memory error"; 89 return "Map to shared memory error";
79 case UNEXPECTED_VALID_MEMORY_HANDLE: 90 case UNEXPECTED_VALID_MEMORY_HANDLE:
80 return "Unexpected valide memory handle"; 91 return "Unexpected valide memory handle";
81 case METAFILE_INVALID_HEADER: 92 case METAFILE_INVALID_HEADER:
82 return "Invalid metafile header"; 93 return "Invalid metafile header";
83 case METAFILE_GET_DATA_ERROR: 94 case METAFILE_GET_DATA_ERROR:
84 return "Get data from metafile error"; 95 return "Get data from metafile error";
85 case SIMULTANEOUS_PRINT_ACTIVE: 96 case SIMULTANEOUS_PRINT_ACTIVE:
86 return "The previous printing job hasn't finished"; 97 return "The previous printing job hasn't finished";
98 case PAGE_RANGE_SYNTAX_ERROR:
99 return "Page range syntax error";
100 case PAGE_COUNT_EXCEEDED:
101 return "Page range exceeds page count";
87 default: 102 default:
88 NOTREACHED(); 103 NOTREACHED();
89 return "Unknown PrintResult"; 104 return "Unknown PrintResult";
90 } 105 }
91 } 106 }
92 107
93 // static 108 // static
94 std::unique_ptr<base::DictionaryValue> 109 std::unique_ptr<base::DictionaryValue>
95 HeadlessPrintManager::PDFContentsToDictionaryValue(const std::string& data) { 110 HeadlessPrintManager::PDFContentsToDictionaryValue(const std::string& data) {
96 std::string base_64_data; 111 std::string base_64_data;
97 base::Base64Encode(data, &base_64_data); 112 base::Base64Encode(data, &base_64_data);
98 auto result = base::MakeUnique<base::DictionaryValue>(); 113 auto result = base::MakeUnique<base::DictionaryValue>();
99 result->SetString("data", base_64_data); 114 result->SetString("data", base_64_data);
100 return result; 115 return result;
101 } 116 }
102 117
118 // static
119 HeadlessPrintManager::PageRangeStatus
120 HeadlessPrintManager::PageRangeTextToPages(std::string page_range_text,
121 int pages_count,
122 std::vector<int>* pages) {
123 PageRanges page_ranges;
124 for (const auto& range_string :
125 base::SplitStringPiece(page_range_text, ",", base::TRIM_WHITESPACE,
126 base::SPLIT_WANT_NONEMPTY)) {
127 printing::PageRange range;
128 if (range_string.find("-") == base::StringPiece::npos) {
129 if (!base::StringToInt(range_string, &range.from))
130 return SYNTAX_ERROR;
131 range.to = range.from;
132 } else if (range_string == "-") {
133 range.from = 1;
134 range.to = pages_count;
135 } else if (range_string.starts_with("-")) {
136 range.from = 1;
137 if (!base::StringToInt(range_string.substr(1), &range.to))
138 return SYNTAX_ERROR;
139 } else if (range_string.ends_with("-")) {
140 range.to = pages_count;
141 if (!base::StringToInt(range_string.substr(0, range_string.length() - 1),
142 &range.from))
143 return SYNTAX_ERROR;
144 } else {
145 auto tokens = base::SplitStringPiece(
146 range_string, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
147 if (tokens.size() != 2 || !base::StringToInt(tokens[0], &range.from) ||
148 !base::StringToInt(tokens[1], &range.to))
149 return SYNTAX_ERROR;
150 }
151
152 if (range.from < 1 || range.from > range.to)
153 return SYNTAX_ERROR;
154 if (range.to > pages_count)
155 return LIMIT_ERROR;
156
157 // Page numbers are 1-based in the dictionary.
158 // Page numbers are 0-based for the print settings.
159 range.from--;
160 range.to--;
161 page_ranges.push_back(range);
162 }
163 *pages = PageRange::GetPages(page_ranges);
164 return NO_ERROR;
165 }
166
103 void HeadlessPrintManager::GetPDFContents(content::RenderFrameHost* rfh, 167 void HeadlessPrintManager::GetPDFContents(content::RenderFrameHost* rfh,
168 const HeadlessPrintSettings& settings,
104 const GetPDFCallback& callback) { 169 const GetPDFCallback& callback) {
105 DCHECK(callback); 170 DCHECK(callback);
106 171
107 if (callback_) { 172 if (callback_) {
108 callback.Run(SIMULTANEOUS_PRINT_ACTIVE, std::string()); 173 callback.Run(SIMULTANEOUS_PRINT_ACTIVE, std::string());
109 return; 174 return;
110 } 175 }
111 printing_rfh_ = rfh; 176 printing_rfh_ = rfh;
112 callback_ = callback; 177 callback_ = callback;
178 print_params_ = PrintParams(settings);
179 page_ranges_text_ = settings.page_ranges;
113 rfh->Send(new PrintMsg_PrintPages(rfh->GetRoutingID())); 180 rfh->Send(new PrintMsg_PrintPages(rfh->GetRoutingID()));
114 } 181 }
115 182
183 std::unique_ptr<PrintMsg_PrintPages_Params> HeadlessPrintManager::PrintParams(
184 HeadlessPrintSettings settings) {
185 PrintSettings print_settings;
186 print_settings.set_dpi(kPointsPerInch);
187 print_settings.set_should_print_backgrounds(
188 settings.should_print_backgrounds);
189 print_settings.set_scale_factor(settings.scale);
190 print_settings.SetOrientation(settings.landscape);
191
192 print_settings.set_display_header_footer(settings.display_header_footer);
193 if (print_settings.display_header_footer()) {
194 url::Replacements<char> url_sanitizer;
195 url_sanitizer.ClearUsername();
196 url_sanitizer.ClearPassword();
197 std::string url = printing_rfh_->GetLastCommittedURL()
198 .ReplaceComponents(url_sanitizer)
199 .spec();
200 print_settings.set_url(base::UTF8ToUTF16(url));
201 }
202
203 print_settings.set_margin_type(settings.margin_type);
204 if (settings.margin_type == CUSTOM_MARGINS)
205 print_settings.SetCustomMargins(settings.MarginInPoints());
206
207 gfx::Size physical_size_device_units = settings.PaperSizeInPoints();
208 gfx::Rect printable_area_device_units(physical_size_device_units);
209 print_settings.SetPrinterPrintableArea(physical_size_device_units,
210 printable_area_device_units, true);
211
212 auto print_params = base::MakeUnique<PrintMsg_PrintPages_Params>();
213 RenderParamsFromPrintSettings(print_settings, &print_params->params);
214 print_params->params.document_cookie = PrintSettings::NewCookie();
215 return print_params;
216 }
217
116 bool HeadlessPrintManager::OnMessageReceived( 218 bool HeadlessPrintManager::OnMessageReceived(
117 const IPC::Message& message, 219 const IPC::Message& message,
118 content::RenderFrameHost* render_frame_host) { 220 content::RenderFrameHost* render_frame_host) {
119 bool handled = true; 221 bool handled = true;
120 IPC_BEGIN_MESSAGE_MAP(HeadlessPrintManager, message) 222 IPC_BEGIN_MESSAGE_MAP(HeadlessPrintManager, message)
121 IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, 223 IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
122 OnShowInvalidPrinterSettingsError) 224 OnShowInvalidPrinterSettingsError)
123 IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) 225 IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage)
124 IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, 226 IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
125 OnGetDefaultPrintSettings) 227 OnGetDefaultPrintSettings)
228 IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
126 IPC_MESSAGE_UNHANDLED(handled = false) 229 IPC_MESSAGE_UNHANDLED(handled = false)
127 IPC_END_MESSAGE_MAP() 230 IPC_END_MESSAGE_MAP()
128 return handled || PrintManager::OnMessageReceived(message, render_frame_host); 231 return handled || PrintManager::OnMessageReceived(message, render_frame_host);
129 } 232 }
130 233
131 void HeadlessPrintManager::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { 234 void HeadlessPrintManager::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
132 PrintMsg_Print_Params print_params;
133 RenderParamsFromPrintSettings(GetDefaultPDFPrinterSettings(), &print_params);
134 print_params.document_cookie = PrintSettings::NewCookie();
135 PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, 235 PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg,
136 print_params); 236 print_params_->params);
137 printing_rfh_->Send(reply_msg); 237 printing_rfh_->Send(reply_msg);
138 } 238 }
139 239
240 void HeadlessPrintManager::OnScriptedPrint(
241 const PrintHostMsg_ScriptedPrint_Params& params,
242 IPC::Message* reply_msg) {
243 PageRangeStatus status = PageRangeTextToPages(
244 page_ranges_text_, params.expected_pages_count, &print_params_->pages);
245 switch (status) {
246 case SYNTAX_ERROR:
247 printing_rfh_->Send(reply_msg);
248 ReleaseJob(PAGE_RANGE_SYNTAX_ERROR);
249 return;
250 case LIMIT_ERROR:
251 printing_rfh_->Send(reply_msg);
252 ReleaseJob(PAGE_COUNT_EXCEEDED);
253 return;
254 default:
255 PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, *print_params_);
256 printing_rfh_->Send(reply_msg);
257 return;
258 }
259 }
260
140 void HeadlessPrintManager::OnShowInvalidPrinterSettingsError() { 261 void HeadlessPrintManager::OnShowInvalidPrinterSettingsError() {
141 ReleaseJob(INVALID_PRINTER_SETTINGS); 262 ReleaseJob(INVALID_PRINTER_SETTINGS);
142 } 263 }
143 264
144 void HeadlessPrintManager::OnPrintingFailed(int cookie) { 265 void HeadlessPrintManager::OnPrintingFailed(int cookie) {
145 ReleaseJob(PRINTING_FAILED); 266 ReleaseJob(PRINTING_FAILED);
146 } 267 }
147 268
269 void HeadlessPrintManager::OnDidGetPrintedPagesCount(int cookie,
270 int number_pages) {
271 PrintManager::OnDidGetPrintedPagesCount(cookie, number_pages);
272 if (!print_params_->pages.empty())
273 number_pages_ = print_params_->pages.size();
274 }
275
148 void HeadlessPrintManager::OnDidPrintPage( 276 void HeadlessPrintManager::OnDidPrintPage(
149 const PrintHostMsg_DidPrintPage_Params& params) { 277 const PrintHostMsg_DidPrintPage_Params& params) {
150 if (!callback_) { 278 if (!callback_) {
151 DLOG(ERROR) 279 DLOG(ERROR)
152 << "Unexpected PrintHostMsg_DidPrintPage message from the renderer"; 280 << "Unexpected PrintHostMsg_DidPrintPage message from the renderer";
153 return; 281 return;
154 } 282 }
155 283
156 const bool metafile_must_be_valid = expecting_first_page_; 284 const bool metafile_must_be_valid = expecting_first_page_;
157 expecting_first_page_ = false; 285 expecting_first_page_ = false;
(...skipping 28 matching lines...) Expand all
186 } 314 }
187 } 315 }
188 316
189 if (--number_pages_ == 0) 317 if (--number_pages_ == 0)
190 ReleaseJob(PRINT_SUCCESS); 318 ReleaseJob(PRINT_SUCCESS);
191 } 319 }
192 320
193 void HeadlessPrintManager::Reset() { 321 void HeadlessPrintManager::Reset() {
194 printing_rfh_ = nullptr; 322 printing_rfh_ = nullptr;
195 callback_.Reset(); 323 callback_.Reset();
324 print_params_.reset();
325 page_ranges_text_.clear();
196 data_.clear(); 326 data_.clear();
197 expecting_first_page_ = true; 327 expecting_first_page_ = true;
198 number_pages_ = 0; 328 number_pages_ = 0;
199 } 329 }
200 330
201 void HeadlessPrintManager::ReleaseJob(PrintResult result) { 331 void HeadlessPrintManager::ReleaseJob(PrintResult result) {
202 if (!callback_) { 332 if (!callback_) {
203 DLOG(ERROR) << "ReleaseJob is called when callback_ is null. Check whether " 333 DLOG(ERROR) << "ReleaseJob is called when callback_ is null. Check whether "
204 "ReleaseJob is called more than once."; 334 "ReleaseJob is called more than once.";
205 return; 335 return;
206 } 336 }
207 337
208 if (result == PRINT_SUCCESS) 338 if (result == PRINT_SUCCESS)
209 callback_.Run(result, std::move(data_)); 339 callback_.Run(result, std::move(data_));
210 else 340 else
211 callback_.Run(result, std::string()); 341 callback_.Run(result, std::string());
212 printing_rfh_->Send(new PrintMsg_PrintingDone(printing_rfh_->GetRoutingID(), 342 printing_rfh_->Send(new PrintMsg_PrintingDone(printing_rfh_->GetRoutingID(),
213 result == PRINT_SUCCESS)); 343 result == PRINT_SUCCESS));
214 Reset(); 344 Reset();
215 } 345 }
216 346
217 } // namespace printing 347 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698