ljjh#True

// background.js

// 使用 Map 存储拦截的请求数据,键为 interceptionId
const interceptedRequests = new Map();

// 使用 Map 存储 requestId 到 interceptionId 的映射
const requestIdToInterceptionIdMap = new Map();

// 存储已附加调试器的标签页ID
const debuggedTabs = new Set();

/**
 * 生成唯一的 uniqueRequestId
 */
function generateRequestId() {
  return `req_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
}

/**
 * 监听浏览器标签页更新,自动附加调试器
 */
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && !debuggedTabs.has(tabId)) {
    // 仅附加到 http 和 https 协议的标签页
    if (/^https?:\/\//.test(tab.url)) {
      attachDebugger(tabId);
    }
  }
});

/**
 * 监听新标签页创建,自动附加调试器
 */
chrome.tabs.onCreated.addListener((tab) => {
  if (/^https?:\/\//.test(tab.url)) {
    attachDebugger(tab.id);
  }
});

/**
 * 附加调试器到指定标签页
 */
function attachDebugger(tabId) {
  try {
    chrome.debugger.attach({ tabId: tabId }, '1.3', () => {
      if (chrome.runtime.lastError) {
        console.error(`Debugger attach failed: ${chrome.runtime.lastError.message}`);
        return;
      }
      debuggedTabs.add(tabId);
      console.log(`Debugger attached to tab ${tabId}`);

      // 启用网络域
      chrome.debugger.sendCommand({ tabId: tabId }, 'Network.enable');

      // 设置请求捕获的过滤器,拦截 URL 包含 '/build' 的所有类型请求
      chrome.debugger.sendCommand({ tabId: tabId }, 'Network.setRequestInterception', {
        patterns: [
          { urlPattern: '*://*/*/build*', interceptionStage: 'Request' }
        ]
      }, (response) => {
        if (chrome.runtime.lastError) {
          console.error(`Failed to set request interception: ${chrome.runtime.lastError.message}`);
        } else {
          console.log(`Request interception set for tab ${tabId}`);
        }
      });
    });
  } catch (error) {
    console.error(`Failed to attach debugger to tab ${tabId}:`, error);
  }
}

/**
 * 监听调试器的网络事件
 */
chrome.debugger.onEvent.addListener((source, method, params) => {
  if (method === 'Network.requestIntercepted') {
    handleRequestIntercepted(source.tabId, params);
  }
  if (method === 'Network.responseReceived') {
    handleResponseReceived(source.tabId, params);
  }
  // 监听加载完成事件
  if (method === 'Network.loadingFinished') {
    handleLoadingFinished(source.tabId, params);
  }
});

/**
 * 处理 Network.requestIntercepted 事件
 */
function handleRequestIntercepted(tabId, params) {
  const { interceptionId, requestId, request, resourceType } = params;
  const { url, method, headers, postData } = request;

  // 检查是否成功获取到 url
  if (!url) {
    console.warn(`[background.js] 拦截ID ${interceptionId} 的请求缺少 URL 信息`);
    // 继续拦截的请求,避免阻塞
    chrome.debugger.sendCommand({ tabId: tabId }, 'Network.continueInterceptedRequest', { interceptionId }, (response) => {
      if (chrome.runtime.lastError) {
        console.error(`Failed to continue request ${interceptionId}: ${chrome.runtime.lastError.message}`);
      } else {
        console.log(`Continued request ${interceptionId}`);
      }
    });
    return;
  }

  // 仅处理 URL 包含 '/build' 的请求
  if (!url.includes('/build')) {
    // 继续拦截的请求,避免阻塞
    chrome.debugger.sendCommand({ tabId: tabId }, 'Network.continueInterceptedRequest', { interceptionId }, (response) => {
      if (chrome.runtime.lastError) {
        console.error(`Failed to continue request ${interceptionId}: ${chrome.runtime.lastError.message}`);
      } else {
        console.log(`Continued request ${interceptionId}`);
      }
    });
    return;
  }

  console.log(`存储请求信息 ${JSON.stringify({
    url: url,
    method: method,
    headers: headers,
    payload: postData || null,
    type: resourceType,
    responseContent: null
  })}`)

  // 存储请求信息
  interceptedRequests.set(interceptionId, {
    url: url,
    method: method,
    headers: headers,
    payload: postData || null,
    type: resourceType,
    responseContent: null
  });

  // 存储 requestId 到 interceptionId 的映射
  requestIdToInterceptionIdMap.set(requestId, interceptionId);

  console.log(`[background.js] 捕获到请求 - 拦截ID: ${interceptionId}, 类型: ${resourceType}, 方法: ${method}, URL: ${url}`);

  // 继续拦截的请求,确保请求不会被阻塞
  chrome.debugger.sendCommand({ tabId: tabId }, 'Network.continueInterceptedRequest', { interceptionId }, (response) => {
    if (chrome.runtime.lastError) {
      console.error(`Failed to continue request ${interceptionId}: ${chrome.runtime.lastError.message}`);
    } else {
      console.log(`Continued request ${interceptionId}`);
    }
  });
}

/**
 * 处理 Network.responseReceived 事件
 */
function handleResponseReceived(tabId, params) {
  const { requestId, response, type } = params;

  // 检查是否有对应的 interceptionId
  if (!requestIdToInterceptionIdMap.has(requestId)) {
    return;
  }

  const interceptionId = requestIdToInterceptionIdMap.get(requestId);
  const requestInfo = interceptedRequests.get(interceptionId);

  if (!requestInfo) {
    return;
  }

  // 更新请求类型(有时 response.type 可能更准确)
  requestInfo.type = type;

  console.log(`[background.js] 捕获到响应 - 类型: ${type}, URL: ${response.url}`);
}

/**
 * 处理 Network.loadingFinished 事件
 */
function handleLoadingFinished(tabId, params) {
  const { requestId } = params;

  // 检查是否有对应的 interceptionId
  if (!requestIdToInterceptionIdMap.has(requestId)) {
    return;
  }

  const interceptionId = requestIdToInterceptionIdMap.get(requestId);
  requestIdToInterceptionIdMap.delete(requestId);

  const requestInfo = interceptedRequests.get(interceptionId);

  if (!requestInfo) {
    return;
  }

  // 发送命令获取响应内容
  chrome.debugger.sendCommand({ tabId: tabId }, 'Network.getResponseBody', { requestId }, (bodyResponse) => {
    if (chrome.runtime.lastError) {
      console.error(`Failed to get response body for requestId ${requestId}: ${chrome.runtime.lastError.message}`);
      interceptedRequests.delete(interceptionId);
      return;
    }

    const { body, base64Encoded } = bodyResponse;
    const responseContent = base64Encoded ? atob(body) : body;

    console.log(`[background.js] 捕获到响应内容 - 方法: ${requestInfo.method}, URL: ${requestInfo.url}, 内容长度: ${responseContent.length}`);

    // 生成唯一的 uniqueRequestId
    const uniqueRequestId = generateRequestId();

    // 存储完整的请求和响应信息
    console.log(`存储完整的请求和响应信息: ${JSON.stringify({
      requestId: uniqueRequestId,
      url: requestInfo.url,
      method: requestInfo.method,
      payload: requestInfo.payload,
      headers: requestInfo.headers,
      responseContent: responseContent,
      type: requestInfo.type
    })}`);

    interceptedRequests.set(uniqueRequestId, {
      requestId: uniqueRequestId,
      url: requestInfo.url,
      method: requestInfo.method,
      payload: requestInfo.payload,
      headers: requestInfo.headers,
      responseContent: responseContent,
      type: requestInfo.type
    });

    console.log(`[background.js] 请求已存储,uniqueRequestId: ${uniqueRequestId}`);

    // 移除原始的 interceptionId
    interceptedRequests.delete(interceptionId);
  });
}

/**
 * 监听来自弹出页面的消息
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === "getDocumentRequests") {
    // 将 Map 转换为数组进行传输
    const data = Array.from(interceptedRequests.values());
    sendResponse({ data: data });
  } else if (request.action === "clearDocumentRequests") {
    interceptedRequests.clear();
    requestIdToInterceptionIdMap.clear();
    sendResponse({ data: "清除成功" });
    console.log("interceptedRequests 和 requestIdToInterceptionIdMap 已清除");
  }
});

/**
 * 在扩展卸载时,移除所有附加的调试器
 */
chrome.runtime.onSuspend.addListener(() => {
  debuggedTabs.forEach(tabId => {
    chrome.debugger.detach({ tabId: tabId }, () => {
      console.log(`Debugger detached from tab ${tabId}`);
    });
  });
});
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试经典150】day 9

目录 1.Z 字形变换 2.找出字符串中第一个匹配项的下标 3.文本左右对齐 1.Z 字形变换 class Solution {public String convert(String s, int numRows) {//明明是N字形变换if(numRows<2) return s;//rows是可扩展的字符串数组List<StringBuilder>rowsnew ArrayLi…

代码随想录 | Day36 | 动态规划 :整数拆分不同的二叉搜索树

代码随想录 | Day36 | 动态规划 &#xff1a;整数拆分&不同的二叉搜索树 动态规划应该如何学习&#xff1f;-CSDN博客 动态规划学习&#xff1a; 1.思考回溯法&#xff08;深度优先遍历&#xff09;怎么写 注意要画树形结构图 2.转成记忆化搜索 看哪些地方是重复计算…

TCP丢包,连接机制,滑动窗口解析

面向字节流 如何理解面向字节流&#xff1f; 发送缓冲区&#xff0c;我们将它当做char类型的数组&#xff0c;当发送时他们的发送序号就可以从他们的下标来获取&#xff0c;接受缓冲区也是char数组&#xff0c;再一个一个字节的向上层读取。 如何理解流动的概念 我们的报文中…

前端开发设计模式——观察者模式

目录 一、定义和特点 1. 定义 2. 特点 二、实现方式 1. 使用 JavaScript 实现观察者模式的基本结构 2. 实际应用中的实现示例 三、使用场景 1. 事件处理 2. 数据绑定 3. 异步通信 4. 组件通信 四、优点 1. 解耦和灵活性 2. 实时响应和数据一致性 3. 提高代码的可…

少儿编程学习中的家庭支持:家长角色如何从监督到参与?

随着少儿编程教育的普及&#xff0c;越来越多的家庭开始意识到编程对孩子未来发展的重要性。编程不仅仅是一项技术技能&#xff0c;更是培养逻辑思维、解决问题能力和创新意识的有效途径。然而&#xff0c;如何在家庭中正确支持孩子的编程学习&#xff0c;对家长而言是一个新的…

EJB项目如何升级SpringCloud

记录某金融机构老项目重构升级为微服务过程1 如何从EJB架构拆分微服务 这个非常有趣的过程&#xff0c;整个过程耗时大致接近半年时光&#xff0c;需要考虑到重构升级保留原来的业务线&#xff0c;而且还要考虑后续的维护成本&#xff0c;保留现有的数据库表结构&#xff0c;…

Redis 哨兵 问题

前言 相关系列 《Redis & 目录》《Redis & 哨兵 & 源码》《Redis & 哨兵 & 总结》《Redis & 哨兵 & 问题》 参考文献 《Redis的主从复制和哨兵机制详解》《Redis中的哨兵&#xff08;Sentinel&#xff09;》《【Redis实现系列】Sentinel自动故…

基于SpringBoot的在线医疗问答平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

如何使用 Python 操作数据库

&#x1f600;前言 在现代编程中&#xff0c;Python 的数据库操作已广泛应用于各类项目中&#xff0c;例如数据分析、Web 开发和数据持久化存储等。本文将介绍 Python 操作数据库的核心步骤&#xff0c;涉及数据库连接对象、游标对象的使用&#xff0c;以及常见的 SQL 数据操作…

夸克浏览器的用户反馈如何提交

夸克浏览器凭借其简洁的界面、强大的功能以及不断优化的用户体验&#xff0c;赢得了众多用户的青睐。然而&#xff0c;任何产品都不可能完美无缺&#xff0c;用户的反馈对于产品的持续改进至关重要。本文将详细介绍如何在夸克浏览器中高效提交用户反馈&#xff0c;帮助开发者更…

极狐GitLab 签约新大陆自动识别,以质量和安全让智能识别更精准

关于新大陆自动识别 福建新大陆自动识别技术有限公司&#xff08;以下简称为新大陆自动识别&#xff09;是新大陆科技集团的成员企业&#xff0c;是新大陆数字技术股份有限公司(股票代码: 000997)的全资子公司。成立自1999年&#xff0c;当前已成为一家全球化的感知识别和机器…

【移动应用开发】使用多媒体--通知/播放音频/视频

目录 一、具体步骤 二、运行截图 1. 开启通知权限 2. 播放音乐 3. 播放视频 三、源代码 1. activity_main.xml 2. activity_video_player.xml 3. activity_notification.xml 4. 一些配置 5. MainActivity 6. VideoPlayerActivity 7. NotificationActivity 8. And…

VulnHub-Brainpan1 靶机笔记

Brainpan1 靶机笔记 概述 靶机地址&#xff1a;https://vulnhub.com/entry/brainpan-1,51/#download 这台靶机是很好的缓冲区溢出漏洞利用的练习靶机&#xff0c;涉及到逆向和缓冲区溢出漏洞挖掘的一些知识。 一、nmap 扫描 1&#xff09;端口扫描 nmap -sT --min-rate 1…

echarts实现 水库高程模拟图表

需求背景解决思路解决效果index.vue 需求背景 需要做一个水库高程模拟的图表&#xff0c;x轴是水平距离&#xff0c;y轴是高程&#xff0c;需要模拟改水库的形状 echarts 图表集链接 解决思路 配合ui切图&#xff0c;模拟水库形状 解决效果 index.vue <!--/*** author:…

安全见闻-web安全

web安全 一、web程序简介 1. Web程序的基本构成 2. 工作流程 3. 安全性 二、JavaScript代码库 1. 代码库的概念和用途 2. 常见的代码库 三、框架 1. 常见的前端框架 2. 常见的后端框架 四、数据库 1. 数据库的分类 2. 数据库的潜在漏洞 3. 学习数据库的重要性 五、…

Vue.js(2) 基础:指令与功能概览

正确的开始&#xff0c;微笑的进步&#xff0c;然后持续 文章目录 class和Style绑定v-bind绑定classv-bind绑定style 指令v-model指令v-clock指令v-once指令自定义指令 功能过滤器操作dom计算属性 class和Style绑定 v-bind绑定class 绑定数据对象<div id"app"&g…

【Linux探索学习】第九弹——Linux工具篇(四):项目自动化构建工具—make/Makefile

Linux笔记&#xff1a;https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在前面我们学习了如何用编译并执行&#xff0c;在现代软件开发中&#xff0c;构建一个项目涉及多个步骤&#xff0c;从编译源代码到链接库文件&a…

基于SpringBoot+Vue+MySQL的房屋租赁系统

系统展示 系统背景 随着城市化进程的加速和人口流动性的增加&#xff0c;房屋租赁市场逐渐成为城市生活的重要组成部分。然而&#xff0c;传统的房屋租赁方式存在诸多问题&#xff0c;如信息不对称、交易成本高、租赁关系不稳定等&#xff0c;这些问题严重影响了租赁市场的健康…

View三大机制(一):触摸机制(事件分发)

传递过程遵循如下顺序&#xff1a;Activity->Window->PhoneWindow->DecorView->RootView->ViewGroup->View View事件方法执行顺序:onTouchListener > onTouchEvent > onLongClickListener > onClickListener 主要由三个重要的方法共同完成的,只有Vi…

【面试】rabbitmq的主要组件有哪些?

目录 1. Producer&#xff08;生产者&#xff09;2. Broker&#xff08;消息代理&#xff09;3. Exchange&#xff08;交换机&#xff09;4. Queue&#xff08;队列&#xff09;5. Consumer&#xff08;消费者&#xff09;6. Binding&#xff08;绑定&#xff09;7. Channel&am…