nemeeting-electron-sdk
Version:
NetEase Meeting Electron SDK
270 lines • 11 kB
JavaScript
;
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a = require('electron'), ipcRenderer = _a.ipcRenderer, webFrame = _a.webFrame;
var NERoom = require('neroom-node-sdk');
var log = require('electron-log/renderer');
var os = require('os');
var startMarvel = require('marvel-node').startMarvel;
var isLocal = require('./constant').isLocal;
log.transports.console.format = '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] {text}';
// ─── IPC Channel 白名单(P0-11 修复)──────────────────────────────────────────
// 说明:contextIsolation: false 时 preload 与渲染进程共享 window,
// 通过替换 window.ipcRenderer 为白名单封装版本来防止渲染进程访问任意 channel。
// send(单向)+ sendSync:渲染进程 → 主进程
// 以下值均来源于 meeting-kit-core 中所有 ipcRenderer?.send / ipcRenderer?.sendSync 的实际调用
var ALLOWED_SEND_CHANNELS = [
// ─── 窗口控制 ───
'MinimizeWindow', // 旧驼峰写法(兼容)
'MaximizeWindow', // 旧驼峰写法(兼容)
'minimize-window', // IPCEvent.minimizeWindow
'maximize-window', // IPCEvent.maximizeWindow
'focusWindow', // IPCEvent.focusWindow
'MAIN_WINDOW_QUIT_FULLSCREEN',
'enter-full-screen', // IPCEvent.enterFullscreen
'leave-full-screen', // IPCEvent.quiteFullscreen
'enterFullscreen', // 旧写法兼容
'quiteFullscreen', // 旧写法兼容
// ─── Popover ───
'showPopover',
'hidePopover',
'updatePopover',
'popoverItemClick',
// ─── 设置 ───
'changeSetting', // IPCEvent.changeSetting
'changeSettingDevice', // IPCEvent.changeSettingDevice
// ─── 屏幕共享 / 标注 ───
'nemeeting-sharing-screen', // IPCEvent.sharingScreen
'annotationWindow', // IPCEvent.annotationWindow
'ignoreMouseEvents', // IPCEvent.IgnoreMouseEvents
'setIgnoreMouseEvents', // 旧写法兼容
'MAIN_WINDOW_IS_FULLSCREEN',
// ─── 通知浮窗 ───
'notify-show', // IPCEvent.notifyShow
'notify-hide', // IPCEvent.notifyHide
'notifyShow', // 旧写法兼容
'notifyHide', // 旧写法兼容
'member-notify-close', // IPCEvent.memberNotifyClose
'member-notify-mousemove', // IPCEvent.memberNotifyMourseMove
'member-notify-not-notify', // IPCEvent.memberNotifyNotNotify
'member-notify-view-member-msg', // IPCEvent.memberNotifyViewMemberMsg
// ─── 会议状态 ───
'meetingStatus', // IPCEvent.meetingStatus
'change-meeting-status', // IPCEvent.changeMeetingStatus
'changeMeetingStatus', // 旧写法兼容
'in-waiting-room', // IPCEvent.inWaitingRoom
'no-permission', // IPCEvent.noPermission
// ─── 文件操作 ───
'nemeeting-open-file',
'nemeeting-choose-file', // IPCEvent.choseFile
'nemeeting-file-save-as',
'nemeeting-download-path', // IPCEvent.downloadPath(sendSync 也用)
// ─── 子窗口 ───
'childWindow:closed', // IPCEvent.childWindowClosed
'openChatroomOrMemberList', // IPCEvent.openChatroomOrMemberList
'open-browser-window', // IPCEvent.openBrowserWindow
'DUAL_MONITORS_WIN_SWAP',
'DUAL_MONITORS_WIN_CLOSE', // useDualMonitors IPC_EVENT
'DUAL_MONITORS_WIN_SHOW', // useDualMonitors IPC_EVENT
'DUAL_MONITORS_WIN_HIDE', // useDualMonitors IPC_EVENT
// ─── 存储 ───
'flushStorageData', // IPCEvent.flushStorageData
'register-trusted-meeting-origin',
// ─── 工具 ───
'openDevTools', // IPCEvent.openDevTools
'startMarvel',
'main-close-before',
'mainWindow-dom-ready',
'nemeeting-beauty', // IPCEvent.beauty
'previewController', // IPCEvent.previewController
'reportEvent', // IPCEvent.reportEvent
'relaunch', // IPCEvent.relaunch
'delete-audio-dump', // IPCEvent.deleteAudioDump
'download-file-by-url', // IPCEvent.downloadFileByURL
'get-system-manufacturer', // IPCEvent.getSystemManufacturer
// ─── NEMeetingKit IPC 代理 ───
'NEMeetingKitElectron',
'LISTENER_CHANNEL',
];
// sendSync:渲染进程 → 主进程(同步,返回值)
// 与 ALLOWED_SEND_CHANNELS 共用校验,额外列出方便审阅
var ALLOWED_SEND_SYNC_CHANNELS = [
'nemeeting-download-path', // IPCEvent.downloadPath => sendSync(IPCEvent.downloadPath, 'get')
];
// invoke:渲染进程 → 主进程(异步,有返回值)
var ALLOWED_INVOKE_CHANNELS = [
'check-disk-space',
'local-record-meetingid-path',
'getCoverImage', // IPCEvent.getCoverImage
'getExcludeWindowList',
'get-system-info',
'nemeeting-open-file',
'neMeetingOnViewClick',
'getLogPath', // IPCEvent.getLogPath
'getAppPath',
'getAppLogsPath', // IPCEvent.getAppLogsPath
'getDeviceAccessStatus', // IPCEvent.getDeviceAccessStatus
'getThemeColor', // IPCEvent.getThemeColor
'setThemeColor',
'getVirtualBackground', // IPCEvent.getVirtualBackground
'getMonitoringInfo', // IPCEvent.getMonitoringInfo
'getImageBase64', // IPCEvent.getImageBase64 = 'nemeeting-get-image-base64'
'nemeeting-get-image-base64', // 实际字符串值
'getLocalUpdateInfo', // IPCEvent.getLocalUpdateInfo
'get-local-update-info', // IPCEvent.getLocalUpdateInfo 实际字符串
'MAIN_WINDOW_IS_FULLSCREEN',
'isMainFullScreen', // IPCEvent.isMainFullscreen 实际字符串
'deleteDirectory',
'saveAvatarToPath',
'getDeviceModel',
'get-theme-color', // IPCEvent.getThemeColor 实际字符串
'whiteboardTransparentMirror', // IPCEvent.whiteboardTransparentMirror
'DUAL_MONITORS_GET_DISPLAY_COUNT', // useDualMonitors IPC_EVENT
];
// on/off:主进程 → 渲染进程(事件监听)
/**
* 判断 send/invoke channel 是否允许。
* 支持动态格式:
* - "NEMeetingKit::<方法名>" kit 层直接 IPC 调用
* - "NEMeetingRoomsKit::<方法名>"
*/
function isAllowedSendChannel(channel) {
if (ALLOWED_SEND_CHANNELS.includes(channel))
return true;
if (ALLOWED_INVOKE_CHANNELS.includes(channel))
return true;
if (ALLOWED_SEND_SYNC_CHANNELS.includes(channel))
return true;
// NEMeetingKit / NEMeetingRoomsKit IPC 代理 channel(格式 "NEMeetingKit::<方法名>")
if (/^NEMeetingKit::/.test(channel))
return true;
if (/^NEMeetingRoomsKit::/.test(channel))
return true;
// 补齐:允许 kit 层发送注册监听器的事件
if (/^NEMeetingKitListener::/.test(channel))
return true;
if (/^NEMeetingRoomsKitListener::/.test(channel))
return true;
return false;
}
/**
* 判断 listen channel 是否允许。
* 支持动态格式:
* - "<module>-click-reply-<timestamp>" NEMeetingKitElectron 回调
* - "NEMeetingKitListener::<MODULE>" kit 层监听回调
*/
// 用白名单封装版本替换原始 ipcRenderer(P0-11 核心修复)
window.ipcRenderer = {
send: function (channel) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
if (isAllowedSendChannel(channel)) {
ipcRenderer.send.apply(ipcRenderer, __spreadArray([channel], __read(args), false));
}
else {
console.warn('[preload] ipcRenderer.send: 拒绝未授权的 channel:', channel);
}
},
sendSync: function (channel) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
if (isAllowedSendChannel(channel)) {
return ipcRenderer.sendSync.apply(ipcRenderer, __spreadArray([channel], __read(args), false));
}
console.warn('[preload] ipcRenderer.sendSync: 拒绝未授权的 channel:', channel);
return undefined;
},
invoke: function (channel) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
if (isAllowedSendChannel(channel)) {
return ipcRenderer.invoke.apply(ipcRenderer, __spreadArray([channel], __read(args), false));
}
console.warn('[preload] ipcRenderer.invoke: 拒绝未授权的 channel:', channel);
return Promise.resolve(undefined);
},
on: function (channel, listener) {
ipcRenderer.on(channel, listener);
},
once: function (channel, listener) {
ipcRenderer.once(channel, listener);
},
off: function (channel, listener) {
ipcRenderer.off(channel, listener);
},
removeListener: function (channel, listener) {
ipcRenderer.removeListener(channel, listener);
},
removeAllListeners: function (channel) {
// electron 官方类型建议仅对特定 channel 清理以防全局破坏,但接口仍保持兼容
if (channel) {
ipcRenderer.removeAllListeners(channel);
}
else {
ipcRenderer.removeAllListeners();
}
},
};
// ─── 其他全局对象暴露 ─────────────────────────────────────────────────────────
window.addEventListener('DOMContentLoaded', function () {
// TODO
});
if (process.platform === 'darwin') {
window.startMarvel = startMarvel;
}
try {
window.isElectronNative = true;
window.NERoom = NERoom;
}
catch (e) {
console.warn('neroom-node-sdk not found');
}
window.isLocal = isLocal;
window.electronLog = log.info;
console.info = log.info;
console.warn = log.warn;
window.isWins32 = process.platform === 'win32';
window.platform = process.platform;
window.systemPlatform = process.platform;
window.webFrame = webFrame;
window.isArm64 = os.arch() === 'arm64';
window.electronPopover = {
show: function (items) {
ipcRenderer.send('showPopover', items);
},
hide: function () {
ipcRenderer.send('hidePopover');
},
update: function (items) {
ipcRenderer.send('updatePopover', items);
},
};