UNPKG

nemeeting-electron-sdk

Version:

NetEase Meeting Electron SDK

270 lines 11 kB
"use strict"; 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); }, };