electron 注入hook代码

发布时间 2023-08-28 02:20:42作者: 乘舟凉

主要使用了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();