李恒道 发表于 2024-4-13 20:49:48

尝试抹平Tampermonkey的VSCode开发体验(二)

在能加载插件并且自动唤起浏览器后

我们的下一个目标就是可以实现插件与本地进行通信并且传输数据

并且在加载后会提示一个插件已被篡改

https://www.tampermonkey.net/index.php?version=5.1.0&updated=true#installed

我们可以在本地起一个express的服务器,并且篡改掉显示的主页来表明我们注入成功

```js
const express = require("express");
const path = require("path");
const http = require("http");
const { Server } = require("socket.io");

function initLocalServer() {
return new Promise((resolve) => {
    const app = express();
    app.use(express.static(path.join(__dirname, "/public")));

    let server = http.createServer(app);
    const io = new Server(server);
    io.on("connection", (socket) => {
      console.log("a user connected");
      socket.on("disconnect", () => {
      console.log("user disconnected");
      });
    });
    server.listen(0, () => {
      resolve(server.address().port);
    });
});
}

exports.initLocalServer = initLocalServer;
```

这里我们写了一个express服务器,并且监听了socket用于双向传输数据,同时为了解决篡改错误页面的显示,我们可以在public目录写一个自己的页面,然后通过调试找到了在插件的
```js
          let e,
            t = "version=" + ti.newV + "&ext=" + qe.short_id + "&updated=true";
          if (
            (ti.first_run
            ? ((e = "https://www.tampermonkey.net/installed.php?" + t),
                (ti.active = !0))
            : ((t += "&old=" + ti.oldV),
                (e = "https://www.tampermonkey.net/changelog.php?" + t)),
            "off" == un.values.notification_showUpdate)
          );
```

我们可以直接替换一下
```js
          let e,
            t = "version=" + ti.newV + "&ext=" + qe.short_id + "&updated=true";
          if (
            (ti.first_run
            ? ((e = window.openPage),
                (ti.active = !0))
            : ((t += "&old=" + ti.oldV),
                (e = window.openPage)),
            "off" == un.values.notification_showUpdate)
          );
```
然后提前在该js前引入另外一个js隔离引入变量即可
但是由于express的port是动态的,所以我们需要动态修改,这里我引入了ejs模板
```js
const path = require("path");
const ejs = require("ejs");
const puppeteer = require("puppeteer");
const fs = require("fs");

const templateBase = path.join(__dirname, "./template");
const crxBase = path.join(__dirname, "./tampermonkey_crx");

async function injectCode({ port }) {
const result = await ejs.renderFile(templateBase + "/backgroundInject.js", {
    openPage: "127.0.0.1:" + port,
    socketURL:"127.0.0.1:" + port
});
fs.writeFileSync(path.join(crxBase, "/backgroundInject.js"), result);
}
async function openBroswer() {
const pathToExtension = crxBase;
const browser = await puppeteer.launch({
    headless: false,
    args: [
      `--disable-extensions-except=${pathToExtension}`,
      `--load-extension=${pathToExtension}`,
    ],
});
}

async function init(options) {
await injectCode(options);
await openBroswer();
}
```
然后编写一个ejs模板

```js
window.openPage=`http://<%= openPage %>`
var socket = io('http://<%= socketURL %>');
socket.send({"Title": "12315645566"})
```
这样本地的express建立成功并且得到了端口,传给客户端,客户端通过ejs合成一个backgroundInject.js的文件,然后写入到插件目录中,那我们需要提前在`background.html`声明一下socket文件以及backgroundInject文件
```js
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <script src="socket.io.min.js"></script>
    <script src="backgroundInject.js"></script>
    <script src="test.js"></script>
    <script src="background.js"></script>
</head>
<body>
</body>
</html>

```

再通过puppteer来唤起浏览器,那我们编制一下client和server的粘合代码

```js
const server = require("./server/index.js");
const client = require("./client/index.js");

async function init() {
   const port=await server.initLocalServer()
   client.init({port})
   console.log('port',port)
}
init()
exports.init = init;
```
![图片.png](data/attachment/forum/202404/13/204943i29spcqic9i9s2g9.png)
页: [1]
查看完整版本: 尝试抹平Tampermonkey的VSCode开发体验(二)