请教如何写一个 firefox uc 下载脚本

我想参考 benzBrake 大佬的 downloadPlus_ff98.uc.js,写一个接管下载的 UC 脚本。

与 downloadPlus_ff98.uc.js 不同的是,我计划编译一个 dll,这个 uc 脚本除了把 url 和 Response header 输入给 dll,什么都不需要做。显示界面、判断是否下载,多线程下载之类的问题,都是这个 dll 负责。
因为我能写 dll,但不会 JavaScript。JavaScript 也能看懂一二,但 firefox 的内部 js 变量和回调也太复杂了。

但我研究了半天 downloadPlus_ff98.uc.js,也问了好几个 AI,都没有找到一个可行的方案。
我计划的这个脚本只有两个步骤,1,注册;2,收到回调后调用 dll。

uc 大佬能指点下怎么写吗?

进展:
从 downloadSoundPlay_Fx26.uc.js 这个脚本获取到最简易实现。在 onDownloadAdded 回调可以拦截事件。当前的问题是会显示一个"已取消"弹窗。
从这个事件似乎只能获取 url/size,无法获取到完整的返回头(不过有contentType数据)。

请问谁知道如何不显示"已取消"弹窗吗?

已取消弹窗真没见过,孤陋寡闻了?如果是界面一部分,inspect一下,用css隐藏得了,不然hook函数还得找半天

你是要拦截下载时间并在 Firefox 下载管理中实时显示进度还是只需要拦截啊

downloadPlus_ff98.uc.js 为了增加 about:config 开关改成模块已经变成屎山了。

不是独立弹窗,是下载按钮的小弹窗,我把下载按钮隐藏掉,就没有闪烁了。
现在算是打完收工了,效果图

1

论坛不支持gif,有点意外。而273KB gif转换出389KB avif,也有点意外。

代码:

	var downloadPlaySound = {
		_list: null,
		init: function sampleDownload_init() {
			if (!this._list)
			{
				globalThis.Downloads.getList(globalThis.Downloads.ALL).then(list => {
					this._list = list;
					return this._list.addView(this);
				}).then(null, Cu.reportError);
			}
		},

		onDownloadAdded: function (ui) {
			let url = ui.source.url;
			let uri = Services.io.newURI(url, null, null),
				cookies = Services.cookies.getCookiesFromHost(uri.host, {});

			console.log({
				name: "AutoHotkey DN", contentType: ui.contentType, currentBytes: ui.currentBytes, totalBytes: ui.totalBytes
				, size: ui.target.size, url: url, cookies: cookies.map((el) => el.name + '=' + el.value).join("; ")
			});

		},
	}

	downloadPlaySound.init();
let mimeInfo = DownloadsCommon.getMimeInfo(ui);
let refererInfo = ui.source.referrerInfo?.originalReferrer;

加上这两个信息应该够用了

还有

uri.schemeIs('data') 和 uri.schemeIs('blob') 要不要处理一下

多谢大佬。这两个是不是没有拦截的必要?

不知不觉,已经写的又臭又长了

onDownloadAdded: function (dl) {
	let target = dl.target;
	let path = target.path;
	let match = path.match(/[^\\\.]+$/);

	let ext;

	if (match)
	{
		ext = match[0].toLowerCase();
	}
	else
	{
		ext = null;
	}

	if (ext == "htm" || ext == "html")
		return;

	let url = dl.source.url;
	let uri = Services.io.newURI(url, null, null);


	if (uri.schemeIs('data') || uri.schemeIs('blob'))
		return;

	const buf = new TextEncoder().encode(JSON.stringify({
		name: "firefox_download_call"
		, contentType: dl.contentType
		, currentBytes: dl.currentBytes
		, startTime: dl.startTime
		, totalBytes: dl.totalBytes
		, dl_path: path
		, dl_ext: ext
		, dl_size: target.size
		, mimeInfo: DownloadsCommon.getMimeInfo(dl)
		, refererInfo: dl.source.referrerInfo?.originalReferrer
		, url: url
		, cookies: Services.cookies.getCookiesFromHost(uri.host, {})?.map((el) => el.name + '=' + el.value).join("; ")
	}));

	if (dll_fn(buf, buf.length) == 1)
		dl.cancel();

	console.log(dl);

},

data blob一般是js发起保存的内容,地址里就包含内容,没必要转发下载器了
啥时候搞出来发小众