fix: ensure nativeImage serialization main->renderer (#23759)
This commit is contained in:
parent
e5da2caa34
commit
e8ea007104
3 changed files with 41 additions and 8 deletions
|
@ -4,12 +4,13 @@ import * as electron from 'electron';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import objectsRegistry from './objects-registry';
|
import objectsRegistry from './objects-registry';
|
||||||
import { ipcMainInternal } from '../ipc-main-internal';
|
import { ipcMainInternal } from '../ipc-main-internal';
|
||||||
import { isPromise, isSerializableObject, deserialize } from '@electron/internal/common/type-utils';
|
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
|
||||||
import { Size } from 'electron/main';
|
import { Size } from 'electron/main';
|
||||||
|
|
||||||
const v8Util = process.electronBinding('v8_util');
|
const v8Util = process.electronBinding('v8_util');
|
||||||
const eventBinding = process.electronBinding('event');
|
const eventBinding = process.electronBinding('event');
|
||||||
const features = process.electronBinding('features');
|
const features = process.electronBinding('features');
|
||||||
|
const { NativeImage } = process.electronBinding('native_image');
|
||||||
|
|
||||||
if (!features.isRemoteModuleEnabled()) {
|
if (!features.isRemoteModuleEnabled()) {
|
||||||
throw new Error('remote module is disabled');
|
throw new Error('remote module is disabled');
|
||||||
|
@ -114,6 +115,9 @@ type MetaType = {
|
||||||
} | {
|
} | {
|
||||||
type: 'promise',
|
type: 'promise',
|
||||||
then: MetaType
|
then: MetaType
|
||||||
|
} | {
|
||||||
|
type: 'nativeimage'
|
||||||
|
value: electron.NativeImage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a real value into meta data.
|
// Convert a real value into meta data.
|
||||||
|
@ -124,6 +128,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||||
// Recognize certain types of objects.
|
// Recognize certain types of objects.
|
||||||
if (value instanceof Buffer) {
|
if (value instanceof Buffer) {
|
||||||
type = 'buffer';
|
type = 'buffer';
|
||||||
|
} else if (value instanceof NativeImage) {
|
||||||
|
type = 'nativeimage';
|
||||||
} else if (Array.isArray(value)) {
|
} else if (Array.isArray(value)) {
|
||||||
type = 'array';
|
type = 'array';
|
||||||
} else if (value instanceof Error) {
|
} else if (value instanceof Error) {
|
||||||
|
@ -147,6 +153,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||||
type,
|
type,
|
||||||
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
|
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
|
||||||
};
|
};
|
||||||
|
} else if (type === 'nativeimage') {
|
||||||
|
return { type, value: serialize(value) };
|
||||||
} else if (type === 'object' || type === 'function') {
|
} else if (type === 'object' || type === 'function') {
|
||||||
return {
|
return {
|
||||||
type,
|
type,
|
||||||
|
|
|
@ -5,7 +5,7 @@ const { hasSwitch } = process.electronBinding('command_line');
|
||||||
const { NativeImage } = process.electronBinding('native_image');
|
const { NativeImage } = process.electronBinding('native_image');
|
||||||
|
|
||||||
const { CallbacksRegistry } = require('@electron/internal/renderer/remote/callbacks-registry');
|
const { CallbacksRegistry } = require('@electron/internal/renderer/remote/callbacks-registry');
|
||||||
const { isPromise, isSerializableObject, serialize } = require('@electron/internal/common/type-utils');
|
const { isPromise, isSerializableObject, serialize, deserialize } = require('@electron/internal/common/type-utils');
|
||||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||||
|
|
||||||
const callbacksRegistry = new CallbacksRegistry();
|
const callbacksRegistry = new CallbacksRegistry();
|
||||||
|
@ -219,6 +219,7 @@ function metaToValue (meta) {
|
||||||
const types = {
|
const types = {
|
||||||
value: () => meta.value,
|
value: () => meta.value,
|
||||||
array: () => meta.members.map((member) => metaToValue(member)),
|
array: () => meta.members.map((member) => metaToValue(member)),
|
||||||
|
nativeimage: () => deserialize(meta.value),
|
||||||
buffer: () => Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength),
|
buffer: () => Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength),
|
||||||
promise: () => Promise.resolve({ then: metaToValue(meta.then) }),
|
promise: () => Promise.resolve({ then: metaToValue(meta.then) }),
|
||||||
error: () => metaToError(meta),
|
error: () => metaToError(meta),
|
||||||
|
|
|
@ -366,11 +366,11 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
|
||||||
const w = makeWindow();
|
const w = makeWindow();
|
||||||
const remotely = makeRemotely(w);
|
const remotely = makeRemotely(w);
|
||||||
|
|
||||||
it('can serialize an empty nativeImage', async () => {
|
it('can serialize an empty nativeImage from renderer to main', async () => {
|
||||||
const getEmptyImage = (img: NativeImage) => img.isEmpty();
|
const getImageEmpty = (img: NativeImage) => img.isEmpty();
|
||||||
|
|
||||||
w().webContents.once('remote-get-global', (event) => {
|
w().webContents.once('remote-get-global', (event) => {
|
||||||
event.returnValue = getEmptyImage;
|
event.returnValue = getImageEmpty;
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(remotely(() => {
|
await expect(remotely(() => {
|
||||||
|
@ -379,11 +379,23 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
|
||||||
})).to.eventually.be.true();
|
})).to.eventually.be.true();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can serialize a non-empty nativeImage', async () => {
|
it('can serialize an empty nativeImage from main to renderer', async () => {
|
||||||
const getNonEmptyImage = (img: NativeImage) => img.getSize();
|
w().webContents.once('remote-get-global', (event) => {
|
||||||
|
const emptyImage = require('electron').nativeImage.createEmpty();
|
||||||
|
event.returnValue = emptyImage;
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(remotely(() => {
|
||||||
|
const image = require('electron').remote.getGlobal('someFunction');
|
||||||
|
return image.isEmpty();
|
||||||
|
})).to.eventually.be.true();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can serialize a non-empty nativeImage from renderer to main', async () => {
|
||||||
|
const getImageSize = (img: NativeImage) => img.getSize();
|
||||||
|
|
||||||
w().webContents.once('remote-get-global', (event) => {
|
w().webContents.once('remote-get-global', (event) => {
|
||||||
event.returnValue = getNonEmptyImage;
|
event.returnValue = getImageSize;
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(remotely(() => {
|
await expect(remotely(() => {
|
||||||
|
@ -393,6 +405,18 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
|
||||||
})).to.eventually.deep.equal({ width: 2, height: 2 });
|
})).to.eventually.deep.equal({ width: 2, height: 2 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can serialize a non-empty nativeImage from main to renderer', async () => {
|
||||||
|
w().webContents.once('remote-get-global', (event) => {
|
||||||
|
const nonEmptyImage = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQYlWP8//8/AwMDEwMDAwMDAwAkBgMBBMzldwAAAABJRU5ErkJggg==');
|
||||||
|
event.returnValue = nonEmptyImage;
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(remotely(() => {
|
||||||
|
const image = require('electron').remote.getGlobal('someFunction');
|
||||||
|
return image.getSize();
|
||||||
|
})).to.eventually.deep.equal({ width: 2, height: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
it('can properly create a menu with an nativeImage icon in the renderer', async () => {
|
it('can properly create a menu with an nativeImage icon in the renderer', async () => {
|
||||||
await expect(remotely(() => {
|
await expect(remotely(() => {
|
||||||
const { remote, nativeImage } = require('electron');
|
const { remote, nativeImage } = require('electron');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue