I'm needing some help on a small task on Mozilla AddonSDK.
I am attempting to open the element hyperlink in a new tab while retaining browser session state and any JavaScript events.
This would mean a simple, grabbing of the element's href
and tab.open(href)
would be unlikely to provide ideal support.
It would be ideal to simulate the Ctrl+ on a element to open the link in a new window.
Current attempt:
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);
I appreciate your answers and comments.
Thank you.
If I understood properly, it seems to me that you just need to add inBackground
property when you open the link using tabs.open:
tabs.open({
url: href,
inBackground: true
});
If that is not the case, let me know and we'll figure out alternatives.
Updated (see the comments):
In order to properly synthetize keystrokes and mouse events, especially in the new version of Firefox with e10s, we need to do something more complex, like:
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);
This simulate the left click plus the accel key (ctrl (MODIFIER_CONTROL) on Win / Linux, cmd ⌘ (MODIFIER_META) on OS X). You can also synthetize keys in a similar way, see: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMWindowUtils#sendKeyEvent%28%29