使用firefox addon sdk API阻止关闭选项卡

时间:2014-10-27 13:13:52

标签: firefox firefox-addon firefox-addon-sdk

我正在寻找一种方法来防止使用firefox插件sdk关闭选项卡。

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:3)

好的男人,这就是你想要的。以前的版本是为了看看我是否可以在关闭标签时触发onb​​eforeunload触发,但我无法弄明白。

以下是如何做到的: 我们覆盖removeTab函数。遵循指导原则:MDN :: Overriding/Extending/Amending existing functions - Alternative: Replace + Function.apply()

  // Keep a reference to the original function.
  var _original = gBrowser.removeTab;

  // Override a function.
  gBrowser.removeTab = function() {
    // Execute some action before the original function call.
    if (window.myAddonIsInstalled = true) {
        var closeit = confirm('are you sure you want to close the tab?')

        // Execute original function.
        if (closeit) {
            var rv = _original.apply(gBrowser, arguments);
        }

        // return the original result
        return rv;
    } else {
        var rv = _original.apply(gBrowser, arguments);
        // return the original result
        return rv;
    }
  };

卸载你的插件时,请确保将window.myAddonIsInstalled的全局属性设置为false。因为这是根据该文章禁用您的功能的推荐方法。

答案 1 :(得分:2)

这就是诀窍。可以复制粘贴到暂存器并运行(当然环境>浏览器)

改编自此处:https://gist.github.com/Noitidart/9406437来自:https://gist.github.com/Noitidart/51b62b356b3a21010a4d

它使用onbeforeunload的东西,并在加载标签时将其附加到所有顶级窗口,也打开包含事件监听器TabOpen

的标签页

如果要撤消所做的更改,请运行windowListener.unregister()我在窗口底部给出了注释掉的示例。但是如果你从暂存器中运行取消注册,请确保先删除顶部的内容,否则它不会取消注册在PREVIOUS运行中注册的内容,它将取消注册当前运行中注册的内容。

不是为addon-sdk量身定做的,但你可以将其放入你的插件sdk中,但最重要的是你需要添加var {Cu, Ci} = require('chrome'); Cu.import('resource://gre/modules/Services.jsm');

此代码确实修改了警告模式的文本。

它没有检查是否已经注册了其他onbeforeunload,它是一个ez检查你应该添加它。如果需要帮助让我知道。

try {
    windowListener.unregister();
} catch (ignore) {}

var ignoreFrames = true;

function beforeUnloader(e) {
    //console.log('beforeUnload e:', e); //http://i.imgur.com/AbUn20J.png
    var DOMWindow = e.target.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
                                                     .getInterface(Ci.nsIWebNavigation)
                                                     .QueryInterface(Ci.nsIDocShellTreeItem)
                                                     .rootTreeItem
                                                     .QueryInterface(Ci.nsIInterfaceRequestor)
                                                     .getInterface(Ci.nsIDOMWindow);
    DOMWindow.setTimeout(function() {
        try {
            if (DOMWindow.gBrowser) {
                var linkedBrowser = DOMWindow.gBrowser.getBrowserForDocument(e.target);
            } else {
                var linkedBrowser = DOMWindow.document;
            }
            var modal = linkedBrowser.parentNode.querySelector('tabmodalprompt');
            var warnTxtNode = modal.ownerDocument.getAnonymousElementByAttribute(modal, 'anonid', 'info.body').firstChild;
            warnTxtNode.textContent = 'rawr';
        } catch (ex) {
            console.warn('excpetion occured when trying to modify warn text, ex:', ex);
        }
    }, 10);
    return 'dummy text so it shows unloader'; //see third bullet here: https://developer.mozilla.org/en-US/docs/WindowEventHandlers.onbeforeunload it says "Note that in Firefox 4 and later the returned string is not displayed to the user. Instead, Firefox displays the string "This page is asking you to confirm that you want to leave - data you have entered may not be saved." See bug 588292."
};

function addInjections(theDoc) {
    theDoc.defaultView.onbeforeunload = beforeUnloader;
}

function removeInjections(theDoc, skipChecks) {
  theDoc.defaultView.onbeforeunload = null;
}

function tabopened(e) {
    //console.info('tabopened: e:', e); //http://i.imgur.com/Re0Wmfn.png
    addInjections(e.target.linkedBrowser.contentDocument);
}

function listenPageLoad(event) {
    var win = event.originalTarget.defaultView;
    var doc = win.document;
    Cu.reportError('page loaded loc = ' + doc.location);
    if (win.frameElement) {
        //its a frame
        Cu.reportError('its a frame');
        if (ignoreFrames) {
            return;//dont want to watch frames
        }
    }
    addInjections(doc);
}

/*start - windowlistener*/
var windowListener = {
    //DO NOT EDIT HERE
    onOpenWindow: function (aXULWindow) {
        // Wait for the window to finish loading
        let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        aDOMWindow.addEventListener("load", function () {
            aDOMWindow.removeEventListener("load", arguments.callee, false);
            windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
        }, false);
    },
    onCloseWindow: function (aXULWindow) {},
    onWindowTitleChange: function (aXULWindow, aNewTitle) {},
    register: function () {
        // Load into any existing windows
        let XULWindows = Services.wm.getXULWindowEnumerator(null);
        while (XULWindows.hasMoreElements()) {
            let aXULWindow = XULWindows.getNext();
            let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
            windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
        }
        // Listen to new windows
        Services.wm.addListener(windowListener);
    },
    unregister: function () {
        // Unload from any existing windows
        let XULWindows = Services.wm.getXULWindowEnumerator(null);
        while (XULWindows.hasMoreElements()) {
            let aXULWindow = XULWindows.getNext();
            let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
            windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
        }
        //Stop listening so future added windows dont get this attached
        Services.wm.removeListener(windowListener);
    },
    //END - DO NOT EDIT HERE
    loadIntoWindow: function (aDOMWindow, aXULWindow) {
        if (!aDOMWindow) {
            return;
        }
        if (aDOMWindow.gBrowser) {
            aDOMWindow.gBrowser.addEventListener('DOMContentLoaded', listenPageLoad, false);
            if (aDOMWindow.gBrowser.tabContainer) {
                //has tabContainer
                aDOMWindow.gBrowser.tabContainer.addEventListener("TabOpen", tabopened, false);
                //start - go through all tabs in this window we just added to
                var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
                for (var i = 0; i < tabs.length; i++) {
                    Cu.reportError('DOING tab: ' + i);
                    var tabBrowser = tabs[i].linkedBrowser;
                    var win = tabBrowser.contentWindow;
                    loadIntoContentWindowAndItsFrames(win);
                }
                //end - go through all tabs in this window we just added to
            } else {
                //does not have tabContainer
                var win = aDOMWindow.gBrowser.contentWindow;
                loadIntoContentWindowAndItsFrames(win);
            }
        } else {
            //window does not have gBrowser
        }
    },
    unloadFromWindow: function (aDOMWindow, aXULWindow) {
        if (!aDOMWindow) {
            return;
        }
        if (aDOMWindow.gBrowser) {
            aDOMWindow.gBrowser.removeEventListener('DOMContentLoaded', listenPageLoad, false);
            if (aDOMWindow.gBrowser.tabContainer) {
                //has tabContainer
                aDOMWindow.gBrowser.tabContainer.removeEventListener("TabOpen", tabopened, false);
                //start - go through all tabs in this window we just added to
                var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
                for (var i = 0; i < tabs.length; i++) {
                    Cu.reportError('DOING tab: ' + i);
                    var tabBrowser = tabs[i].linkedBrowser;
                    var win = tabBrowser.contentWindow;
                    unloadFromContentWindowAndItsFrames(win);
                }
                //end - go through all tabs in this window we just added to
            } else {
                //does not have tabContainer
                var win = aDOMWindow.gBrowser.contentWindow;
                unloadFromContentWindowAndItsFrames(win);
            }
        } else {
            //window does not have gBrowser
        }
    }
};
/*end - windowlistener*/

function loadIntoContentWindowAndItsFrames(theWin) {
    var frames = theWin.frames;
    var winArr = [theWin];
    for (var j = 0; j < frames.length; j++) {
        winArr.push(frames[j].window);
    }
    Cu.reportError('# of frames in tab: ' + frames.length);
    for (var j = 0; j < winArr.length; j++) {
        if (j == 0) {
            Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
        } else {
            Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
        }
        var doc = winArr[j].document;
        //START - edit below here
        addInjections(doc);
        if (ignoreFrames) {
            break;
        }
        //END - edit above here
    }
}

function unloadFromContentWindowAndItsFrames(theWin) {
    var frames = theWin.frames;
    var winArr = [theWin];
    for (var j = 0; j < frames.length; j++) {
        winArr.push(frames[j].window);
    }
    Cu.reportError('# of frames in tab: ' + frames.length);
    for (var j = 0; j < winArr.length; j++) {
        if (j == 0) {
            Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
        } else {
            Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
        }
        var doc = winArr[j].document;
        //START - edit below here
        removeInjections(doc);
        if (ignoreFrames) {
            break;
        }
        //END - edit above here
    }
}

windowListener.register();