You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Chrome调试器API在内联脚本的document.write处断点并记录参数

问题描述

我有一个包含内联脚本<script>document.write("bla")</script>的页面,想要开发Chrome扩展记录document.write的参数“bla”。原本计划使用Chrome调试器API,但代码并未触发断点。

相关代码如下:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status === 'complete' && tab.url && !tab.url.startsWith('chrome://')) {
        attachDebugger(tab.id);
    }
});

function attachDebugger(debuggeeTabId) {
    chrome.debugger.attach({tabId:debuggeeTabId}, "1.0", function() {
        if (chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError.message);
            return;
        }

        // Enable the Debugger
        chrome.debugger.sendCommand({tabId:debuggeeTabId}, "Debugger.enable", {}, function() {
            if (chrome.runtime.lastError) {
                console.log(chrome.runtime.lastError.message);
                return;
            }
            
            chrome.debugger.sendCommand({tabId:debuggeeTabId}, "DOM.enable", {}, function() {
                if (chrome.runtime.lastError) {
                    console.log(chrome.runtime.lastError.message);
                    return;
                }

                // Set the breakpoint
                chrome.debugger.sendCommand({tabId:debuggeeTabId}, "DOMDebugger.setInstrumentationBreakpoint", {eventName: "document.write"}, function() {
                    if (chrome.runtime.lastError) {
                        console.log(chrome.runtime.lastError.message);
                        return;
                    }
                    console.log("Breakpoint set on document.write");
                });
            });
        });
    });

    chrome.debugger.onEvent.addListener(debuggerEvent);
}

function debuggerEvent(debuggeeId, message, params) {

    console.log(message + " " + JSON.stringify(params));

    //let callFrame = params.callFrames[0];
    //let funcArgs = callFrame.scopeChain[0].object.description;
    //console.log("document.write called with arguments: ", funcArgs);
}

Chrome DevTools中有“EventListener Breakpoint - Parse - document.write”的断点选项,但不清楚实现方式;尝试使用DOMDebugger.setEventListenerBreakpoint也未成功。

解决方案

核心问题分析

原代码失效的关键原因是时机不对:tabs.onUpdated的complete状态在页面所有资源加载完成后触发,但内联的document.write在HTML解析阶段就已经执行完毕,此时再附加调试器、设置断点,根本无法捕获到目标调用。

修正后的代码

1. 背景脚本(background.js)

// 改用webNavigation.onCommitted事件,在页面开始加载时触发
chrome.webNavigation.onCommitted.addListener((details) => {
  const tabId = details.tabId;
  chrome.tabs.get(tabId, (tab) => {
    if (tab.url && !tab.url.startsWith('chrome://')) {
      attachDebugger(tabId);
    }
  });
});

function attachDebugger(debuggeeTabId) {
  chrome.debugger.attach({tabId: debuggeeTabId}, "1.0", () => {
    if (chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError.message);
      return;
    }

    // 启用Debugger
    chrome.debugger.sendCommand({tabId: debuggeeTabId}, "Debugger.enable", {}, () => {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
      }

      // 启用DOMDebugger(无需启用DOM,此处不需要)
      chrome.debugger.sendCommand({tabId: debuggeeTabId}, "DOMDebugger.enable", {}, () => {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          return;
        }

        // 设置document.write的 instrumentation breakpoint
        chrome.debugger.sendCommand(
          {tabId: debuggeeTabId},
          "DOMDebugger.setInstrumentationBreakpoint",
          {eventName: "document.write"},
          () => {
            if (chrome.runtime.lastError) {
              console.log(chrome.runtime.lastError.message);
              return;
            }
            console.log("已设置document.write断点");
          }
        );
      });
    });
  });

  // 先移除旧监听,避免重复绑定导致多次输出
  chrome.debugger.onEvent.removeListener(debuggerEvent);
  chrome.debugger.onEvent.addListener(debuggerEvent);
}

function debuggerEvent(debuggeeId, message, params) {
  // 监听instrumentation断点触发事件
  if (message === "DOMDebugger.instrumentationBreakpointHit") {
    // 获取document.write的调用栈帧
    const callFrame = params.callFrames[0];
    // 提取第一个参数值
    if (callFrame.arguments.length > 0) {
      const writeParam = callFrame.arguments[0].value;
      console.log("document.write调用参数:", writeParam);
    }
  }
}

2. 清单文件(manifest.json)

需要添加webNavigation权限确保能捕获页面加载事件:

{
  "name": "Document Write 日志记录器",
  "version": "1.0",
  "permissions": ["debugger", "tabs", "webNavigation"],
  "background": {
    "service_worker": "background.js"
  },
  "manifest_version": 3
}

关键改动说明

  • 事件替换:用chrome.webNavigation.onCommitted替代tabs.onUpdated,确保在页面解析HTML前完成调试器附加和断点设置。
  • 事件监听优化:每次附加调试器前先移除旧的debuggerEvent监听,避免重复绑定导致多次输出。
  • 参数提取逻辑:在DOMDebugger.instrumentationBreakpointHit事件中,通过callFrames获取调用栈,直接从arguments中提取document.write的传入参数。

内容的提问来源于stack exchange,提问作者joe-jeff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:44:59