从Firefox扩展中替换网站背景颜色?

时间:2011-06-20 11:26:12

标签: firefox firefox-addon

我正在构建一个Firefox扩展程序,除其他外,需要在一个网站上替换正文背景颜色。我对主要在Firefox 4上工作的方法感兴趣,与旧版Firefox的兼容性并不重要。

我已经在Chrome,Opera和Safari扩展程序中完成了这项工作,但经过几个小时的阅读和尝试各种内容后,我无法在Firefox扩展程序中执行相同的操作。请帮忙。

我提前为这么长的帖子道歉,我试图尽可能地缩短它。

到目前为止我尝试了什么:


1。 DOMContentLoaded

这种方法确实取代了颜色但是它做得太晚了,Firefox首先显示原始颜色,然后用我的颜色替换它。看来我的功能直到该网站的adsense或facebook小部件完成他们的工作才会执行。如果用户有某种广告拦截器而不是正常工作,但这显然对我的扩展没有任何意义。

gBrowser.addEventListener("DOMContentLoaded", my_function, true);

my_function: function(event)
{
    var doc = event.originalTarget;
    doc.body.style.background = "#f00";
}


2。观察员

我尝试了这三种观察者类型:

  • 铬文档全局创建
  • 内容文件全局创建
  • 文档元素插入

我无法从任何列出的观察者中访问body元素。

Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService).addObserver(
{
    observe: function(aSubject, aTopic, aData)
    {
        var doc = aSubject;
        // doc.location     - contains the url
        // doc          - [object XrayWrapper [object Window]]
        // doc.document     - [object XrayWrapper [object HTMLDocument]]
        // doc.document.body    - null
        doc.document.body.style.background = "#f00";    // this will obviously not work because body is not yet created or I'm looking in the wrong place
    }
}, "content-document-global-created", false);


3。带有NOTIFY_STATE_DOCUMENT

的WebProgressListener

从STATE_TRANSFERRING我无法访问正文,从STATE_STOP开始为时已晚。

browser.webProgress.addProgressListener(this, browser.webProgress.NOTIFY_STATE_DOCUMENT);

onStateChange: function(aWebProgress, aRequest, aFlag, aStatus)
{
    var doc = aWebProgress.DOMWindow;

    if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_TRANSFERRING)
    {
        // doc.document.body    - null
        doc.document.body.style.background = "#f00";    // again this will obviously not work because body is not yet created or I'm looking in the wrong place
    }
    if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP)
    {
        // doc.document.body    - [object XrayWrapper [object HTMLBodyElement]]
        doc.document.body.style.background = "#f00";    // works but the same way DOMContentLoaded does, too slow
    }
}


4。带有NOTIFY_PROGRESS(或NOTIFY_STATE_REQUEST或NOTIFY_STATE_ALL)的WebProgressListener

这确实会立即改变颜色,但我为用户访问的每个网站和资源都获得了很多事件,我不习惯使用这个简单的事情来改变一个网站的背景颜色。

browser.webProgress.addProgressListener(this, browser.webProgress.NOTIFY_PROGRESS);

onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot)
{
    var doc = aWebProgress.DOMWindow;
    doc.document.body.style.background = "#f00";
}



是否有任何其他方法可以在创建后立即访问body元素? 或者可能是其他一些方法来改变网页样式(当然不涉及其他一些扩展)? 我可以以某种方式将NOTIFY_PROGRESS监听器附加到一个网站吗?

2 个答案:

答案 0 :(得分:2)

最后,我做了一些不应该对性能产生很大影响的东西,它会立即改变背景颜色。

我做了两个听众: NOTIFY_LOCATION NOTIFY_PROGRESS 。我使用第一个(NOTIFY_LOCATION)来查看用户何时打开网站我正在尝试更改颜色,一旦用户打开该网站,我在该选项卡上设置了NOTIFY_PROGRESS监听器。从NOTIFY_PROGRESS监听器内部检查是否存在body元素,只要body可以访问,我就设置颜色并删除NOTIFY_PROGRESS监听器,因为我不再需要它了。

listener_location =
{
    init: function()
    {
        gBrowser.browsers.forEach(function(browser)
        {
            browser.webProgress.addProgressListener(this, browser.webProgress.NOTIFY_LOCATION);
        }, this);

        gBrowser.tabContainer.addEventListener("TabOpen", this, false);
        gBrowser.tabContainer.addEventListener("TabClose", this, false);
    },

    uninit: function()
    {
        gBrowser.browsers.forEach(function(browser)
        {
            browser.webProgress.removeProgressListener(this);
        }, this);

        gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
        gBrowser.tabContainer.removeEventListener("TabClose", this, false);
    },

    handleEvent: function(aEvent)
    {
        var tab = aEvent.target;
        var webProgress = gBrowser.getBrowserForTab(tab).webProgress;

        if (aEvent.type === "TabOpen")
        {
            webProgress.addProgressListener(this, webProgress.NOTIFY_LOCATION);
        }
        else
        {
            webProgress.removeProgressListener(this);
        }
    },

    QueryInterface: function(aIID)
    {
        if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
            aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
            aIID.equals(Components.interfaces.nsISupports))
            return this;
        throw Components.results.NS_NOINTERFACE;
    },

    onLocationChange: function(aProgress, aRequest, aURI)
    {
        if (aURI.host.indexOf("www.example.com") !== -1)
        {
            aProgress.addProgressListener(listener_progress, aProgress.NOTIFY_PROGRESS);
        }
    }
};
listener_location.init();

listener_progress =
{
    QueryInterface: function(aIID)
    {
        if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
            aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
            aIID.equals(Components.interfaces.nsISupports))
            return this;
        throw Components.results.NS_NOINTERFACE;
    },

    onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot)
    {
        if (aWebProgress.DOMWindow.document.body)
        {
            aWebProgress.removeProgressListener(this);  // remove listener

            var doc = aWebProgress.DOMWindow.document;
            doc.body.style.background = "#f00";     // set color
        }
    }
};


如果其他人试图使用此代码,那么阅读这些代码可能会有用: https://developer.mozilla.org/en/XUL_School/Intercepting_Page_Loads https://developer.mozilla.org/en/Code_snippets/Progress_Listeners https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIWebProgressListener

答案 1 :(得分:0)

在显示之前,可能无法将手放在body元素上,因此您可以更改CSS样式。另一种方法是向文档样式表添加新规则,您应该可以通过Web进度监听器中的document.styleSheets来执行该规则。只需添加一个规则(使其成为必要的重要部分),强制身体的背景为您想要的颜色,并在显示正文时应用它。