firefox插件webextensions-特权代码、chrome代码、Gecko究竟是什么以及在哪里



在阅读有关File API的文章时,想要将数据从indexedDB数据库直接写入客户端磁盘,而不是首先在RAM中构建并保存一个大的blob以下载到磁盘,有一些基本项目我不理解。

在MDN文档中,可以找到以下两种语句:

在Gecko中,特权代码可以创建表示任何本地文件的File对象,而无需用户交互。

如果您想在chrome代码中使用DOMFileneneneba API,那么您可以不受限制地这样做。事实上,你有一个额外的功能:你可以在用户的计算机上创建指定文件路径的File对象。这只适用于特权代码,所以网络内容无法做到这一点

  1. 究竟在哪里编写chrome代码和/或Gecko专用代码?这超出了web扩展吗?我已经阅读并尝试过扩展;所以,我并没有特别询问如何访问它们

我不关心"正常"网页和服务器访问客户端磁盘。我知道为了保护个人是不允许的。

我感兴趣的是,在网络扩展和/或授予特殊权限的单独配置文件的帮助下,但不需要node.js、electronic等,一个知情的人可以通过浏览器离线完成他们应该在操作系统中而不是在浏览器中构建的事情。

  1. 换句话说,如果我只想使用浏览器来运行我的javascript代码,在我自己的机器上离线执行任务,那么编写的特权代码在哪里,可以访问这些类型的API,而这些API不受普通网页安全问题的影响?

  2. 在这些领域,它仍然是javascript还是C++?

谢谢。

这个老问题提供了一个指向其扩展的链接,其中包括文件API,该文件以某种方式写入磁盘,似乎提供了一种绕过创建大量数据的方法。它已经有六年的历史了,但似乎包含了所需的东西,至少是刚开始的时候。

我指的不是他们试图绕过indexedDB,而是使用这种类型的扩展可以将数据库中的每个对象直接写入客户端磁盘,而不必首先生成一个大的blob来下载。

尝试采用Andrew Swan的建议

我正在努力把这些碎片拼凑起来,但已经到了不确定如何继续的地步。我在一个扩展的后台脚本中写了下面的代码。在尝试采用Andrew Swan的建议时,计划是初始化一个文本.csv文件的GET请求,该文件被拦截并替换为从数据库中提取的数据,并由流过滤器写入GET请求。

首先,向一个伪造的url发出GET请求,并侦听响应,如下所示:

let request = new XMLHttpRequest();
request.open("GET", url );
request.setRequestHeader( "Content-Type", "text/csv" );
request.send(null);
request.onreadystatechange = () =>
{
portFromCS.postMessage( { 'func' : 'disp_result', 'args' : { 'msg' : "request.status :", 'value' : request.status + ' : ' + request.statusText} } );
};

其次,截取请求并写入GET,如下所示:

browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls : ["<all_urls>"] },
["blocking"] );

function listener( details ) 
{ 
let filter = browser.webRequest.filterResponseData(details.requestId);
let decoder = new TextDecoder("utf-8");
let encoder = new TextEncoder();
filter.onstart = event =>
{
let str = decoder.decode(event.data, {stream: true});
str = '' +
'HTTP/1.1 200 OK rn' +
'Content-Length: 17 rn' +
'Content-Type: text/csv rnrnrn' +
'This is a string.';

filter.write(encoder.encode(str));
filter.disconnect();
};
}

从request.onreadystatechange函数中的后台脚本发送的消息在内容脚本中接收,request.status为"0"。

使用filter.onstart是因为ondata事件永远不会激发,因为url是伪造的。此外,这意味着不会转换url中的数据,只会通过过滤器写入新数据。

str数据由请求写入和接收,但仅作为responseText,而不是作为响应标头。request.status保持为"0",而不是"200"。

它似乎无法更改响应标头,除非在onHeadersReceived中,这似乎永远不会发生,因为它是一个虚假的url。然而,我在一个真实的url上尝试了这一点,即使事件被触发,也抛出了一个错误webRequest.HttpHeaders不是函数。当时我在webRequest extraInfoSpec中有"responseHeaders"。

我的问题是:

  1. 是否可以编写一个响应标头,将request.status设置为"200",然后在检索到的小块中通过异步函数开始写入数据库数据?

  2. 标头响应的Content-Disposition部分是否可以设置为自动启动response.text的下载,并允许用户选择文件名和保存位置,并在数据从数据库中提取并通过filter.write()传递给GET请求时保持"打开"状态以继续写入文件?

谢谢。

结论

这是个好主意,但我认为这不可能,至少有两个原因。

一个是webRequest似乎根本没有拦截downloads.download()函数或任何下载事件;因此,您无法拦截下载,甚至需要一个ContentDisposition为"attachment"的事件来尝试用流写入。我可以拦截对锚标记href的强制点击,但除了onBeforeRequest之外,没有其他事件触发。

另一种情况是,在onHeadersReceived事件发生之前,不能修改响应标头,这意味着假URL必须返回一些内容。你不能在BeforeRequest上取消它。所以,这在离线时是行不通的。但是,即使您让它在线处理返回响应标头的现有URL,它也不会接受修改。我反复尝试修改响应标头,但它就是不起作用。我尝试了XMLHttpRequestGET,可以拦截触发的事件,但不能修改响应标头;因此,无论是否有文件,都不能将Content-Disposition设置为"attachment"来开始下载。我可以写信给它,但除非它要下载所写的内容,否则这是不好的。如果书面内容被放到网页上就可以了。

此外,如果您将URL重定向到webRequest可接受的URL之外的任何其他URL,则其他事件将不可拦截。因此,如果重定向到onBeforeRequest中的对象URL,则不会截获webRequest中的响应头阶段,而是可以在XMLHttpRequest的onreadystatechange事件中查看threm。

因此,结果是,即使MDN Web文档说这是可能的,响应标头似乎也无法修改。而且,使用awebRequest流过滤器来流式传输客户端上生成的或从indexedDB数据库中提取的数据,而不是构建一个大的blob进行下载,这种想法是行不通的,因为无法拦截下载或更改响应标头以触发下载,从而通过流过滤器写入。

不过这是一个有趣的想法。我仍然想知道,可以说,当数据被写入客户端并以块或块的形式传递时,下载是否会保持"打开"状态。也许,如果响应标头中说明如何传递和接收数据的部分也被修改,它也会起作用。

目前,我不再采取这种做法。其中一个Web文档或错误记录表明,计划允许拦截数据URL。也许,对于离线下载到客户端,这比伪造的URL更可取。

如果有人能做到这一点,请告诉我们。非常感谢。

几个术语:

  • "Gecko"是构建Firefox(以及Thunderbird等其他一些应用程序)的渲染引擎
  • 在此上下文中,"Chrome"是指浏览器的用户界面和功能,而不是浏览器显示的网页内容

在Firefox中,大部分浏览器chrome都是用Javascript实现的。实现用户界面的代码需要能够做普通网页无法做的事情(例如读取和写入本地文件系统)。因此,与作为网页一部分运行的Javascript相比,此代码以不同的权限运行。术语"特权代码"、"chrome特权代码"one_answers"Gecko特权代码"都是描述同一事物的不同方式:Javascript代码内置于浏览器中,可以访问网页所没有的功能。

在Firefox Quantum(57版)发布之前,Firefox扩展被允许运行特权Javascript代码。正如你可能想象的那样,这充满了安全性、性能和稳定性等方面的问题。使用WebExtensions,扩展现在以与常规web内容相同的权限级别运行(即,它们不以提升的权限执行)。一些浏览器功能通过扩展API向扩展公开。

因此,如果您对扩展可以做什么感兴趣,那么MDN上引用特权代码的任何文档实际上都是无关紧要的。目前,WebExtensions没有任何API可以允许您直接访问文件系统,但有一个开放的bug可以添加一些此功能。(这个错误已经存在了很长一段时间,但我怀疑很快就会有进展…)

最新更新