AMO批准的将脚本注入文档的方法

时间:2014-03-07 07:11:39

标签: javascript firefox firefox-addon firefox-addon-sdk

我正在开发cross-browser extension for Battlelog(战地系列的在线游戏启动器和社交平台)。

为了使其正常运行,它需要访问页面的JS环境,因为整个网站是一个庞大而复杂的客户端应用程序,尝试复制它是没有意义的,而所有的功能我需要就在那里。

无论如何,我上周推出了一个工作扩展,并将其提交给AMO进行审核。几个小时前我收到了回复:

  

您的版本被拒绝了。您的加载项从HTML创建DOM节点   包含unsanitized数据的字符串,通过分配innerHTML或   通过类似的方式。除了效率低下,这是一个主要问题   安全风险。有关更多信息,请参阅   https://developer.mozilla.org/en/XUL_School/DOM_Building_and_HTML_Insertion

显然,这是因为this content script

var head = document.getElementsByTagName('head')[0];

var css = document.createElement('link');
css.setAttribute('rel', 'stylesheet');
css.setAttribute('type', 'text/css');
css.setAttribute('href', @@CSS@@);
head.appendChild(css);

var js = document.createElement('script');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', @@JS@@);
head.appendChild(js);

虽然我同意,但它很脏,我不知道这是一种安全风险或任何方式效率低下。其中没有“未经过规范化”的数据:@@CSS@@@@JS@@在构建过程中分别被self.data.url('battletag.css')self.data.url('battletag.js')替换。

我正在寻找一种方法来扩展工作而不需要点击页面的上下文(当然这是可能的),但我真的不想这样做,特别是在途中有几个功能,大量使用页面数据。响应中提供的链接根本没用,因为我的注入脚本基本上是JSON模板的精简版本。

将JS文件加载到文档中是否有“合法”方式?

1 个答案:

答案 0 :(得分:1)

你的代码看起来很好我不知道为什么拒绝它。

但他们想看到的是:

 var injectJsonCss = [
    'link', {
        rel: 'stylesheet',
        type: 'text/css',
        href: 'chrome://your-path-set-in-the-chrome.manifest-file/content/your-style.css'
    }
 ];

 var injectJsonScript = [
    'script', {
        type: 'stylesheet',
        type: 'text/javascript',
        src: 'chrome://your-path-set-in-the-chrome.manifest-file/content/your-script.js'
    }
 ];

jsonToDOM(injectJsonCss, document.head, {}); //inject the css
jsonToDOM(injectJsonScript, document.head, {}); //inject the script

确保该文档是网站的contentDocument

并在您的代码中粘贴从该页面中删除的库内容

jsonToDOM.namespaces = {
    html: "http://www.w3.org/1999/xhtml",
    xul: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
};
jsonToDOM.defaultNamespace = jsonToDOM.namespaces.html;
function jsonToDOM(xml, doc, nodes) {
    function namespace(name) {
        var m = /^(?:(.*):)?(.*)$/.exec(name);
        return [jsonToDOM.namespaces[m[1]], m[2]];
    }

    function tag(name, attr) {
        if (Array.isArray(name)) {
            var frag = doc.createDocumentFragment();
            Array.forEach(arguments, function (arg) {
                if (!Array.isArray(arg[0]))
                    frag.appendChild(tag.apply(null, arg));
                else
                    arg.forEach(function (arg) {
                        frag.appendChild(tag.apply(null, arg));
                    });
            });
            return frag;
        }

        var args = Array.slice(arguments, 2);
        var vals = namespace(name);
        var elem = doc.createElementNS(vals[0] || jsonToDOM.defaultNamespace,
                                       vals[1]);

        for (var key in attr) {
            var val = attr[key];
            if (nodes && key == "key")
                nodes[val] = elem;

            vals = namespace(key);
            if (typeof val == "function")
                elem.addEventListener(key.replace(/^on/, ""), val, false);
            else
                elem.setAttributeNS(vals[0] || "", vals[1], val);
        }
        args.forEach(function(e) {
            elem.appendChild(typeof e == "object" ? tag.apply(null, e) :
                             e instanceof Node    ? e : doc.createTextNode(e));
        });
        return elem;
    }
    return tag.apply(null, xml);
}

编辑第二个想法

您是否使用script.js中的脚本设置任何innerHTML?