From 5bb8da60737802d9c4e09b2c813ec93539fb92be Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 14:57:35 +0900 Subject: [PATCH 1/4] Explicitly initialize session before webContents --- lib/browser/api/app.js | 5 +++-- lib/browser/api/web-contents.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/browser/api/app.js b/lib/browser/api/app.js index f8a531626bf7..09835a792e0e 100644 --- a/lib/browser/api/app.js +++ b/lib/browser/api/app.js @@ -1,6 +1,7 @@ 'use strict' -const {deprecate, Menu, session} = require('electron') +const electron = require('electron') +const {deprecate, Menu} = electron const {EventEmitter} = require('events') const bindings = process.atomBinding('app') @@ -49,7 +50,7 @@ app.allowNTLMCredentialsForAllDomains = function (allow) { if (!this.isReady()) { this.commandLine.appendSwitch('auth-server-whitelist', domains) } else { - session.defaultSession.allowNTLMCredentialsForDomains(domains) + electron.session.defaultSession.allowNTLMCredentialsForDomains(domains) } } diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index cb8cf41e3aa6..059f204e1ee7 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -1,7 +1,11 @@ 'use strict' const {EventEmitter} = require('events') -const {ipcMain, Menu, NavigationController} = require('electron') +const {ipcMain, session, Menu, NavigationController} = require('electron') + +// session is not used here, the purpose is to make sure session is initalized +// before the webContents module. +session const binding = process.atomBinding('web_contents') const debuggerBinding = process.atomBinding('debugger') From eb882855bcd5dc925695ceb54669da51696f9bcd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:08:51 +0900 Subject: [PATCH 2/4] Cleanup the CoffeeScript converted code --- lib/browser/api/web-contents.js | 46 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 059f204e1ee7..d7bcdb455b33 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -11,12 +11,11 @@ const binding = process.atomBinding('web_contents') const debuggerBinding = process.atomBinding('debugger') let nextId = 0 - -let getNextId = function () { +const getNextId = function () { return ++nextId } -let PDFPageSize = { +const PDFPageSize = { A5: { custom_display_name: 'A5', height_microns: 210000, @@ -64,9 +63,9 @@ const webFrameMethods = [ 'setZoomLevelLimits' ] -let wrapWebContents = function (webContents) { +// Add JavaScript wrappers for WebContents class. +const wrapWebContents = function (webContents) { // webContents is an EventEmitter. - var controller, method, name, ref1 Object.setPrototypeOf(webContents, EventEmitter.prototype) // Every remote callback from renderer process would add a listenter to the @@ -85,21 +84,18 @@ let wrapWebContents = function (webContents) { webContents.sendToAll = sendWrapper.bind(null, true) // The navigation controller. - controller = new NavigationController(webContents) - ref1 = NavigationController.prototype - for (name in ref1) { - method = ref1[name] + const controller = new NavigationController(webContents) + for (const name in NavigationController.prototype) { + const method = NavigationController.prototype[name] if (method instanceof Function) { - (function (name, method) { - webContents[name] = function () { - return method.apply(controller, arguments) - } - })(name, method) + webContents[name] = function () { + return method.apply(controller, arguments) + } } } // Mapping webFrame methods. - for (let method of webFrameMethods) { + for (const method of webFrameMethods) { webContents[method] = function (...args) { this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) } @@ -115,7 +111,7 @@ let wrapWebContents = function (webContents) { // Make sure webContents.executeJavaScript would run the code only when the // webContents has been loaded. webContents.executeJavaScript = function (code, hasUserGesture, callback) { - let requestId = getNextId() + const requestId = getNextId() if (typeof hasUserGesture === 'function') { callback = hasUserGesture hasUserGesture = false @@ -131,18 +127,16 @@ let wrapWebContents = function (webContents) { // Dispatch IPC messages to the ipc module. webContents.on('ipc-message', function (event, [channel, ...args]) { - ipcMain.emit.apply(ipcMain, [channel, event].concat(args)) + ipcMain.emit(channel, event, ...args) }) webContents.on('ipc-message-sync', function (event, [channel, ...args]) { Object.defineProperty(event, 'returnValue', { set: function (value) { return event.sendReply(JSON.stringify(value)) }, - get: function () { - return undefined - } + get: function () {} }) - return ipcMain.emit.apply(ipcMain, [channel, event].concat(args)) + ipcMain.emit(channel, event, ...args) }) // Handle context menu action request from pepper plugin. @@ -164,8 +158,7 @@ let wrapWebContents = function (webContents) { }) webContents.printToPDF = function (options, callback) { - var printingSetting - printingSetting = { + const printingSetting = { pageRage: [], mediaSize: {}, landscape: false, @@ -229,13 +222,14 @@ let wrapWebContents = function (webContents) { } } -// Wrapper for native class. -let wrapDebugger = function (webContentsDebugger) { +binding._setWrapWebContents(wrapWebContents) + +// Add JavaScript wrappers for Debugger class. +const wrapDebugger = function (webContentsDebugger) { // debugger is an EventEmitter. Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype) } -binding._setWrapWebContents(wrapWebContents) debuggerBinding._setWrapDebugger(wrapDebugger) module.exports = { From 0864d3b1ee7370ece474532ffbeda646c2e5ed5e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:24:53 +0900 Subject: [PATCH 3/4] Cleanup the printToPDF code --- lib/browser/api/web-contents.js | 81 +++++++++++++++++---------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index d7bcdb455b33..ed7bfe0b8bdf 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -15,7 +15,8 @@ const getNextId = function () { return ++nextId } -const PDFPageSize = { +// Stock page sizes +const PDFPageSizes = { A5: { custom_display_name: 'A5', height_microns: 210000, @@ -55,6 +56,31 @@ const PDFPageSize = { } } +// Default printing setting +const defaultPrintingSetting = { + pageRage: [], + mediaSize: {}, + landscape: false, + color: 2, + headerFooterEnabled: false, + marginsType: 0, + isFirstRequest: false, + requestID: getNextId(), + previewModifiable: true, + printToPDF: true, + printWithCloudPrint: false, + printWithPrivet: false, + printWithExtension: false, + deviceName: 'Save as PDF', + generateDraftData: true, + fitToPageEnabled: false, + duplex: 0, + copies: 1, + collate: true, + shouldPrintBackgrounds: false, + shouldPrintSelectionOnly: false +} + // Following methods are mapped to webFrame. const webFrameMethods = [ 'insertText', @@ -158,29 +184,7 @@ const wrapWebContents = function (webContents) { }) webContents.printToPDF = function (options, callback) { - const printingSetting = { - pageRage: [], - mediaSize: {}, - landscape: false, - color: 2, - headerFooterEnabled: false, - marginsType: 0, - isFirstRequest: false, - requestID: getNextId(), - previewModifiable: true, - printToPDF: true, - printWithCloudPrint: false, - printWithPrivet: false, - printWithExtension: false, - deviceName: 'Save as PDF', - generateDraftData: true, - fitToPageEnabled: false, - duplex: 0, - copies: 1, - collate: true, - shouldPrintBackgrounds: false, - shouldPrintSelectionOnly: false - } + const printingSetting = Object.assign({}, defaultPrintingSetting) if (options.landscape) { printingSetting.landscape = options.landscape } @@ -195,30 +199,29 @@ const wrapWebContents = function (webContents) { } if (options.pageSize) { - let height = 0 - let width = 0 - if (typeof options.pageSize === 'object') { + const pageSize = options.pageSize + if (typeof pageSize === 'object') { + if (!pageSize.height || !pageSize.width) { + return callback(new Error('Must define height and width for pageSize')) + } // Dimensions in Microns // 1 meter = 10^6 microns - height = options.pageSize.height ? options.pageSize.height : 0 - width = options.pageSize.width ? options.pageSize.width : 0 - } - - if (height > 0 && width > 0) { printingSetting.mediaSize = { - height_microns: height, name: 'CUSTOM', - width_microns: width, - custom_display_name: 'Custom' + custom_display_name: 'Custom', + height_microns: pageSize.height, + width_microns: pageSize.width } - } else if (PDFPageSize[options.pageSize]) { - printingSetting.mediaSize = PDFPageSize[options.pageSize] + } else if (PDFPageSizes[pageSize]) { + printingSetting.mediaSize = PDFPageSizes[pageSize] } else { - printingSetting.mediaSize = PDFPageSize['A4'] + return callback(new Error(`Does not support pageSize with ${pageSize}`)) } + } else { + printingSetting.mediaSize = PDFPageSizes['A4'] } - return this._printToPDF(printingSetting, callback) + this._printToPDF(printingSetting, callback) } } From 01b10b3b39d3e34f6aedbeaa431d18afdd58d060 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:27:17 +0900 Subject: [PATCH 4/4] Slightly improve docs of webContents.printToPDF --- docs/api/web-contents.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 89d7e1245d77..ca9cf43c468f 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -655,7 +655,8 @@ size. * `marginsType` Integer - Specifies the type of margins to use. Uses 0 for default margin, 1 for no margin, and 2 for minimum margin. * `pageSize` String - Specify page size of the generated PDF. Can be `A3`, - `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` & `width` in Microns. + `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` + and `width` in microns. * `printBackground` Boolean - Whether to print CSS backgrounds. * `printSelectionOnly` Boolean - Whether to print selection only. * `landscape` Boolean - `true` for landscape, `false` for portrait. @@ -678,6 +679,8 @@ By default, an empty `options` will be regarded as: } ``` +An example of `webContents.printToPDF`: + ```javascript const {BrowserWindow} = require('electron'); const fs = require('fs');