我在Mozilla AddonSDK上的小任务上需要一些帮助。
我正在尝试在新选项卡中打开元素超链接,同时保留浏览器会话状态和任何JavaScript事件。
这意味着简单地抓住元素href
和tab.open(href)
不太可能提供理想的支持。
在元素上模拟 Ctrl + 以在新窗口中打开链接是理想的。
目前的尝试:
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);
感谢您的回答和评论。
谢谢。
答案 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