electron 注入hook代码
主要使用了BrowserWindow的webContents对象,它提供了在主进程中对渲染进程进行操作的接口
mainWindow.webContents.on("did-finish-load", function() {
//...
//这里放注入代码逻辑
//...
});
上面的事件是关键代码,提供了在渲染进程主页页面文档加载完毕之后执行代码逻辑的可能
mainWindow.webContents.executeJavaScript(js);
想要在渲染进程执行js,必须用这里的接口,直接执行js只会在主进程执行
下面是一个实际的例子,作用是在netflix网页中注入hook代码,以获取视频信息
main.js
const { app, components,BrowserWindow } = require('electron');
const path = require('path')
const fs = require("fs")
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
nodeIntegration: true
},
});
// Load Netflix URL
mainWindow.loadURL('https://www.netflix.com/watch/80210938?trackId=254015180&tctx=0%2C0%2C22898ff0-1c41-43eb-b390-bfe8c6bebbad-72361130%2CNES_ABA75BA61D6959C46E272C0D175353-951BB306AEF2A8-5D9479BF5C_p_1690129307742%2CNES_ABA75BA61D6959C46E272C0D175353_p_1690129307742%2C%2C%2C%2C%2CVideo%3A80197526%2CbillboardPlayButton');
mainWindow.webContents.openDevTools()
mainWindow.webContents.on("did-finish-load", function() {
const js = fs.readFileSync(path.join(__dirname, 'netflixHook.js')).toString();
mainWindow.webContents.executeJavaScript(js);
});
}
app.whenReady().then(async () => {
await components.whenReady();
console.log('components ready:', components.status());
createWindow();
});
netflixHook.js
const injection = () => {
const WEBVTT = 'webvtt-lssdh-ios8';
const MANIFEST_URL = "manifest";
const forceSubs = localStorage.getItem('NSD_force-all-lang') !== 'false';
// hijack JSON.parse and JSON.stringify functions
((parse, stringify) => {
JSON.parse = function (text) {
const data = parse(text);
if (data && data.result && data.result.timedtexttracks && data.result.movieId) {
window.dispatchEvent(new CustomEvent('netflix_sub_downloader_data', {detail: data.result}));
console.log('manifest:')
console.log(data)
console.log(stringify(data))
}
return data;
};
JSON.stringify = function (data) {
if (data && typeof data.url === 'string' && data.url.indexOf(MANIFEST_URL) > -1) {
for (let v of Object.values(data)) {
try {
if (v.profiles)
v.profiles.unshift(WEBVTT);
if (v.showAllSubDubTracks != null && forceSubs)
v.showAllSubDubTracks = true;
}
catch (e) {
if (e instanceof TypeError)
continue;
else
throw e;
}
}
console.log('manifest_req:')
console.log(data)
}
if(data && typeof data.movieId === 'number') {
try {
let videoId = data.params.sessionParams.uiplaycontext.video_id;
if(typeof videoId === 'number' && videoId !== data.movieId)
window.dispatchEvent(new CustomEvent('netflix_sub_downloader_data', {detail: {id_override: [videoId, data.movieId]}}));
}
catch(ignore) {}
}
return stringify(data);
};
})(JSON.parse, JSON.stringify);
}
injection();