From 025034127a90c1f8ba30bc3242366780e82cbf94 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 20:52:07 +0900 Subject: [PATCH] Set JavaScript APIs on prototype of WebContents --- lib/browser/api/web-contents.js | 199 ++++++++++++++++---------------- 1 file changed, 100 insertions(+), 99 deletions(-) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 796f2b20f6d9..c255cd0ff951 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -78,11 +78,23 @@ const defaultPrintingSetting = { shouldPrintSelectionOnly: false } +// JavaScript implementations of WebContents. const binding = process.atomBinding('web_contents') const {WebContents} = binding Object.setPrototypeOf(WebContents.prototype, EventEmitter.prototype) +// WebContents::send(channel, args..) +// WebContents::sendToAll(channel, args..) +WebContents.prototype.send = function (channel, ...args) { + if (channel == null) throw new Error('Missing required channel argument') + return this._send(false, channel, args) +} +WebContents.prototype.sendToAll = function (channel, ...args) { + if (channel == null) throw new Error('Missing required channel argument') + return this._send(true, channel, args) +} + // Following methods are mapped to webFrame. const webFrameMethods = [ 'insertText', @@ -90,29 +102,104 @@ const webFrameMethods = [ 'setZoomLevel', 'setZoomLevelLimits' ] - const webFrameMethodsWithResult = [ 'getZoomFactor', 'getZoomLevel' ] +const asyncWebFrameMethods = function (requestId, method, callback, ...args) { + this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args) + ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { + if (callback) callback(result) + }) +} + +const syncWebFrameMethods = function (requestId, method, callback, ...args) { + this.send('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', requestId, method, args) + ipcMain.once(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { + if (callback) callback(result) + }) +} + +for (const method of webFrameMethods) { + WebContents.prototype[method] = function (...args) { + this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) + } +} + +for (const method of webFrameMethodsWithResult) { + WebContents.prototype[method] = function (...args) { + const callback = args[args.length - 1] + const actualArgs = args.slice(0, args.length - 2) + syncWebFrameMethods.call(this, getNextId(), method, callback, ...actualArgs) + } +} + +// Make sure WebContents::executeJavaScript would run the code only when the +// WebContents has been loaded. +WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) { + const requestId = getNextId() + if (typeof hasUserGesture === 'function') { + callback = hasUserGesture + hasUserGesture = false + } + if (this.getURL() && !this.isLoadingMainFrame()) { + asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) + } else { + this.once('did-finish-load', () => { + asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) + }) + } +} + +// Translate the options of printToPDF. +WebContents.prototype.printToPDF = function (options, callback) { + const printingSetting = Object.assign({}, defaultPrintingSetting) + if (options.landscape) { + printingSetting.landscape = options.landscape + } + if (options.marginsType) { + printingSetting.marginsType = options.marginsType + } + if (options.printSelectionOnly) { + printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly + } + if (options.printBackground) { + printingSetting.shouldPrintBackgrounds = options.printBackground + } + + if (options.pageSize) { + 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 + printingSetting.mediaSize = { + name: 'CUSTOM', + custom_display_name: 'Custom', + height_microns: pageSize.height, + width_microns: pageSize.width + } + } else if (PDFPageSizes[pageSize]) { + printingSetting.mediaSize = PDFPageSizes[pageSize] + } else { + return callback(new Error(`Does not support pageSize with ${pageSize}`)) + } + } else { + printingSetting.mediaSize = PDFPageSizes['A4'] + } + + this._printToPDF(printingSetting, callback) +} + // Add JavaScript wrappers for WebContents class. WebContents.prototype._init = function () { // Every remote callback from renderer process would add a listenter to the // render-view-deleted event, so ignore the listenters warning. this.setMaxListeners(0) - // WebContents::send(channel, args..) - // WebContents::sendToAll(channel, args..) - const sendWrapper = (allFrames, channel, ...args) => { - if (channel == null) { - throw new Error('Missing required channel argument') - } - return this._send(allFrames, channel, args) - } - this.send = sendWrapper.bind(null, false) - this.sendToAll = sendWrapper.bind(null, true) - // The navigation controller. const controller = new NavigationController(this) for (const name in NavigationController.prototype) { @@ -124,52 +211,6 @@ WebContents.prototype._init = function () { } } - const asyncWebFrameMethods = function (requestId, method, callback, ...args) { - this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args) - ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { - if (callback) callback(result) - }) - } - - const syncWebFrameMethods = function (requestId, method, callback, ...args) { - this.send('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', requestId, method, args) - ipcMain.once(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { - if (callback) callback(result) - }) - } - - // Mapping webFrame methods. - for (const method of webFrameMethods) { - this[method] = function (...args) { - this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) - } - } - - for (const method of webFrameMethodsWithResult) { - this[method] = function (...args) { - const callback = args[args.length - 1] - const actualArgs = args.slice(0, args.length - 2) - syncWebFrameMethods.call(this, getNextId(), method, callback, ...actualArgs) - } - } - - // Make sure webContents.executeJavaScript would run the code only when the - // webContents has been loaded. - this.executeJavaScript = function (code, hasUserGesture, callback) { - const requestId = getNextId() - if (typeof hasUserGesture === 'function') { - callback = hasUserGesture - hasUserGesture = false - } - if (this.getURL() && !this.isLoadingMainFrame()) { - asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) - } else { - this.once('did-finish-load', () => { - asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) - }) - } - } - // Dispatch IPC messages to the ipc module. this.on('ipc-message', function (event, [channel, ...args]) { ipcMain.emit(channel, event, ...args) @@ -202,50 +243,10 @@ WebContents.prototype._init = function () { }) }) - this.printToPDF = function (options, callback) { - const printingSetting = Object.assign({}, defaultPrintingSetting) - if (options.landscape) { - printingSetting.landscape = options.landscape - } - if (options.marginsType) { - printingSetting.marginsType = options.marginsType - } - if (options.printSelectionOnly) { - printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly - } - if (options.printBackground) { - printingSetting.shouldPrintBackgrounds = options.printBackground - } - - if (options.pageSize) { - 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 - printingSetting.mediaSize = { - name: 'CUSTOM', - custom_display_name: 'Custom', - height_microns: pageSize.height, - width_microns: pageSize.width - } - } else if (PDFPageSizes[pageSize]) { - printingSetting.mediaSize = PDFPageSizes[pageSize] - } else { - return callback(new Error(`Does not support pageSize with ${pageSize}`)) - } - } else { - printingSetting.mediaSize = PDFPageSizes['A4'] - } - - this._printToPDF(printingSetting, callback) - } - app.emit('web-contents-created', {}, this) } +// JavaScript wrapper of Debugger. const {Debugger} = process.atomBinding('debugger') Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype)