我是扩展开发的新手。我试图在我的自举Firefox扩展中触发对keydown
事件的操作,但它似乎不起作用。我错过了什么吗?
这是我的bootstrap.js代码:
Cu.import("resource://gre/modules/Services.jsm");
function watchWindows(callback) {
function watcher(window) {
try {
let {documentElement} = window.document;
if (documentElement.getAttribute("windowtype") == "navigator:browser")
callback(window);
}
catch(ex) {}
}
function runOnLoad(window) {
window.addEventListener("load", function runOnce() {
window.removeEventListener("load", runOnce, false);
watcher(window);
}, false);
}
// Add functionality to existing windows
let windows = Services.wm.getEnumerator(null);
while (windows.hasMoreElements()) {
// Only run the watcher immediately if the window is completely loaded
let window = windows.getNext();
if (window.document.readyState == "complete")
watcher(window);
// Wait for the window to load before continuing
else
runOnLoad(window);
}
// Watch for new browser windows opening then wait for it to load
function windowWatcher(subject, topic) {
if (topic == "domwindowopened")
runOnLoad(subject);
}
Services.ww.registerNotification(windowWatcher);
// Make sure to stop watching for windows if we're unloading
unload(function() Services.ww.unregisterNotification(windowWatcher));
}
/**
* Save callbacks to run when unloading. Optionally scope the callback to a
* container, e.g., window. Provide a way to run all the callbacks.
*
* @usage unload(): Run all callbacks and release them.
*
* @usage unload(callback): Add a callback to run on unload.
* @param [function] callback: 0-parameter function to call on unload.
* @return [function]: A 0-parameter function that undoes adding the callback.
*
* @usage unload(callback, container) Add a scoped callback to run on unload.
* @param [function] callback: 0-parameter function to call on unload.
* @param [node] container: Remove the callback when this container unloads.
* @return [function]: A 0-parameter function that undoes adding the callback.
*/
function unload(callback, container) {
// Initialize the array of unloaders on the first usage
let unloaders = unload.unloaders;
if (unloaders == null)
unloaders = unload.unloaders = [];
// Calling with no arguments runs all the unloader callbacks
if (callback == null) {
unloaders.slice().forEach(function(unloader) unloader());
unloaders.length = 0;
return;
}
// The callback is bound to the lifetime of the container if we have one
if (container != null) {
// Remove the unloader when the container unloads
container.addEventListener("unload", removeUnloader, false);
// Wrap the callback to additionally remove the unload listener
let origCallback = callback;
callback = function() {
container.removeEventListener("unload", removeUnloader, false);
origCallback();
}
}
// Wrap the callback in a function that ignores failures
function unloader() {
try {
callback();
}
catch(ex) {}
}
unloaders.push(unloader);
// Provide a way to remove the unloader
function removeUnloader() {
let index = unloaders.indexOf(unloader);
if (index != -1)
unloaders.splice(index, 1);
}
return removeUnloader;
}
/* library */
const Utils = (function() {
const sbService = Cc['@mozilla.org/intl/stringbundle;1']
.getService(Ci.nsIStringBundleService);
const windowMediator = Cc['@mozilla.org/appshell/window-mediator;1']
.getService(Ci.nsIWindowMediator);
let setAttrs = function(widget, attrs) {
for (let [key, value] in Iterator(attrs)) {
widget.setAttribute(key, value);
}
};
let getMostRecentWindow = function(winType) {
return windowMediator.getMostRecentWindow(winType);
};
let exports = {
setAttrs: setAttrs,
getMostRecentWindow: getMostRecentWindow,
};
return exports;
})();
let ResponseManager = (function() {
const obsService = Cc['@mozilla.org/observer-service;1']
.getService(Ci.nsIObserverService);
const RESPONSE_TOPIC = 'http-on-examine-response';
let observers = [];
let addObserver = function(observer) {
try {
obsService.addObserver(observer, RESPONSE_TOPIC, false);
} catch(error) {
trace(error);
}
observers.push(observers);
};
let removeObserver = function(observer) {
try {
obsService.removeObserver(observer, RESPONSE_TOPIC, false);
} catch(error) {
trace(error);
}
};
let destory = function() {
for (let observer of observers) {
removeObserver(observer);
}
observers = null;
};
let exports = {
addObserver: addObserver,
removeObserver: removeObserver,
destory: destory,
};
return exports;
})();
/* main */
let ReDisposition = function() {
let respObserver;
respObserver = {
observing: false,
observe: function(subject, topic, data) {
try {
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
this.override(channel);
} catch(error) {
trace(error);
}
},
start: function() {
if (!this.observing) {
ResponseManager.addObserver(this);
this.observing = true;
}
},
stop: function() {
if (this.observing) {
ResponseManager.removeObserver(this);
this.observing = false;
}
},
refresh: function() {
this.start();
},
re: /^\s*attachment/i,
re2: /^\s*text/i,
override: function(channel) {
if(disablePlugin)
{
try {
let contentHeader;
contentHeader = channel.getResponseHeader('Content-Type');
if (this.re2.test(contentHeader))
return;
channel.setResponseHeader('Content-Disposition', "attachment", false);
return;
}
catch(error) {
return;
}
}
// check if have header
let header;
try {
header = channel.getResponseHeader('Content-Disposition');
} catch(error) {
return;
}
// override to inline
if (this.re.test(header)) {
channel.setResponseHeader('Content-Disposition', header.replace(this.re, "inline"), false);
return;
}
}
};
let initialize = function() {
respObserver.refresh();
};
let destory = function() {
respObserver.stop();
};
let exports = {
initialize: initialize,
destory: destory,
}
return exports;
};
/* bootstrap entry points */
let reDisposition;
var disablePlugin = false;
let install = function(data, reason) {};
let uninstall = function(data, reason) {};
let startup = function(data, reason) {
reDisposition = ReDisposition();
reDisposition.initialize();
function onwindow(window) {
function onkeydown(e) {
if (e.keyCode == 70)
{
disablePlugin = true;
}
else
{
disablePlugin = false;
}
}
function onkeyup(e) {
disablePlugin = false;
}
// Bootstrapped add-ons need to clean up after themselves!
function onunload() {
window.removeEventListener("keydown", onkeypress);
window.removeEventListener("keyup", onkeypress);
}
window.addEventListener("keydown", onkeydown);
window.addEventListener("keyup", onkeyup);
unload(onunload, window);
}
watchWindows(onwindow);
};
let shutdown = function(data, reason) {
reDisposition.destory();
};
答案 0 :(得分:3)
window
范围内没有bootstrap.js
。 bootstrap.js
本质上是一个独立的代码模块(在沙箱中运行,但这只是一个实现细节)。它每个应用程序只运行一次,而不是每个窗口运行一次。
在开发bootstrapped add-ons时,您必须枚举现有的并自己观察新窗口并根据需要“附加”它们。参见例如watchWindows
boilerplate。
这是一个例子。它假设您正在使用watchWindows
样板:
function startup(data, reason) {
// Callback function called for each browser window (browser.xul)
function onwindow(window) {
function onkeydown(e) {
// XXX: Your code here.
}
// Bootstrapped add-ons need to clean up after themselves!
function onunload() {
window.removeEventListener("keydown", onkeypress);
}
window.addEventListener("keydown", onkeydown);
unload(onunload, window);
}
// Will also fire for existing windows once and upon each new window.
watchWindows(onwindow);
}
当你刚接触Firefox附加组件,XUL / XPCOM和mozilla平台时,开发自举的附加组件并不是我推荐的。您可能应该查看基于XUL overlay的附加组件或Add-on SDK。