当前位置: 首页 > news >正文

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.mrgr.cn/news/62098.html

相关文章:

  • vue添加省市区
  • Spring Security使用
  • SQL PRIMARY KEY
  • Word 每次打开时都会弹出“要还原的文件”对话框
  • 【数据仓库】
  • 初识WebGL
  • Java继承的super关键字
  • 【C++刷题】力扣-#594-最长和谐子序列
  • C++ 之 VS2010 和MySQL数据库的链接问题
  • leetcode452. 用最少数量的箭引爆气球
  • Autosar AP SM中同EM相关的核心概念解析
  • 《探秘 POC 方案:开启创新之门的钥匙》
  • 如何使用SOCKS5代理提升匿名性
  • 两台主机只能单方向ping通
  • Spring Boot 创建项目详细介绍
  • SpringBoot最大的优势是什么?
  • 24.10.30 Python 包和模块
  • 加油-加油
  • C++基础: string(3)
  • 【ROS】详解ROS文件系统
  • 【ECMAScript标准】深入解析ES5:现代JavaScript的基石
  • InnoDB 存储引擎<四>磁盘文件一
  • QChart中柱形图的简单使用并实现【Qt】
  • 【力扣打卡系列】反转链表
  • python 模块和包、类和对象
  • VBA语言専攻介绍20241031