Chromium Code Reviews| Index: headless/lib/browser/headless_print_manager.cc |
| diff --git a/headless/lib/browser/headless_print_manager.cc b/headless/lib/browser/headless_print_manager.cc |
| index a17c5a4486f3cc2ec64a4af5d84ae67cfd8e76d9..2c1156063e27c1f8cb8337c2292a88a9ebe9015c 100644 |
| --- a/headless/lib/browser/headless_print_manager.cc |
| +++ b/headless/lib/browser/headless_print_manager.cc |
| @@ -8,53 +8,64 @@ |
| #include <vector> |
| #include "base/base64.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/strings/string_piece.h" |
| +#include "base/strings/string_split.h" |
| +#include "base/strings/utf_string_conversions.h" |
| #include "components/printing/browser/print_manager_utils.h" |
| #include "components/printing/common/print_messages.h" |
| #include "printing/pdf_metafile_skia.h" |
| -#include "printing/print_settings.h" |
| +#include "printing/print_job_constants.h" |
| #include "printing/units.h" |
| +#include "ui/gfx/geometry/size_f.h" |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::HeadlessPrintManager); |
| namespace printing { |
| -namespace { |
| - |
| -// TODO(jzfeng): let the print settings to be configurable. |
| -const double kTopMarginInInch = 0.25; |
| -const double kBottomMarginInInch = 0.56; |
| -const double kLeftMarginInInch = 0.25; |
| -const double kRightMarginInInch = 0.25; |
| - |
| -PrintSettings GetDefaultPDFPrinterSettings() { |
| -#if defined(OS_MACOSX) |
| - // On the Mac, the printable area is in points, use kPointsPerInch to compute |
| - // its bounds. |
| - int dpi = kPointsPerInch; |
| -#else |
| - int dpi = kDefaultPdfDpi; |
| -#endif |
| - gfx::Size physical_size_device_units; |
| - gfx::Rect printable_area_device_units; |
| - double page_width_in_pixel = kLetterWidthInch * dpi; |
| - double page_height_in_pixel = kLetterHeightInch * dpi; |
| - physical_size_device_units.SetSize(static_cast<int>(page_width_in_pixel), |
| - static_cast<int>(page_height_in_pixel)); |
| - printable_area_device_units.SetRect( |
| - static_cast<int>(kLeftMarginInInch * dpi), |
| - static_cast<int>(kTopMarginInInch * dpi), |
| - page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi, |
| - page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi); |
| - |
| - PrintSettings settings; |
| - settings.set_dpi(dpi); |
| - settings.SetPrinterPrintableArea(physical_size_device_units, |
| - printable_area_device_units, true); |
| - settings.set_should_print_backgrounds(true); |
| - return settings; |
| -} |
| - |
| -} // namespace |
| +HeadlessPrintSettings::HeadlessPrintSettings() |
| + : 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
|
| + margin_type(DEFAULT_MARGINS), |
| + landscape(false), |
| + display_header_footer(false), |
| + should_print_backgrounds(false), |
| + scale(1) {} |
| + |
| +HeadlessPrintSettings::HeadlessPrintSettings(const HeadlessPrintSettings& obj) = |
| + default; |
| +HeadlessPrintSettings::~HeadlessPrintSettings() = default; |
| + |
| +gfx::Size HeadlessPrintSettings::PaperSizeInPoints() { |
| + gfx::SizeF paper_size(paper_width_in_inch, paper_height_in_inch); |
| + switch (paper_type) { |
| + case NA_LETTER: |
| + paper_size.SetSize(kLetterWidthInch, kLetterHeightInch); |
| + break; |
| + case NA_LEGAL: |
| + paper_size.SetSize(kLegalWidthInch, kLegalHeightInch); |
| + break; |
| + case ISO_A4: |
| + paper_size.SetSize(kA4WidthInch, kA4HeightInch); |
| + break; |
| + case ISO_A3: |
| + paper_size.SetSize(kA3WidthInch, kA3HeightInch); |
| + break; |
| + default: // Customized paper size |
| + break; |
| + } |
| + return gfx::Size(paper_size.width() * kPointsPerInch, |
| + paper_size.height() * kPointsPerInch); |
| +} |
| + |
| +PageMargins HeadlessPrintSettings::MarginInPoints() { |
| + PageMargins margins_in_points; |
| + margins_in_points.top = margin_top_in_inch * kPointsPerInch; |
| + margins_in_points.bottom = margin_bottom_in_inch * kPointsPerInch; |
| + margins_in_points.left = margin_left_in_inch * kPointsPerInch; |
| + margins_in_points.right = margin_right_in_inch * kPointsPerInch; |
| + return margins_in_points; |
| +} |
| HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents) |
| : PrintManager(web_contents) { |
| @@ -84,6 +95,10 @@ std::string HeadlessPrintManager::PrintResultToString(PrintResult result) { |
| return "Get data from metafile error"; |
| case SIMULTANEOUS_PRINT_ACTIVE: |
| return "The previous printing job hasn't finished"; |
| + case PAGE_RANGE_SYNTAX_ERROR: |
| + return "Page range syntax error"; |
| + case PAGE_COUNT_EXCEEDED: |
| + return "Page range exceeds page count"; |
| default: |
| NOTREACHED(); |
| return "Unknown PrintResult"; |
| @@ -100,7 +115,57 @@ HeadlessPrintManager::PDFContentsToDictionaryValue(const std::string& data) { |
| return result; |
| } |
| +// static |
| +HeadlessPrintManager::PageRangeStatus |
| +HeadlessPrintManager::PageRangeTextToPages(std::string page_range_text, |
| + int pages_count, |
| + std::vector<int>* pages) { |
| + PageRanges page_ranges; |
| + for (const auto& range_string : |
| + base::SplitStringPiece(page_range_text, ",", base::TRIM_WHITESPACE, |
| + base::SPLIT_WANT_NONEMPTY)) { |
| + printing::PageRange range; |
| + if (range_string.find("-") == base::StringPiece::npos) { |
| + if (!base::StringToInt(range_string, &range.from)) |
| + return SYNTAX_ERROR; |
| + range.to = range.from; |
| + } else if (range_string == "-") { |
| + range.from = 1; |
| + range.to = pages_count; |
| + } else if (range_string.starts_with("-")) { |
| + range.from = 1; |
| + if (!base::StringToInt(range_string.substr(1), &range.to)) |
| + return SYNTAX_ERROR; |
| + } else if (range_string.ends_with("-")) { |
| + range.to = pages_count; |
| + if (!base::StringToInt(range_string.substr(0, range_string.length() - 1), |
| + &range.from)) |
| + return SYNTAX_ERROR; |
| + } else { |
| + auto tokens = base::SplitStringPiece( |
| + range_string, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| + if (tokens.size() != 2 || !base::StringToInt(tokens[0], &range.from) || |
| + !base::StringToInt(tokens[1], &range.to)) |
| + return SYNTAX_ERROR; |
| + } |
| + |
| + if (range.from < 1 || range.from > range.to) |
| + return SYNTAX_ERROR; |
| + if (range.to > pages_count) |
| + return LIMIT_ERROR; |
| + |
| + // Page numbers are 1-based in the dictionary. |
| + // Page numbers are 0-based for the print settings. |
| + range.from--; |
| + range.to--; |
| + page_ranges.push_back(range); |
| + } |
| + *pages = PageRange::GetPages(page_ranges); |
| + return NO_ERROR; |
| +} |
| + |
| void HeadlessPrintManager::GetPDFContents(content::RenderFrameHost* rfh, |
| + const HeadlessPrintSettings& settings, |
| const GetPDFCallback& callback) { |
| DCHECK(callback); |
| @@ -110,9 +175,46 @@ void HeadlessPrintManager::GetPDFContents(content::RenderFrameHost* rfh, |
| } |
| printing_rfh_ = rfh; |
| callback_ = callback; |
| + print_params_ = PrintParams(settings); |
| + page_ranges_text_ = settings.page_ranges; |
| rfh->Send(new PrintMsg_PrintPages(rfh->GetRoutingID())); |
| } |
| +std::unique_ptr<PrintMsg_PrintPages_Params> HeadlessPrintManager::PrintParams( |
| + HeadlessPrintSettings settings) { |
| + PrintSettings print_settings; |
| + print_settings.set_dpi(kPointsPerInch); |
| + print_settings.set_should_print_backgrounds( |
| + settings.should_print_backgrounds); |
| + print_settings.set_scale_factor(settings.scale); |
| + print_settings.SetOrientation(settings.landscape); |
| + |
| + print_settings.set_display_header_footer(settings.display_header_footer); |
| + if (print_settings.display_header_footer()) { |
| + url::Replacements<char> url_sanitizer; |
| + url_sanitizer.ClearUsername(); |
| + url_sanitizer.ClearPassword(); |
| + std::string url = printing_rfh_->GetLastCommittedURL() |
| + .ReplaceComponents(url_sanitizer) |
| + .spec(); |
| + print_settings.set_url(base::UTF8ToUTF16(url)); |
| + } |
| + |
| + print_settings.set_margin_type(settings.margin_type); |
| + if (settings.margin_type == CUSTOM_MARGINS) |
| + print_settings.SetCustomMargins(settings.MarginInPoints()); |
| + |
| + gfx::Size physical_size_device_units = settings.PaperSizeInPoints(); |
| + gfx::Rect printable_area_device_units(physical_size_device_units); |
| + print_settings.SetPrinterPrintableArea(physical_size_device_units, |
| + printable_area_device_units, true); |
| + |
| + auto print_params = base::MakeUnique<PrintMsg_PrintPages_Params>(); |
| + RenderParamsFromPrintSettings(print_settings, &print_params->params); |
| + print_params->params.document_cookie = PrintSettings::NewCookie(); |
| + return print_params; |
| +} |
| + |
| bool HeadlessPrintManager::OnMessageReceived( |
| const IPC::Message& message, |
| content::RenderFrameHost* render_frame_host) { |
| @@ -123,20 +225,39 @@ bool HeadlessPrintManager::OnMessageReceived( |
| IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, |
| OnGetDefaultPrintSettings) |
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled || PrintManager::OnMessageReceived(message, render_frame_host); |
| } |
| void HeadlessPrintManager::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { |
| - PrintMsg_Print_Params print_params; |
| - RenderParamsFromPrintSettings(GetDefaultPDFPrinterSettings(), &print_params); |
| - print_params.document_cookie = PrintSettings::NewCookie(); |
| PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, |
| - print_params); |
| + print_params_->params); |
| printing_rfh_->Send(reply_msg); |
| } |
| +void HeadlessPrintManager::OnScriptedPrint( |
| + const PrintHostMsg_ScriptedPrint_Params& params, |
| + IPC::Message* reply_msg) { |
| + PageRangeStatus status = PageRangeTextToPages( |
| + page_ranges_text_, params.expected_pages_count, &print_params_->pages); |
| + switch (status) { |
| + case SYNTAX_ERROR: |
| + printing_rfh_->Send(reply_msg); |
| + ReleaseJob(PAGE_RANGE_SYNTAX_ERROR); |
| + return; |
| + case LIMIT_ERROR: |
| + printing_rfh_->Send(reply_msg); |
| + ReleaseJob(PAGE_COUNT_EXCEEDED); |
| + return; |
| + default: |
| + PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, *print_params_); |
| + printing_rfh_->Send(reply_msg); |
| + return; |
| + } |
| +} |
| + |
| void HeadlessPrintManager::OnShowInvalidPrinterSettingsError() { |
| ReleaseJob(INVALID_PRINTER_SETTINGS); |
| } |
| @@ -145,6 +266,13 @@ void HeadlessPrintManager::OnPrintingFailed(int cookie) { |
| ReleaseJob(PRINTING_FAILED); |
| } |
| +void HeadlessPrintManager::OnDidGetPrintedPagesCount(int cookie, |
| + int number_pages) { |
| + PrintManager::OnDidGetPrintedPagesCount(cookie, number_pages); |
| + if (!print_params_->pages.empty()) |
| + number_pages_ = print_params_->pages.size(); |
| +} |
| + |
| void HeadlessPrintManager::OnDidPrintPage( |
| const PrintHostMsg_DidPrintPage_Params& params) { |
| if (!callback_) { |
| @@ -193,6 +321,8 @@ void HeadlessPrintManager::OnDidPrintPage( |
| void HeadlessPrintManager::Reset() { |
| printing_rfh_ = nullptr; |
| callback_.Reset(); |
| + print_params_.reset(); |
| + page_ranges_text_.clear(); |
| data_.clear(); |
| expecting_first_page_ = true; |
| number_pages_ = 0; |