Firefox extensions and full file paths from HTML form?

六月ゝ 毕业季﹏ 提交于 2019-12-24 06:38:29

问题


I have built a Firefox extension using the Addon SDK that opens up a new tab with a HTML page from the extensions directory and attaches a content script to it:

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

I have an <input type="file"> in the HTML file and some code that handles the "submit" event in the JS file (these files are given by htmlFileName and jsWorkerFileName respectively)

Because of security reasons, I cannot access the full file path in JS with document.getElementById('uploadid').value. I only get the file's name.

However, since this is a Firefox extension, I'm wondering if there is anyway to override this restriction?

I have been looking into netscape.security.PrivilegeManager.enablePrivilege("UniversalFileRead") and mozFullPath but I haven't been able to get it to work. I believe it's deprecated anyway?

The other solution is to build an XUL-based UI and prompt for the file there somehow, but I would like to know for sure if there is anyway to get this to work in HTML.

First edit with small example code

I built a small sample extension to illustrate how I'm doing things.

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) ]
            });
        }
    });
}

data/load-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>

data/load-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");
}

As you can see in main.js, I used jquery-1.8.0.min.js, downloaded from the jQuery website.

Note: I also tried these without jQuery included as a content script when I opened the tab in main.js, but no luck.

The conclusion is that mozFullPath is indeed empty when I access it from JS embedded in the HTML page and I cannot find a way to access mozFullPath from jQuery, nor can I find a way to add a onchange handler in load-form.html that's defined in load-form.js

Second edit with onchange handler in the load-form.js content-script

I added the following code to load-form.js to catch the onchange event. I also removed the jQuery content script from main.js

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);

This still outputs an empty string for 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: 

Is there anyway to acquire the needed permissions? How can I get my hands on that full path? I need the full path so I can pass it to an application the extension launches. (There are workaround solutions where I can do without the full path, but they decrease the quality of the extension)


回答1:


fileInput.value property is meant to be accessible to web pages so it will only give you the file name, not the full path - web pages have no reason to know the full path on your machine. However, as a privileged extension you should be able to access the File.mozFullPath property. In this particular case you would do it like this:

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);
}

The big question of course is whether your code is allowed to access File.mozFullPath. I suspect that a content script in the Add-on SDK won't have the necessary privileges. The main extension code will have the privileges but getting to the input field from there is hard...



来源:https://stackoverflow.com/questions/12145622/firefox-extensions-and-full-file-paths-from-html-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!