1

我已经使用 Addon SDK 构建了一个 Firefox 扩展,它打开了一个新选项卡,其中包含扩展目录中的 HTML 页面,并将内容脚本附加到它:

function openHtmlLoadFormTab(htmlFileName, jsWorkerFileName) {
    tabs.open({
        url: data.url(htmlFileName),
        onReady: function(tab) {
            var tabWorker = tab.attach({
                contentScriptFile: [ data.url(jsJquery), data.url(jsWorkerFileName) ]
            });
        }
    });
}

<input type="file">在 HTML 文件中有一个和一些处理 JS 文件中的“提交”事件的代码(这些文件分别由htmlFileName和给出jsWorkerFileName

由于安全原因,我无法使用 .js 访问 JS 中的完整文件路径document.getElementById('uploadid').value。我只得到文件名。

但是,由于这是一个 Firefox 扩展,我想知道是否有办法覆盖这个限制?

我一直在研究netscape.security.PrivilegeManager.enablePrivilege("UniversalFileRead")mozFullPath但我无法让它发挥作用。我相信它已经被弃用了?

另一种解决方案是构建一个基于 XUL 的 UI 并以某种方式提示输入文件,但我想确定是否有任何方法可以让它在 HTML 中工作。

首先使用小示例代码进行编辑

我构建了一个小的示例扩展来说明我是如何做事的。

lib/main.js

var self = require('self');
var tabs = require('tabs');
var data = self.data;
var jsLoadForm = "load-form.js", htmlLoadForm = "load-form.html";
var jsJquery = 'jquery-1.8.0.min.js';


exports.onUnload = function(reason) {};
exports.main = function(options, callbacks) {
    // TODO: remove this debugging line
    openHtmlLoadFormTab(htmlLoadForm, jsLoadForm);
};

function openHtmlLoadFormTab(htmlFileName, jsWorkerFileName) {
    tabs.open({
        url: data.url(htmlFileName),
        onReady: function(tab) {
            var tabWorker = tab.attach({
                contentScriptFile: [ data.url(jsJquery), data.url(jsWorkerFileName) ]
            });
        }
    });
}

数据/加载-form.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Form</title>

        <script lang="text/javascript">
            function fileChanged(e) {
                // this is just the file name
                alert("html js: files[0].name: " + e.files[0].name);

                // mozFullPath is indeed empty, NOT undefined
                alert("html js: files[0].mozFullPath: " + e.files[0].mozFullPath);
            }
        </script>
    </head>

    <body>
        <form name="my-form" id="my-form" action="">
            <div>
                <label for="uploadid1" id="uploadlabel1">File (JS in HTML):</label>
                <input type="file" name="uploadid1" id="uploadid1" onchange="fileChanged(this)"/>
            </div>
            <div>
                <label for="uploadid2" id="uploadlabel2">File (JS in content script): </label>
                <input type="file" name="uploadid2" id="uploadid2" onchange="fileChangedInContentScript(this)"/>
            </div>
            <div>
                <label for="uploadid3" id="uploadlabel3">File (JS using jQuery in content script):</label>
                <input type="file" name="uploadid3" id="uploadid3" />
            </div>
        </form>
    </body>
</html>

数据/加载-form.js

$(document).ready(function() {
    $("#uploadid3").change(function(e) {
        // in jquery, e.files is null
        if(e.files != null)
            console.log("jquery: e.files is defined");
        else
            console.log("jquery: e.files is null");

        // this works, prints the file name though
        console.log("$('#uploadid3').val(): " + $("#uploadid3").val());
        // this is undefined
        console.log("$('#uploadid3').mozFullPath: " + $("#uploadid3").mozFullPath);
    });
});

// this handler never gets called
function fileChangedInContentScript(e) {
    alert("js content script: filechanged in content script called");
}

正如您在 main.js 中看到的,我使用了从 jQuery 网站下载的 jquery-1.8.0.min.js。

注意:当我在 main.js 中打开选项卡时,我也尝试了没有将 jQuery 作为内容脚本包含在内的这些,但没有运气。

结论是,mozFullPath当我从嵌入在 HTML 页面中的 JS 访问它时,它确实是空的,我找不到从 jQuery 访问的方法mozFullPath,也找不到onchange在 load-form.html 中添加处理程序的方法,该处理程序定义在 load-表单.js

在 load-form.js 内容脚本中使用 onchange 处理程序进行第二次编辑

我将以下代码添加到 load-form.js 以捕获 onchange 事件。我还从 main.js 中删除了 jQuery 内容脚本

document.addEventListener("DOMContentLoaded", function() {
    try {
        document.getElementById("uploadid2").addEventListener('change', function(e) {
            console.log("addeventlistener worked!");    
            console.log("e: " + e);
            console.log("e.target: " + e.target);
            console.log("e.target.files: " + e.target.files);
            console.log("e.target.files[0].name: " + e.target.files[0].name);
            console.log("e.target.files[0].mozFullPath: " + e.target.files[0].mozFullPath);
        });

        console.log('added event listener')
    } catch(e) {
        console.log('adding event listener failed: ' + e);
    }
}, false);

这仍然为 mozFullPath 输出一个空字符串:

info: added event listener
info: addeventlistener worked!
info: e: [object Event]
info: e.target: [object HTMLInputElement]
info: e.target.files: [object FileList]
info: e.target.files[0].name: test.sh
info: e.target.files[0].mozFullPath: 

反正有没有获得所需的权限?我怎样才能走上这条完整的道路?我需要完整路径,以便可以将其传递给扩展程序启动的应用程序。(有一些解决方法我可以在没有完整路径的情况下完成,但它们会降低扩展的质量)

4

1 回答 1

1

fileInput.value属性意味着网页可以访问,所以它只会给你文件名,而不是完整路径 - 网页没有理由知道你机器上的完整路径。但是,作为特权扩展,您应该能够访问该File.mozFullPath属性。在这种特殊情况下,您会这样做:

var files = document.getElementById('uploadid').files;
if (files.length > 0)
{
  // Assuming that only one file can be selected
  // we care only about the first entry
  console.log(files[0].mozFullPath);
}

最大的问题当然是你的代码是否被允许访问File.mozFullPath。我怀疑附加 SDK 中的内容脚本没有必要的权限。主扩展代码将拥有特权,但从那里进入输入字段很难......

于 2012-08-27T18:48:42.513 回答