如何成功发出KeyboardEvent" Ctrl + T"在AddonSDK中

时间:2015-07-10 17:15:49

标签: javascript mouseevent simulation firefox-addon-sdk keyboard-events

我在Mozilla AddonSDK上的小任务上需要一些帮助。

我正在尝试在新选项卡中打开元素超链接,同时保留浏览器会话状态和任何JavaScript事件。

这意味着简单地抓住元素hreftab.open(href)不太可能提供理想的支持。

在元素上模拟 Ctrl + Left Mouse Click 以在新窗口中打开链接是理想的。

目前的尝试:

var tabs = require("sdk/tabs");

exports.testOpenTabCommand = function(assert, done) {
  var html = 'data:text/html,<html><title></title><body><a href="http://example.com">Click</a></body></html>';
  var script = [
    'self.port.on("openNewTab", function(selector){',
    '  var elm = document.querySelector(selector);',
    '  var ev = new KeyboardEvent(\'keydown\', {',
    '    ctrlKey: true,',
    '    key: \'t\'',
    '  });',
    '  elm.dispatchEvent(ev);',
    '  self.port.emit("tabOpened", true);',
    '})'
  ].join('');

  tabs.open({
    url: html,
    onLoad: function(tab) {
      var worker = tab.attach({
        contentScript: script,
        contentScriptWhen: 'ready'
      });
      worker.port.on('tabOpened', function (){
        // first tab is `about:blank`
        // second tab is the html above
        // third tab should be the clicked link
        assert.equal(tabs.length, 3);
        tab.close(function(){
          done();
        });
      });
      worker.port.emit('openNewTab', 'a');
    }
  });
};

require('sdk/test').run(exports);

感谢您的回答和评论。

谢谢。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,在我看来,当您使用tabs.open打开链接时,您只需要添加inBackground属性:

tabs.open({
  url: href,
  inBackground: true
});

如果情况并非如此,请告诉我们,我们会找出替代方案。

已更新(请参阅评论):

为了正确地合成击键和鼠标事件,特别是在带有e10s的新版Firefox中,我们需要做一些更复杂的事情,比如:

const tabs = require("sdk/tabs");
const { OS } = require("sdk/system/runtime");
const { getTabBrowserForTab } = require("sdk/tabs/utils");
const { viewFor } = require("sdk/view/core");

const { Cc, Ci } = require("chrome");

const remote = (f) => "data:application/javascript," + encodeURIComponent(`(${f}())`);

const globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]
                              .getService(Ci.nsIMessageListenerManager);

// it would be better put the code of the content function in an
// external module, and then use `framescript/manager` to load it
globalMessageManager.loadFrameScript(remote(function() {
  let domWindowUtils = this.content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIDOMWindowUtils);

  this.addMessageListener("myaddon:click", ({target, json}) => {
    let { accelKey, selector } = json;
    let node = this.content.document.querySelector(selector);
    let { top, left } = node.getBoxQuads()[0].bounds;

    // Simulate the click with the proper accel key
    let accel = domWindowUtils["MODIFIER_" + accelKey];
    domWindowUtils.sendMouseEvent("mousedown", left + 1, top + 1, 0, 1, 0, accel);
    domWindowUtils.sendMouseEvent("mouseup", left + 1, top + 1, 0, 1, accel);

    target.sendAsyncMessage("myaddon:clicked");
  });
}), true);

const synthesizeClickFor = (tab, selector) => new Promise((resolve) => {
  let { selectedBrowser } = getTabBrowserForTab(viewFor(tab));

  globalMessageManager.addMessageListener("myaddon:clicked", function listener({json}) {
    this.removeMessageListener("myaddon:clicked", listener);

    resolve();
  });

  let accelKey = OS === "Darwin" ? "META" : "CONTROL";
  selectedBrowser.messageManager.sendAsyncMessage("myaddon:click", { selector, accelKey });
});

exports.testOpenTabCommand = function(assert, done) {
  var html = "data:text/html,<html><title></title><body><a href='http://mozilla.org'>Click</a></body></html>";

  tabs.open({
    url: html,
    onLoad: function(tab) {
      synthesizeClickFor(tab, "a").then(() => {
        assert.ok(tabs.length, 3, "expected 3 tabs")

        // you need to close also the 3rd tab
        tabs[2].close(() => tab.close(done));
      });
    }
  });
};

require('sdk/test').run(exports);

这模拟左键单击加上Win / Linux上的加速键( ctrl (MODIFIER_CONTROL),OS X上的cmd⌘(MODIFIER_META))。您也可以以类似的方式合成密钥,请参阅:https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMWindowUtils#sendKeyEvent%28%29