Chrome插件获取页面请求内容

2024-01-10 22:51:16 868

先代理xhr/fetch对象

common.js

const shopee_get_product_10045487 = "/api/v4/pdp/get_pc";

const api_category_34a10fd6 = {};

api_category_34a10fd6[shopee_get_product_10045487] = "getProduct";

const rule_api_3ea67778 = {
  shopee: [shopee_get_product_10045487],
};

const site_map_e68a0688 = {
  "shopee.sg": "shopee",
  "shopee.tw": "shopee",
  "shopee.com.my": "shopee",
  "shopee.ph": "shopee",
  "shopee.co.th": "shopee",
  "shopee.vn": "shopee",
  "shopee.com.br": "shopee",
  "shopee.co.id": "shopee",
  "shopee.com.mx": "shopee",
};

page/interceptor.js

let config_2550ac5d = {
  proxy_url: [],
  setUrl: function (site) {
    this.proxy_url = rule_api_3ea67778[site];
  },
  match: function (url) {
    return this.proxy_url.filter((n) => url.indexOf(n) > -1).length > 0;
  },
  get: function (url) {},
};

config_2550ac5d.setUrl(site_map_e68a0688[window.location.hostname]);

function sendEvent(_type, _url, _data) {
  window.postMessage(
    {
      type: "proxy-response",
      text: {
        site: site_map_e68a0688[window.location.hostname],
        data: _data,
        url: _url,
      },
    },
    "*"
  );
}

let proxy_interceptor = {
  originalXHR: window.XMLHttpRequest,
  pluginXHR: function () {
    const xhr = new proxy_interceptor.originalXHR();
    for (let attr in xhr) {
      if (attr === "onreadystatechange") {
        xhr.onreadystatechange = (...args) => {
          this.onreadystatechange && this.onreadystatechange.apply(this, args);
        };
        this.onreadystatechange = null;
        continue;
      } else if (attr === " (...args) => {
          if (config_2550ac5d.match(this.responseURL)) {
            sendEvent("xhr", this.responseURL, this.responseText);
          }
          this. null;
        continue;
      } else if (attr === "open") {
        this.open = (...args) => {
          xhr.open && xhr.open.apply(xhr, args);
        };
        continue;
      } else if (attr === "setRequestHeader") {
        this.setRequestHeader = (...args) => {
          xhr.setRequestHeader && xhr.setRequestHeader.apply(xhr, args);
        };
        continue;
      } else if (attr === "send") {
        this.send = (...args) => {
          xhr.send && xhr.send.apply(xhr, args);
        };
        continue;
      }

      if (typeof xhr[attr] === "function") {
        this[attr] = xhr[attr].bind(xhr);
      } else {
        Object.defineProperty(this, attr, {
          get: () => xhr[attr],
          set: (val) => (xhr[attr] = val),
          enumerable: true,
        });
      }
    }
  },
  originalFetch: window.fetch.bind(window),
  pluginFetch: (url, t) =>
    proxy_interceptor.originalFetch(url, t).then(async (response) => {
      if (config_2550ac5d.match(url)) {
        const data = await response.clone().json();
        sendEvent("fetch", url, data);
      }
      return response;
    }),
};

window.XMLHttpRequest = proxy_interceptor.pluginXHR;
window.fetch = proxy_interceptor.pluginFetch;

content-script.js

const common_script = document.createElement("script");
common_script.setAttribute("type", "text/javascript");
common_script.setAttribute("src", chrome.runtime.getURL("common.js"));
// 注意不能异步加载, 否则interceptor.js注入到页面时, 可能加载不到common.js
common_script.async = false;
document.documentElement.appendChild(common_script);

const interceptor_script = document.createElement("script");
interceptor_script.setAttribute("type", "text/javascript");
interceptor_script.setAttribute(
  "src",
  chrome.runtime.getURL("page/interceptor.js")
);
interceptor_script.async = false;
document.documentElement.appendChild(interceptor_script);

var data_cache = {};

window.addEventListener(
  "message",
  (event) => {
    if (event.source !== window) {
      return;
    }
    if (event.data.type && event.data.type === "proxy-response") {
      
      let temp;
      if (typeof event.data.text === "string") {
        temp = JSON.parse(event.data.text);
      } else {
        temp = event.data.text;
      }
      let key = Object.keys(api_category_34a10fd6).filter((url) => temp.url.indexOf(url) > -1);
      data_cache[api_category_34a10fd6[key]] = event.data.text;
    }
  },
  false
);
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action === "get_title_description") {
    sendResponse(data_cache);
  }
});

service-worker.js


chrome.scripting.getRegisteredContentScripts(
  { ids: ["testing-scripts-gen"] },
  async (scripts) => {
    if (scripts && scripts.length) {
      await chrome.scripting.unregisterContentScripts({
        ids: ["testing-scripts-gen"],
      });
    }
    chrome.scripting.registerContentScripts([
      {
        id: "testing-scripts-gen",
        // 如content-script依赖其他js, 则需要在此写明, 不能使用import等模块关键字
        js: ["./content-script.js", "./common.js"],
        matches: [
          "*://shopee.sg/*",
          "*://shopee.tw/*",
          "*://shopee.com.my/*",
          "*://shopee.ph/*",
          "*://shopee.co.th/*",
          "*://shopee.vn/*",
          "*://shopee.com.br/*",
          "*://shopee.co.id/*",
          "*://shopee.com.mx/*"
        ],
        runAt: "document_start",
        allFrames: true,
      },
    ]);
  }
);

popup.js


chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
    chrome.tabs.sendMessage(
      tabs[0].id,
      {action: "get_title_description"},
      function (data) {
        if (data?.getProduct) {
          parseGetProduct(data.getProduct)
        }
      }
    );
  });

流程

  1. xhr代理对象拦截到指定url的请求后, 将请求内容发送到content-script
  2. content-script接收到内容, 将其缓存起来
  3. popupcontent-script发送消息
  4. content-script响应消息, 将缓存的请求内容返回给popup

Chrome插件在HTTPS页面获取HTTP接口数据

场景是这样的, 插件要在https页面根据规则做拦截, 但是获取规则的接口并不是https的.发起请求时, 被浏览器的安全策略给拦了.这里记录下解决思路页面上不能进行请求, 但是service-worker里是可以的所以将service-worker获取到的数据传到页面即可service-worke
2024-04-16

在线测试跨域

找个网页F12后, 控制台输入如下代码, 能获取到响应即正常var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://localhost:7099/api/xx/xx'); xhr.send(null); xhr.onload = functi
2024-04-16

Chrome插件获取页面请求内容

先代理xhr/fetch对象common.jsconst shopee_get_product_10045487 = "/api/v4/pdp/get_pc"; const api_category_34a10fd6 = {}; api_category_34a10fd6[shopee_get_
2024-01-10

Chrome插件 Popup 与 Content-Scripts通信

popup.jsdocument.getElementById("get").addEventListener("click", function () { chrome.tabs.query({ active: true, currentWindow: true }, function (ta
2023-12-22

各平台时间格式

javayyyy-MM-dd HH:mm:ss2021-01-18 13:05:25mysqlDATE_FORMAT(time,'%Y-%m-%d %H:%i:%s')2021-01-18 13:05:25sql serverSELECT CONVERT(varchar(100), GETDATE(
2021-01-18

Windows 创建软链接

比如将chrome的缓存从系统盘重定向到其他盘mklink /D sourcePath targetPath 示例mklink /D "C:\Users\root\AppData\Local\Google\Chrome\User Data\Default" D:\soft\chrome\Defaul
2020-11-04

Vue.js DOM操作

<template> <input type="button" @click="reply($event)" value="回复"> </template> export default { methods: { replyFun(e) {
2020-03-29

js向json中添加属性

object['attr'] = {};
2020-03-28

freemarker 时间显示不正常 设置时区

项目在本地开发的时候显示正常,部署上服务器就一直差8个小时,最后发现freemarker官方文档有这样的说明time_zone:时区的名称来显示并格式化时间。 默认情况下,使用JVM的时区。 也可以是 Java 时区 API 接受的值,或者 "JVM default" (从 FreeMarker 2
2020-03-28
IDEA 2019.1 xml 不高亮

IDEA 2019.1 xml 不高亮

前几天更新了idea后,发现xml里的代码都没有了高亮,变得跟记事本一个德性了打开setting ,搜索 File Types,找到xml项, 查看下方的匹配格式,果然没有xml,(idea真是厉害)点击右方的+,输入*.xml,点击ok,解决问题
2020-03-28

npm install 淘宝镜像

npm install --registry=https://registry.npm.taobao.org
2020-03-28
Java中方法的参数传递机制

Java中方法的参数传递机制

来看一段代码 public class Man { private String name; private Integer age; public String getName() { return name; } publi
2020-03-28
基于自定义注解手写权限控制

基于自定义注解手写权限控制

方法一: AOP 方法二: 拦截器项目结构项目依赖<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-w
2020-03-28

Docker 部署 详细全过程 附代码

Docker 部署本站 全过程环境:CentOS7.61. 安装Docker其他版本CentOS可以参考这个https://help.aliyun.com/document_detail/187598.html查看本机内核版本,内核版本需高于 3.10uname -r 确保 yum 包最新yum u
2020-03-28

SpringBoot 启动普通java工程

引入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
2020-03-28

Vue.js DOM操作

<template> <input type="button" @click="reply($event)" value="回复"> </template> export default { methods: { replyFun(e) {
2020-03-29
CentOS7编译调试OpenJDK12

CentOS7编译调试OpenJDK12

1. 下载源码https://hg.openjdk.java.net/jdk/jdk12点击左侧的browse,再点击zip,就可以下载zip格式的源码压缩包。unzip xxx.zip 解压文件2. 安装jdkyum install java-11-openjdk-devel -y3. 运行con
2020-04-23
编写自己的Spring Boot Starter

编写自己的Spring Boot Starter

1.新建一个maven项目命名规则统一是xxx-spring-boot-starter完整pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"
2020-06-29