如何让Firefox(或Chrome)读取PC的主机名或其他可分配的ID?

Tri*_*anK 2 firefox uniqueidentifier firefox-addon jsctypes signed-applet

我希望能够为 WAN中的每台PC分配唯一的名称(在主机名或本地文件中),以某种方式允许浏览器选择此信息.理由是我后来可以追踪到"交易X是在终端A上进行的",然后我知道它在B楼,C楼,D房等等.为什么我们需要这个,这是另一个话题.只是说我们确实需要这种识别.

到目前为止,我们已经使用了一个自定义插件(.dll + .xpi)来读取本地配置文件,并允许我们与LPT端口通信(再次,不要问:)),但这让我们陷入困境使用Firefox 3.6.17.在较新版本中不需要LPT内容,因此我们只需要识别我们的工作站,最好在那里存储其他一些只读配置信息.管理员只能改变的东西.

虽然我没有编写插件,但据我所知,在Firefox的后续版本中,所有这些都是不可能的.所以我们出去了:

  • 尝试编写只读取本地文件的Firefox扩展.在FF26之后(或者它是28?),API又一次改变了,我们根本无法使用这个功能(尽管我们联系了Mozilla开发人员,我们一丝不苟地遵循他们的指导方针)
  • 尝试编写Java Applet,但我不知道这是否是2015年的发展方向.它肯定早在21世纪初,当时我正在编写Java.小程序有效,但我担心JRE的性能/稳定性(我知道部署时我必须购买代码签名证书)
  • 考虑编写Flash插件而不是Java Applet.但是,我并不是真的喜欢Flash,我希望它能够被遗忘,因为它是值得的.但如果它能更好地完成我的工作,我会随时使用它

那么,你将如何解决这个任务呢?2015年实现这一目标的"推荐方式"是什么?

nma*_*ier 7

创建与最新Firefox版本兼容的Firefox附加组件并不难,并且可以在不涉及自定义DLL等的情况下完成.

我将使用一个简单的Add-on SDK插件,我刚刚创建它作为演示.

内容脚本

首先,一个人需要一个PageMod名字.内容脚本,将您喜欢的任何信息注入您想要的任何网站.

在下面的例子中,我将在hostInformation所有匹配的页面中注入一个新的全局变量*.example.org.请参阅有关如何针对您的用例进行优化的文档.

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",
});
Run Code Online (Sandbox Code Playgroud)

当然,./hostname它不是标准的SDK模块,因此我们必须在下一步中编写它.

获取主机名

无论你想传递什么信息,你都要自己弄明白.您提到从文件中读取该信息,因此io/fileOS.File可能是可行的选项,并且已经有大量的问题和答案已经详细介绍.

但是,我选择通过调用gethostname函数直接从OS获取主机名.它不能作为mozilla API AFAIK使用,但js-ctypes让我们与任何可动态加载的导出函数进行交互.gethostname.

现在只需要为操作系统加载正确的库(libc.so.6在Linux上,libc.{so,dylib}在*nix上包括OSX和一些嵌入式Linux以及ws2_32.dllWindows上).由于Firefox足够好已经WSAStartup为我们初始化了WinSock(),我们不需要关心它.

所以这是最后的hostname.js模块.

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();
Run Code Online (Sandbox Code Playgroud)

结论

cfx xpi在OSX Mavericks,Windows 7,Linux Arch 上测试了结果附加组件(),并通过导航到example.org打开Web控制台并检查是否有一个新的全局可访问的网站名称hostInformation包含实际的主机名来验证它的工作原理.该hostName物业.

与整个工作项目有一个github回购.