keydown事件在bootstrapped Firefox插件中不起作用

时间:2013-09-11 17:09:15

标签: javascript firefox-addon key

我是扩展开发的新手。我试图在我的自举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();
};

1 个答案:

答案 0 :(得分:3)

window范围内没有bootstrap.jsbootstrap.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。