如何获取"Invalid chrome URI"异常的堆栈跟踪?



我正在调试一个基于XUL的Firefox扩展,该扩展已被Firefox 46版本破坏。

当我运行扩展时,浏览器控制台显示:

Invalid chrome URI: /

既没有行号也没有堆栈跟踪。

在网络论坛上,我读到ChromeBug可以用于此。然后,我尝试了ChromeBug的最新稳定版本(1.7.2),但自2014年10月以来一直没有更新,似乎与最近的Firefox版本不兼容。

因为这个扩展是"老式"的,所以我不能使用插件调试器,所以我使用了浏览器工具箱,但它不显示异常。

考虑到扩展的行数,在代码中漫游不是一种选择。知道我怎么能得到堆栈跟踪吗?

当在浏览器控制台中获得这种类型的错误时,您几乎没有得到导致错误的信息,很可能错误不在JavaScript中,甚至可能不在代码中。在这种情况下,不可能获得JavaScript堆栈跟踪,因为它根本不存在。

这样的事情通常是由打开的弹出窗口或选项卡中使用的XUL或HTML中的问题引起的。您的加载项将打开一个包含内容的选项卡chrome://restclient/content/restclient.html。用一个没有内容的HTML文档代替该文件可以消除错误。

使用该文件内容的二进制搜索(一次注释/删除文件的渐进式半部分,并测试错误是否仍然存在)到a)确认错误存在和B)导致错误的原因,结果确定以下行导致错误显示在浏览器控制台中(第197行):

<input class="span5" style="width:-moz-calc(100% - 1em) !important;" type="password" name="password" autocomplete="on" placeholder="Password">

更多的测试表明,当type不是password时,问题就消失了。将原始HTML文档复制到一个我可以使用file: URL轻松访问的地方,当打开文档时,浏览器控制台中不会出现这样的错误。

因此,结论是,当从chrome: URI加载时,这是Mozilla的<input type="password">代码中的一个错误。

在没有堆栈跟踪的代码中查找无效的chrome: URI:
如果在HTML或XUL文件中没有发现问题,则有必要查看附加组件中使用的chrome: URI,以查找可能的原因。

chrome:URI具有一些属性,我们可以利用这些属性来跟踪这样一个问题:

  • chrome: URI通常是静态的
  • chrome: URI通常采用chrome:\packageName{content,skin,locale}格式
  • 您的chrome.manifest文件定义了哪些chrome: URI可以对您的加载项/包有效
  • 其他chrome.manifest文件定义了哪些chrome: URI可以在加载项/包之外有效

因此,首先查看chrome.manifest文件:

content   restclient                content/
resource  restclient                ./
overlay chrome://browser/content/browser.xul chrome://restclient/content/overlay.xul
overlay chrome://navigator/content/navigator.xul    chrome://restclient/content/overlay.xul
style chrome://global/content/customizeToolbar.xul chrome://restclient/content/css/overlay.css

此消息告诉我们,在您的程序包中,唯一有效的内部chrome: URI将采用chrome://restclient/content/格式,并将引用加载项根目录中的内容目录。

因此,我们现在查找附加组件中使用的所有chrome: URI。要做到这一点,grep -nri chrome: *的命令行是一种简单的方法。grep可以作为多个操作系统下的标准实用程序使用。在Windows中,我通常从Cygwin那里得到它。从这个命令我们得到:

chrome.manifest:4:overlay chrome://browser/content/browser.xul chrome://restclient/content/overlay.xul
chrome.manifest:5:overlay       chrome://navigator/content/navigator.xul        chrome://restclient/content/overlay.xul
chrome.manifest:6:style chrome://global/content/customizeToolbar.xul chrome://restclient/content/css/overlay.css
content/css/overlay.css:30:  list-style-image: url("chrome://restclient/content/images/icon16.png") !important;
content/css/overlay.css:33:  list-style-image: url("chrome://restclient/content/images/icon16.png") !important;
content/js/restclient.js:51:        i18nStrings = new restclient.StringBundle("chrome://restclient/locale/restclient.properties");
content/js/restclient.main.js:1040:      xslDocument.load("chrome://restclient/content/xsl/XMLPrettyPrint.xsl");
content/js/restclient.main.js:1053:      xslDoc.load("chrome://restclient/content/xsl/XMLIndent.xsl");*/
content/js/restclient.overlay.js:68:    browser.selectedTab = browser.addTab("chrome://restclient/content/restclient.html");
content/overlay.xul:2:<?xml-stylesheet href="chrome://restclient/content/css/overlay.css" type="text/css"?>
content/overlay.xul:7:  <script type="application/x-javascript" src="chrome://restclient/content/js/restclient.js" />
content/overlay.xul:8:  <script type="application/x-javascript" src="chrome://restclient/content/js/restclient.overlay.js" />
content/overlay.xul:23:                    image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:35:              image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:46:              image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:58:              image="chrome://restclient/content/images/icon16.png"/>
modules/StringBundle.js:59: *     new StringBundle("chrome://example/locale/strings.properties");

现在,我们可以,也可能应该手动查找问题,但我们可以使用命令grep -nri chrome: * | grep -v chrome://restclient/content/快速缩短列表以发现明显的问题。这将为我们提供任何chrome: URI,这些URI的格式不适用于引用附加组件的content。获得的列表可以很容易地包含有效的chrome: URI,这些URI引用附加组件之外的文件。所以,我们可能需要做更多的检查。从上面的命令我们得到:

content/js/restclient.js:51:        i18nStrings = new restclient.StringBundle("chrome://restclient/locale/restclient.properties");
modules/StringBundle.js:59: *     new StringBundle("chrome://example/locale/strings.properties");

第一个是locale chrome: URI。您没有在chrome.manifest中指定locale。因此,它肯定是无效的。看看content/js/restclient.js的第51行,它在活动代码中。当它被实际使用时,它将是无效的。

第二种可能性是典型的示例chrome: URI。该行以*开头,暗示它可能是一条注释。检查modules/StringBundle.js的第59行可以发现它是一个注释。

如果还没有发现问题,下一步将解决已知的无效chrome: URI,并进行测试,看看这是否解决了问题。在这种情况下,我们已经知道问题是什么,所以没有必要检查。

但是,假设chrome://restclient/locale/restclient.properties无效,并且A)加载项中没有此类文件,B)chrome.manifest.中没有定义locale,这意味着如果执行该代码,它将失败。基本上,函数restclient.i18n是死代码/坏代码,应该删除。考虑到该函数是modules/StringBundle.js文件的唯一用途,它也可以被删除。显然,如果这是你正在积极努力的事情,那就另当别论了。

在处理这个问题的过程中,我还注意到浏览器控制台中的其他几个错误,您可能应该看看:

21:26:37.975 SyntaxError: test for equality (==) mistyped as assignment (=)?1 chrome://restclient/content/js/bootstrap.js:1557:33
21:26:37.989 TypeError: variable url redeclares argument1 chrome://restclient/content/js/restclient.main.js:376:8

虽然这些并不是固有的错误,但在插件的正常操作过程中,浏览器控制台中通常不会显示任何内容。不过,考虑到jquery.js中报告的各种错误,还有什么呢?

相关内容

最新更新