diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 45316522fc62..35a693d92829 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -1282,6 +1282,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md) * `vertical` Number (optional) - The vertical dpi. * `header` String (optional) - String to be printed as page header. * `footer` String (optional) - String to be printed as page footer. + * `pageSize` String | Size (optional) - Specify page size of the printed document. Can be `A3`, + `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`. * `callback` Function (optional) * `success` Boolean - Indicates success of the print call. * `failureReason` String - Called back if the print fails; can be `cancelled` or `failed`. diff --git a/docs/api/webview-tag.md b/docs/api/webview-tag.md index f70a264618ee..f60a8276d278 100644 --- a/docs/api/webview-tag.md +++ b/docs/api/webview-tag.md @@ -569,6 +569,8 @@ Stops any `findInPage` request for the `webview` with the provided `action`. * `vertical` Number (optional) - The vertical dpi. * `header` String (optional) - String to be printed as page header. * `footer` String (optional) - String to be printed as page footer. + * `pageSize` String | Size (optional) - Specify page size of the printed document. Can be `A3`, + `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`. Returns `Promise` diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index b26bd0d2ec60..a0c5b9e4a17b 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -340,9 +340,38 @@ WebContents.prototype.printToPDF = function (options) { } } -WebContents.prototype.print = function (...args) { +WebContents.prototype.print = function (options = {}, callback) { + // TODO(codebytere): deduplicate argument sanitization by moving rest of + // print param logic into new file shared between printToPDF and print + if (typeof options === 'object') { + // Optionally set size for PDF. + if (options.pageSize !== undefined) { + const pageSize = options.pageSize + if (typeof pageSize === 'object') { + if (!pageSize.height || !pageSize.width) { + throw new Error('height and width properties are required for pageSize') + } + // Dimensions in Microns - 1 meter = 10^6 microns + options.mediaSize = { + name: 'CUSTOM', + custom_display_name: 'Custom', + height_microns: Math.ceil(pageSize.height), + width_microns: Math.ceil(pageSize.width) + } + } else if (PDFPageSizes[pageSize]) { + options.mediaSize = PDFPageSizes[pageSize] + } else { + throw new Error(`Unsupported pageSize: ${pageSize}`) + } + } + } + if (features.isPrintingEnabled()) { - this._print(...args) + if (callback) { + this._print(options, callback) + } else { + this._print(options) + } } else { console.error('Error: Printing feature is disabled.') } diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index afc39b682acc..af19cdfd588c 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1897,6 +1897,12 @@ void WebContents::Print(gin_helper::Arguments* args) { options.Get("duplexMode", &duplex_mode); settings.SetIntKey(printing::kSettingDuplexMode, duplex_mode); + // We've already done necessary parameter sanitization at the + // JS level, so we can simply pass this through. + base::Value media_size(base::Value::Type::DICTIONARY); + if (options.Get("mediaSize", &media_size)) + settings.SetKey(printing::kSettingMediaSize, std::move(media_size)); + // Set custom dots per inch (dpi) gin_helper::Dictionary dpi_settings; int dpi = 72; diff --git a/spec-main/api-web-contents-spec.ts b/spec-main/api-web-contents-spec.ts index 49ddbe45dad9..49ff773f00c3 100644 --- a/spec-main/api-web-contents-spec.ts +++ b/spec-main/api-web-contents-spec.ts @@ -128,6 +128,13 @@ describe('webContents module', () => { }).to.throw('webContents.print(): Invalid deviceName provided.') }) + it('throws when an invalid pageSize is passed', () => { + expect(() => { + // @ts-ignore this line is intentionally incorrect + w.webContents.print({ pageSize: 'i-am-a-bad-pagesize' }, () => {}) + }).to.throw('Unsupported pageSize: i-am-a-bad-pagesize') + }) + it('does not crash', () => { expect(() => { w.webContents.print({ silent: true })