fix: always callback error with invalid print settings (#24508)

* fix: always callback error with invalid print settings

* fixup printing patch

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
This commit is contained in:
Shelley Vohr
2020-07-13 14:19:51 -07:00
committed by GitHub
parent 6d34d0759d
commit f59d898f5c
4 changed files with 64 additions and 14 deletions

View File

@@ -1298,6 +1298,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `success` Boolean - Indicates success of the print call.
* `failureReason` String - Error description called back if the print fails.
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minumum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -1321,13 +1323,12 @@ win.webContents.print(options, (success, errorType) => {
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
default margin, 1 for no margin, and 2 for minimum margin.
and `width` in microns.
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - the first page to print.
* `to` Number - the last page to print (inclusive).
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.

View File

@@ -63,6 +63,19 @@ const PDFPageSizes = {
}
};
// The minimum micron size Chromium accepts is that where:
// Per printing/units.h:
// * kMicronsPerInch - Length of an inch in 0.001mm unit.
// * kPointsPerInch - Length of an inch in CSS's 1pt unit.
//
// Formula: (kPointsPerInch / kMicronsPerInch) * size >= 1
//
// Practically, this means microns need to be > 352 microns.
// We therefore need to verify this or it will silently fail.
const isValidCustomPageSize = (width, height) => {
return [width, height].every(x => x > 352);
};
// Default printing setting
const defaultPrintingSetting = {
// Customizable.
@@ -317,13 +330,20 @@ WebContents.prototype.printToPDF = function (options) {
const error = new Error('height and width properties are required for pageSize');
return Promise.reject(error);
}
// Dimensions in Microns
// 1 meter = 10^6 microns
// Dimensions in Microns - 1 meter = 10^6 microns
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
const error = new Error('height and width properties must be minimum 352 microns.');
return Promise.reject(error);
}
printSettings.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
height_microns: height,
width_microns: width
};
} else if (PDFPageSizes[pageSize]) {
printSettings.mediaSize = PDFPageSizes[pageSize];
@@ -358,12 +378,19 @@ WebContents.prototype.print = function (options = {}, callback) {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize');
}
// Dimensions in Microns - 1 meter = 10^6 microns
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
throw new Error('height and width properties must be minimum 352 microns.');
}
options.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
height_microns: height,
width_microns: width
};
} else if (PDFPageSizes[pageSize]) {
options.mediaSize = PDFPageSizes[pageSize];

View File

@@ -63,7 +63,7 @@ index 33e17f0df3563726767d912fb828ab959c8ec252..780967949746cbe957cd7b3487507892
}
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635ed323b7db 100644
index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..6c6d5c885f41412e25ddfc3b884b9c39fabc4f10 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -27,10 +27,7 @@
@@ -167,7 +167,18 @@ index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635e
#endif
ReleasePrinterQuery();
@@ -461,9 +474,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
@@ -380,6 +393,10 @@ void PrintViewManagerBase::OnScriptedPrint(
}
void PrintViewManagerBase::OnShowInvalidPrinterSettingsError() {
+ if (!callback_.is_null()) {
+ std::string cb_str = "Invalid printer settings";
+ std::move(callback_).Run(printing_succeeded_, cb_str);
+ }
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&ShowWarningMessageBox,
l10n_util::GetStringUTF16(
@@ -461,9 +478,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
content::NotificationService::NoDetails());
break;
}
@@ -183,7 +194,7 @@ index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635e
NOTREACHED();
break;
}
@@ -558,8 +575,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
@@ -558,8 +579,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
DCHECK(!quit_inner_loop_);
DCHECK(query);
@@ -196,7 +207,7 @@ index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635e
// We can't print if there is no renderer.
if (!web_contents()->GetRenderViewHost() ||
@@ -574,8 +593,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
@@ -574,8 +597,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
print_job_->SetSource(PrintJob::Source::PRINT_PREVIEW, /*source_id=*/"");
#endif // defined(OS_CHROMEOS)
@@ -205,7 +216,7 @@ index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635e
printing_succeeded_ = false;
return true;
}
@@ -624,14 +641,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
@@ -624,14 +645,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
content::RenderFrameHost* rfh = printing_rfh_;
printing_rfh_ = nullptr;
@@ -230,7 +241,7 @@ index 3378f34bd8e3b1cf8156e86d0e9bea97120c101e..c7c611486b158095c10db7d8e425635e
// Don't close the worker thread.
print_job_ = nullptr;
}
@@ -667,7 +692,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
@@ -667,7 +696,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
}
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {

View File

@@ -135,6 +135,17 @@ describe('webContents module', () => {
}).to.throw('Unsupported pageSize: i-am-a-bad-pagesize');
});
it('throws when an invalid custom pageSize is passed', () => {
expect(() => {
w.webContents.print({
pageSize: {
width: 100,
height: 200
}
});
}).to.throw('height and width properties must be minimum 352 microns.');
});
it('does not crash with custom margins', () => {
expect(() => {
w.webContents.print({