Skip to content

Commit

Permalink
fix: NativeImage serialization of <webview>.capturePage() result (#20825
Browse files Browse the repository at this point in the history
) (#21105)
  • Loading branch information
miniak authored and codebytere committed Nov 14, 2019
1 parent 3d10d4c commit 988c573
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 7 deletions.
2 changes: 1 addition & 1 deletion filenames.gni
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ filenames = {
"lib/common/api/shell.js",
"lib/common/atom-binding-setup.ts",
"lib/common/buffer-utils.js",
"lib/common/clipboard-utils.js",
"lib/common/crash-reporter.js",
"lib/common/error-utils.js",
"lib/common/init.ts",
"lib/common/parse-features-string.js",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.js",
"lib/common/web-view-methods.js",
"lib/renderer/callbacks-registry.js",
"lib/renderer/chrome-api.ts",
Expand Down
7 changes: 7 additions & 0 deletions lib/browser/guest-view-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { webContents } = require('electron')
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
const parseFeaturesString = require('@electron/internal/common/parse-features-string')
const { serialize } = require('@electron/internal/common/type-utils')
const {
syncMethods,
asyncCallbackMethods,
Expand Down Expand Up @@ -386,6 +387,12 @@ handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CALL', function (event, guestInstance
return guest[method](...args)
})

handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CAPTURE_PAGE', async function (event, guestInstanceId, args) {
const guest = getGuestForWebContents(guestInstanceId, event.sender)

return serialize(await guest.capturePage(...args))
})

// Returns WebContents from its guest id hosted in given webContents.
const getGuestForWebContents = function (guestInstanceId, contents) {
const guest = getGuest(guestInstanceId)
Expand Down
4 changes: 2 additions & 2 deletions lib/browser/rpc-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const objectsRegistry = require('@electron/internal/browser/objects-registry')
const guestViewManager = require('@electron/internal/browser/guest-view-manager')
const bufferUtils = require('@electron/internal/common/buffer-utils')
const errorUtils = require('@electron/internal/common/error-utils')
const clipboardUtils = require('@electron/internal/common/clipboard-utils')
const typeUtils = require('@electron/internal/common/type-utils')

const hasProp = {}.hasOwnProperty

Expand Down Expand Up @@ -493,7 +493,7 @@ ipcMainUtils.handle('ELECTRON_BROWSER_CLIPBOARD', function (event, method, ...ar
throw new Error(`Invalid method: ${method}`)
}

return clipboardUtils.serialize(electron.clipboard[method](...clipboardUtils.deserialize(args)))
return typeUtils.serialize(electron.clipboard[method](...typeUtils.deserialize(args)))
})

const readFile = util.promisify(fs.readFile)
Expand Down
6 changes: 3 additions & 3 deletions lib/common/api/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ const clipboard = process.electronBinding('clipboard')

if (process.type === 'renderer') {
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils')
const clipboardUtils = require('@electron/internal/common/clipboard-utils')
const typeUtils = require('@electron/internal/common/type-utils')

const makeRemoteMethod = function (method) {
return (...args) => {
args = clipboardUtils.serialize(args)
args = typeUtils.serialize(args)
const result = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_CLIPBOARD', method, ...args)
return clipboardUtils.deserialize(result)
return typeUtils.deserialize(result)
}
}

Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion lib/common/web-view-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ exports.asyncCallbackMethods = new Set([

exports.asyncPromiseMethods = new Set([
'loadURL',
'capturePage',
'executeJavaScript',
'printToPDF'
])
9 changes: 9 additions & 0 deletions lib/renderer/web-view/web-view-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { deprecate, remote, webFrame } from 'electron'
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils'
import * as guestViewInternal from '@electron/internal/renderer/web-view/guest-view-internal'
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants'
import { deserialize } from '@electron/internal/common/type-utils'
import {
syncMethods,
asyncCallbackMethods,
Expand Down Expand Up @@ -275,6 +276,14 @@ export const setupMethods = (WebViewElement: typeof ElectronInternal.WebViewElem
for (const method of asyncPromiseMethods) {
(WebViewElement.prototype as Record<string, any>)[method] = deprecate.promisify(createPromiseHandler(method))
}

const createCapturePageHandler = function () {
return function (this: ElectronInternal.WebViewElement, ...args: Array<any>) {
return ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_CAPTURE_PAGE', this.getWebContentsId(), args).then(image => deserialize(image))
}
}

WebViewElement.prototype.capturePage = deprecate.promisify(createCapturePageHandler())
}

export const webViewImplModule = {
Expand Down
31 changes: 31 additions & 0 deletions spec/webview-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,37 @@ describe('<webview> tag', function () {
})
})

describe('<webview>.capturePage()', () => {
it('returns a Promise with a NativeImage', async () => {
const src = 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'
await loadWebView(webview, { src })

const image = await webview.capturePage()
const imgBuffer = image.toPNG()

// Check the 25th byte in the PNG.
// Values can be 0,2,3,4, or 6. We want 6, which is RGB + Alpha
expect(imgBuffer[25]).to.equal(6)
})

// TODO(miniak): remove when promisification is complete
it('invokes callback with a NativeImage', (done) => {
webview.addEventListener('did-finish-load', () => {
webview.capturePage(function (image) {
const imgBuffer = image.toPNG()

// Check the 25th byte in the PNG.
// Values can be 0,2,3,4, or 6. We want 6, which is RGB + Alpha
expect(imgBuffer[25]).to.equal(6)
done()
})
})

webview.src = 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'
document.body.appendChild(webview)
})
})

describe('<webview>.printToPDF()', () => {
before(function () {
if (!features.isPrintingEnabled()) {
Expand Down
1 change: 1 addition & 0 deletions typings/internal-electron.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ declare namespace ElectronInternal {
// Created in web-view-impl
public getWebContents(): Electron.WebContents;
public getWebContentsId(): number;
public capturePage(rect?: Electron.Rectangle): Promise<Electron.NativeImage>;
}
}

Expand Down

0 comments on commit 988c573

Please sign in to comment.