How can I allow Firefox (or Chrome) to read a PC's hostname or other assignable ID?

强颜欢笑 提交于 2019-12-22 18:14:47

问题


I want to be able to assign a unique name to each PC in a WAN (either in the hostname or in a local file) and somehow allow the browser to pick this information up. The rationale is that I can later trace that "transaction X was carried out on terminal A", which I then know that it is on building B, floor C, room D and so on. Why we need this, it's another topic. Just say we do need this kind of identification for good reason.

So far we've used a custom plugin (.dll + .xpi) that would read a local config file and also allow us to talk to the LPT port (again, don't ask :) ), but that has left us stuck with Firefox 3.6.17. The LPT stuff won't be needed in the newer version, so we're left with identifying our workstations and preferably storing some other read-only config info in there. Something that an admin will only be able to change.

While I didn't write that plugin, I understand that in the later versions of Firefox all these are impossible. So we went out and:

  • tried writing a Firefox extension that will only read a local file. After FF26 (or was it 28?) the API changed once again and we simply can't get this functionality to work (although we contacted Mozilla devs and we followed their guidelines meticulously)
  • tried writing a Java Applet, but I don't know if that is the way to go in 2015. It certainly was back in the early 2000s, when I was writing Java. The applet works, but I'm concerned about the performance/stability of the JRE (I know that for deployment I'll have to buy a code-signing certificate)
  • thought about writing a Flash plugin instead of a Java Applet. But then, I'm not really fond of Flash and I wish it to whither away into oblivion, because it so deserves it. But if it'll do my work better, I'll use it anytime

So, how would you go about solving this task? What is the "recommended way" to do this in 2015?


回答1:


Creating a Firefox add-on compatible with the recent Firefox versions wouldn't be that hard, and can be done without involving custom DLLs and the like.

I'll be using a simple Add-on SDK add-on I just created as a demonstration.

Content Script

First, one needs a PageMod aka. content-script that will inject whatever information you like into whatever website you want.

In the following example I will be injecting a new global hostInformation variable into all pages matching *.example.org. Consult the docs on how to refine that for your use case.

main.js

const {PageMod} = require("sdk/page-mod");

function contentScript() {
    // Usually, you'd but this function body into a new file ;)

    // Just makes all of contentScriptOptions available to the real website,
    // as the |hostInformation| objects.
    unsafeWindow.hostInformation = cloneInto(self.options, unsafeWindow);
}

PageMod({
    include: "*.example.org",
    contentScript: "(" + contentScript.toSource() + ")()",
    contentScriptOptions: require("./hostname"),
    contentScriptWhen: "start",
});

Of course, ./hostname isn't a standard SDK module, so we'll have to write that in the next step.

Getting the host name

Whatever information you want to pass, you have to figure out for yourself. You mentioned reading that information from a file, so io/file or OS.File might be viable options for that, and have tons of questions and answers already going into more detail.

I opted, however, for getting the hostname from the OS directly by means of calling the gethostname function. It isn't available as a mozilla API AFAIK, but js-ctypes let's us interact with any dynamically-loadable, exported function incl. gethostname.

Now it is just a matter of loading the right library for a OS (libc.so.6 on Linux, libc.{so,dylib} on *nix incl. OSX and some embedded Linux and ws2_32.dll on Windows). Since Firefox was nice enough to already have initialized WinSock (WSAStartup) for us, we don't need to care about it.

So here is the final hostname.js module.

hostname.js

const {Ci, Cc, Cu} = require("chrome"); // for js-ctypes
Cu.import("resource://gre/modules/ctypes.jsm");

function getHostName() {
    function loadLibrary() {
        const candidates = ["libc.so.6", ctypes.libraryName('c'), ctypes.libraryName('ws2_32')];
        for (var cand of candidates) {
            try {
                return ctypes.open(cand);
            }
            catch (ex) {}
        }
    }
    const library = loadLibrary();
    if (!library) {
        return null;
    }
    try {
        const gethostname = library.declare(
            "gethostname",
            ctypes.default_abi,
            ctypes.int, // return value
            ctypes.char.ptr, // [out] name,
            ctypes.int // [in] namelen
            );
        let addrbuf = (ctypes.char.array(1024))();
        if (gethostname(addrbuf, 1024)) {
            throw Error("ctypes call failed");
        }
        let rv = addrbuf.readString();
        console.log("got hostname", rv);
        return rv;
    }
    catch (ex) {
        console.error("Failed to get host name", ex);
        return null;
    }
    finally {
        library.close();
    }
}

exports.hostName = getHostName();

Conclusion

I tested the resulting add-on (cfx xpi) on OSX Mavericks, Windows 7, Linux Arch, and verified it works by navigating to example.org, opening the web console and checking that there is a new global accessible by the website named hostInformation which contains the actual hostname in the hostName property.

Have a github repo with the whole, working project.



来源:https://stackoverflow.com/questions/28223087/how-can-i-allow-firefox-or-chrome-to-read-a-pcs-hostname-or-other-assignable

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