fix: always callback error with invalid print settings (#24476)
This commit is contained in:
parent
5737fda154
commit
6c4017ff45
4 changed files with 65 additions and 14 deletions
|
@ -1311,6 +1311,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||||
* `success` Boolean - Indicates success of the print call.
|
* `success` Boolean - Indicates success of the print call.
|
||||||
* `failureReason` String - Error description called back if the print fails.
|
* `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
|
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.
|
the system's default printer if `deviceName` is empty and the default settings for printing.
|
||||||
|
|
||||||
|
@ -1334,13 +1336,12 @@ win.webContents.print(options, (success, errorType) => {
|
||||||
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
|
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
|
||||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||||
default margin, 1 for no margin, and 2 for minimum margin.
|
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.
|
* `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.
|
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||||
* `from` Number - the first page to print.
|
* `from` Number - the first page to print.
|
||||||
* `to` Number - the last page to print (inclusive).
|
* `to` Number - the last page to print (inclusive).
|
||||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
* `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.
|
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||||
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
|
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,19 @@ const PDFPageSizes: Record<string, MediaSize> = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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: number, height: number) => {
|
||||||
|
return [width, height].every(x => x > 352);
|
||||||
|
};
|
||||||
|
|
||||||
// Default printing setting
|
// Default printing setting
|
||||||
const defaultPrintingSetting = {
|
const defaultPrintingSetting = {
|
||||||
// Customizable.
|
// Customizable.
|
||||||
|
@ -315,13 +328,20 @@ WebContents.prototype.printToPDF = function (options) {
|
||||||
const error = new Error('height and width properties are required for pageSize');
|
const error = new Error('height and width properties are required for pageSize');
|
||||||
return Promise.reject(error);
|
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 = {
|
printSettings.mediaSize = {
|
||||||
name: 'CUSTOM',
|
name: 'CUSTOM',
|
||||||
custom_display_name: 'Custom',
|
custom_display_name: 'Custom',
|
||||||
height_microns: Math.ceil(pageSize.height),
|
height_microns: height,
|
||||||
width_microns: Math.ceil(pageSize.width)
|
width_microns: width
|
||||||
};
|
};
|
||||||
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
|
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
|
||||||
printSettings.mediaSize = PDFPageSizes[pageSize];
|
printSettings.mediaSize = PDFPageSizes[pageSize];
|
||||||
|
@ -356,12 +376,19 @@ WebContents.prototype.print = function (options = {}, callback) {
|
||||||
if (!pageSize.height || !pageSize.width) {
|
if (!pageSize.height || !pageSize.width) {
|
||||||
throw new Error('height and width properties are required for pageSize');
|
throw new Error('height and width properties are required for pageSize');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)) {
|
||||||
|
throw new Error('height and width properties must be minimum 352 microns.');
|
||||||
|
}
|
||||||
|
|
||||||
(options as any).mediaSize = {
|
(options as any).mediaSize = {
|
||||||
name: 'CUSTOM',
|
name: 'CUSTOM',
|
||||||
custom_display_name: 'Custom',
|
custom_display_name: 'Custom',
|
||||||
height_microns: Math.ceil(pageSize.height),
|
height_microns: height,
|
||||||
width_microns: Math.ceil(pageSize.width)
|
width_microns: width
|
||||||
};
|
};
|
||||||
} else if (PDFPageSizes[pageSize]) {
|
} else if (PDFPageSizes[pageSize]) {
|
||||||
(options as any).mediaSize = PDFPageSizes[pageSize];
|
(options as any).mediaSize = PDFPageSizes[pageSize];
|
||||||
|
|
|
@ -90,7 +90,7 @@ index adb208ba3589e32536527219aaf4e89e3ee3311a..301f6416898445eed814d67901254ef8
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||||
index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc473bbd0da 100644
|
index 8a743d0dd74b087059ff812019ae568a22c5fa01..551dbc7b0bfdbf4ca549278bb3dfc4e3abb5cf0f 100644
|
||||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||||
@@ -27,10 +27,7 @@
|
@@ -27,10 +27,7 @@
|
||||||
|
@ -194,7 +194,19 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ReleasePrinterQuery();
|
ReleasePrinterQuery();
|
||||||
@@ -463,9 +476,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
@@ -382,6 +395,11 @@ 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(
|
||||||
|
@@ -463,9 +481,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||||
content::NotificationService::NoDetails());
|
content::NotificationService::NoDetails());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +222,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -560,8 +577,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
@@ -560,8 +582,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||||
DCHECK(!quit_inner_loop_);
|
DCHECK(!quit_inner_loop_);
|
||||||
DCHECK(query);
|
DCHECK(query);
|
||||||
|
|
||||||
|
@ -223,7 +235,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||||
|
|
||||||
// We can't print if there is no renderer.
|
// We can't print if there is no renderer.
|
||||||
if (!web_contents()->GetRenderViewHost() ||
|
if (!web_contents()->GetRenderViewHost() ||
|
||||||
@@ -582,8 +601,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
@@ -582,8 +606,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||||
print_job_->SetSource(source, /*source_id=*/"");
|
print_job_->SetSource(source, /*source_id=*/"");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -232,7 +244,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||||
printing_succeeded_ = false;
|
printing_succeeded_ = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -632,14 +649,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
@@ -632,14 +654,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
||||||
content::RenderFrameHost* rfh = printing_rfh_;
|
content::RenderFrameHost* rfh = printing_rfh_;
|
||||||
printing_rfh_ = nullptr;
|
printing_rfh_ = nullptr;
|
||||||
|
|
||||||
|
@ -257,7 +269,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||||
// Don't close the worker thread.
|
// Don't close the worker thread.
|
||||||
print_job_ = nullptr;
|
print_job_ = nullptr;
|
||||||
}
|
}
|
||||||
@@ -675,7 +700,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
@@ -675,7 +705,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
||||||
|
|
|
@ -141,6 +141,17 @@ describe('webContents module', () => {
|
||||||
}).to.throw('Unsupported pageSize: i-am-a-bad-pagesize');
|
}).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', () => {
|
it('does not crash with custom margins', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
w.webContents.print({
|
w.webContents.print({
|
||||||
|
|
Loading…
Reference in a new issue