尝试从Firefox插件(SDK)中的资源加载内容时出现安全性错误

时间:2014-02-21 23:48:24

标签: firefox-addon firefox-addon-sdk

我正在使用SDK创建一个firefox插件。我的目标很简单,拦截特定的iframe并加载我自己的HTML页面(用我的插件打包为资源),而不是最初请求的内容。

到目前为止,我有以下代码:

var httpRequestObserver = 
{
    observe: function(subject, topic, data)
    {
        var httpChannel, requestURL;

        if (topic == "http-on-modify-request") {
            httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
            requestURL = httpChannel.URI.spec;

            var newRequestURL, i;

            if (/someurl/.test(requestURL)) {
                var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);

                httpChannel.redirectTo(ioService.newURI(self.data.url('pages/test.html'), undefined, undefined));
            }

            return;
        }
    }
};

var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(httpRequestObserver, "http-on-modify-request", false);

此代码的工作原理是它检测到正确的iframe加载并正确进行重定向。但是,我收到以下错误:

  

安全错误:http://url.com的内容可能无法加载或链接到   罐子:文件:///.../pages/test.html

我如何解决这个限制?

4 个答案:

答案 0 :(得分:3)

实际上,我真的在想这个人。

当我改为使用loadContext时它已经解决了。现在,当你获得loadContext时,你得到任何浏览器元素(标签浏览器,框架或iframe)的contentWindow然后就像你正在做的那样中止http请求然后loadContext.associatedWindow.document.location = self.data('pages/tests.html');

完成

在此处粘贴代码,删除所有私有内容。你可能需要chrome.manifest测试它并将代码粘贴回来

Cu.import('resource://gre/modules/Services.jsm');

var httpRequestObserver = {
    observe: function (subject, topic, data) {
        var httpChannel, requestURL;

        if (topic == "http-on-modify-request") {
            httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
            requestURL = httpChannel.URI.spec;

            var newRequestURL, i;

            if (/someurl/.test(requestURL)) {
                var goodies = loadContextGoodies(httpChannel);
                if (goodies) {
                    httpChannel.cancel(Cr.NS_BINDING_ABORTED);
                    goodies.contentWindow.location = self.data.url('pages/test.html');
                } else {
                    //dont do anything as there is no contentWindow associated with the httpChannel, liekly a google ad is loading or some ajax call or something, so this is not an error
                }
            }

            return;
        }
    }
};
Services.obs.addObserver(httpRequestObserver, "http-on-modify-request", false);





//this function gets the contentWindow and other good stuff from loadContext of httpChannel
function loadContextGoodies(httpChannel) {
    //httpChannel must be the subject of http-on-modify-request QI'ed to nsiHTTPChannel as is done on line 8 "httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);"
    //start loadContext stuff
    var loadContext;
    try {
        var interfaceRequestor = httpChannel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor);
        //var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
        try {
            loadContext = interfaceRequestor.getInterface(Ci.nsILoadContext);
        } catch (ex) {
            try {
                loadContext = subject.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
            } catch (ex2) {}
        }
    } catch (ex0) {}

    if (!loadContext) {
        //no load context so dont do anything although you can run this, which is your old code
        //this probably means that its loading an ajax call or like a google ad thing
        return null;
    } else {
        var contentWindow = loadContext.associatedWindow;
        if (!contentWindow) {
            //this channel does not have a window, its probably loading a resource
            //this probably means that its loading an ajax call or like a google ad thing
            return null;
        } else {
            var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIWebNavigation)
                .QueryInterface(Ci.nsIDocShellTreeItem)
                .rootTreeItem
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDOMWindow);
            var gBrowser = aDOMWindow.gBrowser;
            var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
            var browser = aTab.linkedBrowser; //this is the browser within the tab //this is where the example in the previous section ends
            return {
                aDOMWindow: aDOMWindow,
                gBrowser: gBrowser,
                aTab: aTab,
                browser: browser,
                contentWindow: contentWindow
            };
        }
    }
    //end loadContext stuff
}

注意:现在先尝试一下,我还没有测试,如果在尝试重定向时出现安全错误,请创建chrome.manifest文件并将其放在根目录中。如果它抛出一个安全错误,你肯定需要一个chrome.manifest文件,这将毫无疑问地解决它。我会在今晚晚些时候自己测试一下这段时间。

chrome.manifest应如下所示:

content kaboom-data ./resources/kaboom/data/ contentaccessible=yes

然后在上面的代码方式中,将重定向行从goodies.contentWindow.location = self.data.url('pages/test.html');更改为goodies.contentWindow.location = 'chrome://kaboom-data/pages/test.html');

答案 1 :(得分:1)

在此处查看此插件:https://addons.mozilla.org/en-US/firefox/addon/ghforkable/?src=search

在chrome.manifest文件中的

,我们将contentaccessible参数设置为yes

你不需要这个插件的sdk。它如此简单,只是ocpy paste进入bootstrap骨架,如下所示:

Bootstrap With Some Features, Like chrome.manifest which you will need

Bootstrap Ultra Basic

如果您想真正将网页重定向到您的网站,也许您想要对网页进行自定义?如果你想生病,请为你做一个关于页面定制的演示。你可以看到有点难以理解的演示here

答案 2 :(得分:1)

在这里发布我的试用版,以便它可以帮助所有人:

追踪1 失败 - 创建了包含内容content kaboom-data resources/kaboom/data/ contentaccessible=yes

的chrome.manifest文件
var myuri = Services.io.newURI('chrome://kaboom-data/content/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);

错误抛出

  

安全错误:http://digg.com/tools/diggthis/confirm的内容?可以   没有加载或链接   罐子:文件:/// C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ@jetpack.xpi /资源/ KABOOM /数据/pages/test.html。

试用版2 失败 - 在bootstrap.js中创建了资源

  

alias.spec =   文件:/// C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ@jetpack.xpi

     

alias已更新为spec:   罐子:文件:/// C:!/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ@jetpack.xpi /

   let resource = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
  let alias = Services.io.newFileURI(data.installPath);
  Cu.reportError('alias.spec = ' + alias.spec);
  if (!data.installPath.isDirectory()) {
    alias = Services.io.newURI("jar:" + alias.spec + "!/", null, null);
    Cu.reportError('alias updated to spec: ' + alias.spec);
  }
  resource.setSubstitution("kaboom_data", alias);

...

var myuri = Services.io.newURI('resource://kaboom_data/resources/kaboom/data/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);

错误抛出

  

安全错误:http://digg.com/tools/diggthis/confirm的内容?可以   没有加载或链接   罐子:文件:/// C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ@jetpack.xpi /资源/ KABOOM /数据/pages/test.html。

<强>结论 在上面的两个试验中它是最奇怪的事情,它不会显示抛出的安全错误中的资源或chrome路径,但它会给出完整的jar路径。让我相信这与redirectTo函数有关。

有效的解决方案是

的解决方案
var gBrowser = utils.getMostRecentBrowserWindow().gBrowser;
var domWin = httpChannel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
var browser = gBrowser.getBrowserForDocument(domWin.document);

//redirect
browser.loadURI(self.data.url('pages/test.html'));

然而我改为使用loadContext而不是此方法,因为这是推荐的方法。如果网址加载速度很慢,那么gBrowser to getMostRecentBrowserWindow也会失败,并且用户会切换到另一个标签或窗口

我还改为使用Services.jsm,因为你还是导入了Cu。使用Services.jsm非常快,甚至不会快速闪烁。它只是一个指针。

我还在努力尝试使用redirectTo方法来解决它真正困扰我的问题。我所做的更改是我的本地副本。

答案 3 :(得分:1)

您是否考虑过将本地HTML文件转换为数据网址并加载?