【问题标题】:How to get the right-clicked tab's URL in a Firefox add-on如何在 Firefox 插件中获取右键单击选项卡的 URL
【发布时间】:2016-05-07 18:16:11
【问题描述】:

我正在编写一个 Firefox 扩展程序,它将菜单项添加到浏览器的选项卡上下文菜单中,以将选项卡的 URL 发送到 Web 服务。我的菜单项有一个 command 事件侦听器,它在选择菜单项时触发并且工作正常。

我遇到的麻烦是根据我收到的事件确定右键单击了哪个选项卡。从菜单项本身(这是command 事件的目标)到选项卡似乎没有一条简单的路径,因为选项卡上下文菜单不是 XUL-land 中选项卡的子项。当然,我不能只获取当前选项卡,因为用户可能右键单击了非活动选项卡。

我目前使用的解决方案是在每个选项卡上放置一个contextmenu 事件处理程序,将选项卡的URL 存储在一个全局变量中,并在我的command 事件处理程序中使用这个全局变量。这很好用,而且我对全局变量有点放心,因为在物理上不可能同时调出多个上下文菜单。

但是有更好的方法吗?我想用一个包含 URL 的闭包来更新我的 command 事件处理程序,但这样做的缺点是需要在添加新的事件处理程序之前删除旧的事件处理程序,这只会使事情变得更加复杂。

我当前的代码如下所示:

var tabs = require("sdk/tabs");
var xultabs = require("sdk/tabs/utils");
var viewFor = require("sdk/view/core").viewFor;

var itemid = "my-extension-name";
var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

// global variable to hold tab URL and function to set it on right-click of tab
taburl = "";
function getTabURL(e) { taburl = xultabs.getTabURL(e.target); }

tabs.on('ready', function(tab) {
  // set up event listener to get tab URL when tab is right-clicked
  let vtab = viewFor(tab);
  vtab.addEventListener("contextmenu", getTabURL); 

  // add our context menu item if it's not already there
  let doc = viewFor(tab.window).document;
  if (!doc.getElementById(itemid)) {
    let menu = doc.getElementById("tabContextMenu");
    let item = doc.createElementNS(xulns, "menuseparator");
    menu.appendChild(item);
    item = doc.createElementNS(xulns, "menuitem");
    item.setAttribute("label", "My Menu Item");
    item.setAttribute("id", itemid);
    item.addEventListener("command", function() { pushURL(taburl) });
    menu.appendChild(item);
  }
});

function pushURL(url) {
   // pushes the URL to the service
}

【问题讨论】:

    标签: javascript firefox-addon firefox-addon-sdk xul firefox-addon-webextensions


    【解决方案1】:

    当显示上下文菜单时,您可以通过以下操作找出触发弹出窗口的元素:

    e.target.ownerDocument.popupNode
    

    这可能很有用,但实际上您只需要ownerDocument.defaultView

    我认为甚至还有一个 e.view 属性来保存浏览器窗口。

    例如:

    function contextMenuShowing(e) {
        console.log('context menu showing', 'popupNode:', e.target.ownerDocument.popupNode);
        var currentWindow = e.target.ownerDocument.defaultView; // can try var currentWindow = e.view;
        if (currentWindow.gBrowser) {
              var tabURL  = gBrowser.selectedBrowser.currentURI;
        }
    }
    
    cToolbarContextMenu.addEventListener('popupshowing', contextMenuShowing, false);
    

    另一种方法,是因为右键单击,这显然意味着窗口被聚焦。所以你可以这样做:

    const { getMostRecentBrowserWindow } = require('sdk/window/utils');
    
    cToolbarContextMenu.addEventListener('popupshowing', function() {
        var currentWindow = getMostRecentBrowserWindow();
        if (currentWindow.gBrowser) {
             var tabURL = currentWindow.gBrowser.selectedBrowser.currentURI.spec;
        }
    }, false);
    

    【讨论】:

    • selectedBrowser 不幸的是没有帮助,因为它总是指可见选项卡,不一定是右键单击的选项卡。我可以毫不费力地找出 active 选项卡的 URL,有几种方法可以做到这一点。我需要知道菜单命令实际针对的那个。
    • 原来require("sdk/tabs/utils").getTabURL(e.target.ownerDocument.popupNode)是魔法咒语。
    • 哦,我现在明白了,您正在右键单击标签元素!太棒了,popupNode 就可以了!感谢分享和采纳!
    • @kindall 顺便说一句,幕后发生的事情是 xul 的东西,我认为 popupNode 是标签元素本身。所以它正在做的是popupNode.linkedBrowser.currentURI.path :) 如果你想做其他事情,比如发送 e10s 安全消息,你可以做popupNode.linkedBrowser.messageManager.sendAsyncMessage 等)
    • 啊,我们走了,我可以删除对 tabs/utils 的依赖了。
    猜你喜欢
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多