2

我正在尝试使用 Firefox 28.0 调试 Firefox 扩展。

我已经按照https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment中的建议设置了开发环境(实际上我只是采取了懒惰的方式并安装了 DevPrefs 扩展来设置所有必要的:配置)

然后我打开 Firefox 并进入调试环境(工具 > Web 开发人员 > 浏览器工具箱)。

然后我转到调试器选项卡。

但是,在 Sources 窗格下,在我的扩展程序(例如 chrome://myextension)下,我只能看到包含在我的扩展程序 XPI 中的一些 JS 和 XUL 文件。

如何在调试器中手动“加载文件”,以便设置断点并跟踪扩展的运行时?

4

1 回答 1

5

The debugger doesn't have any functionality that would allow loading files "manually", instead it will show you every file that is currently loaded by the JavaScript engine. If you dig into details, this means that whenever the JavaScript engine compiles a new script the debugger is notified and adds the corresponding file to its list. So normally all you need to do is open a page or dialog that uses that script and it will become visible in the debugger. I say "normally" because in my tests this didn't seem to work reliably - there appears to be some bug which makes the debugger miss out some scripts, maybe that's what prompted your question.

Now of course you can consider faking the notification to force the debugger to load a particular file - e.g. if you want to set breakpoints before the file actually loads. I tried it and it is indeed possible, but it requires you to mess with Firefox internals and it relies on a number of implementation details that might change in future Firefox versions. In particular, you need to get the DebuggerServer instance used to communicate with the debugger. While the in-process debugger always uses the same instance which is trivial to get, a new instance is created for each remote debugger. From what I can tell, getting to that instance is only possible with the changes implemented in bug 993029 which means that it will only work with Firefox 32 (currently available from the Firefox Aurora channel) and above.

The problem is that the DebuggerServer instance is being created by the BrowserToolboxProcess class declared in ToolboxProcess.jsm. Before the changes introduced by bug 993029 a BrowserToolboxProcess object would be created and no reference to it kept - meaning that it would be impossible to access it and the corresponding connection after the fact. Starting with Firefox 32 all created BrowserToolboxProcess objects are stored in the processes set and can be enumerated.

This code can be used to fake a Debugger.onNewScript() call that will be forwarded to the remote debugger:

(function()
{
  // Iterate over existing processes
  const {processes} = Cu.import("resource:///modules/devtools/ToolboxProcess.jsm", null);
  for (var process of processes)
  {
    // Iterate over connections associated with each process
    var debuggerServer = process.debuggerServer;
    for (var connID in debuggerServer._connections)
    {
      if (!debuggerServer._connections.hasOwnProperty(connID))
        continue;
      var conn = debuggerServer._connections[connID];

      // Get ChromeDebuggerActor instance for the connection
      var chromeDebugger = conn._getOrCreateActor(conn.rootActor._extraActors.chromeDebugger.actorID);

      // Fake new script call
      chromeDebugger.onNewScript({
        url: "chrome://myextension/content/script.js", // CHANGE THAT LINE
        source: {text:""},
        getChildScripts: () => []
      });
    }
  }
})();

As mentioned above, this code should only work starting with Firefox 32, I tested it on Firefox 33.0a1. You can run it from Scratchpad, make sure to switch environment to "Browser". There is no guarantee whatsoever that it will continue working in future Firefox versions, there are several implementation details used here that can change at any time.

于 2014-07-17T12:01:09.080 回答