gpt4 book ai didi

javascript - 如何从 Firefox 附加 SDK 扩展启动正常下载

转载 作者:行者123 更新时间:2023-12-01 02:13:57 26 4
gpt4 key购买 nike

我正在为 Firefox 开发附加 SDK 扩展。我发现我需要能够像用户请求一样启动下载,即显示正常的文件保存对话框或将文件保存到用户喜欢的任何位置,因为它可以在首选项>内容下进行配置。

每个关于下载的帖子或文档似乎只考虑了我知道在哪里下载文件的情况,但这不是我在这种情况下需要的。在这种情况下,它需要就像用户开始下载一样。

如何做到这一点,最好是通过 SDK 的方法?

最佳答案

好吧,你可以启动一个实际的保存。

从您的代码启动保存链接:
在上下文菜单中,oncommand 值为 gContextMenu.saveLink(); . saveLink() 定义在: chrome://browser/content/nsContextMenu.js .它会做一些家务,然后调用 saveHelper() which is defined in the same file .您可以使用适当的参数调用 saveHelper() 。它包含在 chrome://browser/content/web-panels.xul 的面板中和:

<script type="application/javascript" 
src="chrome://browser/content/nsContextMenu.js"/>

然后 gContextMenu chrome://browser/content/browser.js 中声明的变量如 null被安排了:
gContextMenu = new nsContextMenu(this, event.shiftKey);
在上下文菜单的 onpopupshowing 事件处理程序中。它返回到:
'gContextMenu = null;'
onpopuphiding事件处理程序。

如果你想在自己的代码中使用它,你可以这样做:
let urlToSave = "http://stackoverflow.com/questions/26694442";
let linkText = "Some Link text";

// Add a "/" to un-comment the code appropriate for your add-on type.
/* Overlay and bootstrap:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
//*/
/* Add-on SDK:
var {Cc, Ci, Cr} = require("chrome");
//*/

if (window === null || typeof window !== "object") {
//If you do not already have a window reference, you need to obtain one:
// Add a "/" to un-comment the code appropriate for your add-on type.
/* Add-on SDK:
var window = require('sdk/window/utils').getMostRecentBrowserWindow();
//*/
/* Overlay and bootstrap (from almost any context/scope):
var window=Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
//*/
}

//Create an object in which we attach nsContextMenu.js.
// It needs some support properties/functions which
// nsContextMenu.js assumes are part of its context.
let contextMenuObj = {
makeURI: function (aURL, aOriginCharset, aBaseURI) {
var ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
return ioService.newURI(aURL, aOriginCharset, aBaseURI);
},
gPrefService: Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService)
.QueryInterface(Ci.nsIPrefBranch),
Cc: Cc,
Ci: Ci,
Cr: Cr
};

Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/nsContextMenu.js"
,contextMenuObj);

//Re-define the initMenu function, as there is not a desire to actually
// initialize a menu.
contextMenuObj.nsContextMenu.prototype.initMenu = function() { };

let myContextMenu = new contextMenuObj.nsContextMenu();
//Save the specified URL
myContextMenu.saveHelper(urlToSave,linkText,null,true,window.content.document);

替代使用 loadSubScript 加载 nsContextMenu.js :
我的偏好是使用 loadSubScript 从 nsContextMenu.js 加载 saveHelper 代码.这使代码在 future Firefox 版本中所做的任何更改都是最新的。但是,它引入了您使用来自非官方 API 的函数的依赖性。因此,它可能会在 future 的 Firefox 版本中以某种方式发生变化,并且需要在您的附加组件中进行更改。另一种方法是复制 saveHelper()扩展程序中的代码。它定义如下:
// Helper function to wait for appropriate MIME-type headers and
// then prompt the user with a file picker
saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc) {
// canonical def in nsURILoader.h
const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;

// an object to proxy the data through to
// nsIExternalHelperAppService.doContent, which will wait for the
// appropriate MIME-type headers and then prompt the user with a
// file picker
function saveAsListener() {}
saveAsListener.prototype = {
extListener: null,

onStartRequest: function saveLinkAs_onStartRequest(aRequest, aContext) {

// if the timer fired, the error status will have been caused by that,
// and we'll be restarting in onStopRequest, so no reason to notify
// the user
if (aRequest.status == NS_ERROR_SAVE_LINK_AS_TIMEOUT)
return;

timer.cancel();

// some other error occured; notify the user...
if (!Components.isSuccessCode(aRequest.status)) {
try {
const sbs = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService);
const bundle = sbs.createBundle(
"chrome://mozapps/locale/downloads/downloads.properties");

const title = bundle.GetStringFromName("downloadErrorAlertTitle");
const msg = bundle.GetStringFromName("downloadErrorGeneric");

const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
promptSvc.alert(doc.defaultView, title, msg);
} catch (ex) {}
return;
}

var extHelperAppSvc =
Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
getService(Ci.nsIExternalHelperAppService);
var channel = aRequest.QueryInterface(Ci.nsIChannel);
this.extListener =
extHelperAppSvc.doContent(channel.contentType, aRequest,
doc.defaultView, true);
this.extListener.onStartRequest(aRequest, aContext);
},

onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext,
aStatusCode) {
if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
// do it the old fashioned way, which will pick the best filename
// it can without waiting.
saveURL(linkURL, linkText, dialogTitle, bypassCache, false,
doc.documentURIObject, doc);
}
if (this.extListener)
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
},

onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext,
aInputStream,
aOffset, aCount) {
this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
aOffset, aCount);
}
}

function callbacks() {}
callbacks.prototype = {
getInterface: function sLA_callbacks_getInterface(aIID) {
if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
// If the channel demands authentication prompt, we must cancel it
// because the save-as-timer would expire and cancel the channel
// before we get credentials from user. Both authentication dialog
// and save as dialog would appear on the screen as we fall back to
// the old fashioned way after the timeout.
timer.cancel();
channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
}

// if it we don't have the headers after a short time, the user
// won't have received any feedback from their click. that's bad. so
// we give up waiting for the filename.
function timerCallback() {}
timerCallback.prototype = {
notify: function sLA_timer_notify(aTimer) {
channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
return;
}
}

// set up a channel to do the saving
var ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var channel = ioService.newChannelFromURI(makeURI(linkURL));
if (channel instanceof Ci.nsIPrivateBrowsingChannel) {
let docIsPrivate = PrivateBrowsingUtils.isWindowPrivate(doc.defaultView);
channel.setPrivate(docIsPrivate);
}
channel.notificationCallbacks = new callbacks();

let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;

if (bypassCache)
flags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;

if (channel instanceof Ci.nsICachingChannel)
flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;

channel.loadFlags |= flags;

if (channel instanceof Ci.nsIHttpChannel) {
channel.referrer = doc.documentURIObject;
if (channel instanceof Ci.nsIHttpChannelInternal)
channel.forceAllowThirdPartyCookie = true;
}

// fallback to the old way if we don't see the headers quickly
var timeToWait =
gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(new timerCallback(), timeToWait,
timer.TYPE_ONE_SHOT);

// kick off the channel with our proxy object as the listener
channel.asyncOpen(new saveAsListener(), null);
}

关于javascript - 如何从 Firefox 附加 SDK 扩展启动正常下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26694442/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com