문제

I am trying to add plus one button on a XUL window, but I get this error:

Error: Permission denied for <https://plusone.google.com> to call method ChromeWindow.postMessage
Source file: https://ssl.gstatic.com/webclient/js/gc/22431124-0a127465/googleapis.client__plusone.js
Line: 14

I am adding an iframe to https://plusone.google.com/u/0/_/+1/fastbutton?url= ...

Is there a way to add the +1 button on a XUL window and make it accept the postMessage?


The addon I am trying to develop is in the image bellow. The only problem is that it does not register the click due the permission.

+1 any

bootstrap.js (bootstrap-vsdoc.js)

/// <reference path="bootstrap-vsdoc.js" />

/// <summary>
/// Made by Bruno Leonardo Michels
/// </summary>

var watcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                        .getService(Components.interfaces.nsIWindowWatcher);

var listenOpen = {
    observe : function(cWindow, cEvent) {
        if (cEvent != "domwindowopened") return;
            cWindow.addEventListener("load", start, false);
    }
};

function startup(data, reason) {
    watcher.registerNotification(listenOpen);

    var mWindows = watcher.getWindowEnumerator();
    while (mWindows.hasMoreElements()) {
        start(mWindows.getNext());
    }
}
function shutdown(data, reason) {
    watcher.unregisterNotification(listenOpen);

    var mWindows = watcher.getWindowEnumerator();
    while (mWindows.hasMoreElements()) {
        end(mWindows.getNext());
    }
}
function install(data, reason) {

}
function uninstall(data, reason) {

}

/// #region Methods

function getWindow(cWindow)
{
    try
    {
        if (cWindow instanceof Components.interfaces.nsIDOMEvent)
        {
            cWindow = cWindow.currentTarget;
        }
        if (cWindow.document.documentElement.getAttribute("windowtype") != "navigator:browser")
            return;
    }
    catch(ex) { }

    return cWindow;
}

function ajaxGet(cWindow, url, cb)
{
    var xmlhttp;
    xmlhttp = new cWindow.XMLHttpRequest();
    xmlhttp.open("GET", url, true);
    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
        {
            cb(xmlhttp);
        }
    };
    xmlhttp.send();
}

var eventList = [];
function bind(gBrowser, cWindow, target, eventName, fn)
{
    var ev = function(e) { fn(gBrowser, cWindow, e); };
    eventList.push(ev);
    target.addEventListener(eventName, eventList[eventList.length-1], false);
}
function unbind(target, eventName, fn)
{
    var b = target.removeEventListener ?
        function( elem, type, handle ) {
            if ( elem.removeEventListener ) {
                elem.removeEventListener( type, handle, false );
            }
        } :
        function( elem, type, handle ) {
            if ( elem.detachEvent ) {
                elem.detachEvent( "on" + type, handle );
            }
        };

    b(target, eventName, fn);
}
function unbindAll(target, eventName)
{
    for (var i in eventList)
    {
        unbind(target, eventName, eventList[i]);
    }
}

/// #endregion

/// #region Events

function start(cWindow) {
    cWindow = getWindow(cWindow);

    if (!cWindow) return;

    with (cWindow)
    {
        bind(gBrowser, cWindow, gBrowser.tabContainer, "TabAttrModified", tabChange);

        var window = cWindow;
        var document = cWindow.document;

        var url = window.location.href;
        if (!/^http/i.test(url))url="http://www.orkutmanager.net/";
        var urlE= window.encodeURIComponent(url);

        var iconsBar = document.getElementById("urlbar-icons");

        function insScript(w)
        {
            var sc = document.createElement("script");
            sc.src = "https://apis.google.com/js/plusone.js";
            sc.type= "text/javascript";
            sc.setAttribute("extension", "plusoneany");
            (document.lastChild).appendChild(sc);
        }
        insScript(this);
        insScript(this.parent);
        insScript(this.top);

        var button = document.createElement("iframe");
        button.id = "extensions.plusoneany.button";
        button.setAttribute("src", "https://plusone.google.com/u/0/_/+1/fastbutton?url=" + urlE +
            "&size=small&count=true&hl=en-US&_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe");
        button.setAttribute("class", "urlbar-icon extensions-plusoneany");
        button.setAttribute("style", "border:0;padding:0;margin:0;width:70px;height:16px;");

        iconsBar.insertBefore(button, iconsBar.lastChild);
    }
}
function end(cWindow) {
    try
    {
        unbindAll(gBrowser.tabContainer, "TabAttrModified");
    }
    catch(ex){}

    try
    {
        var elements = cWindow.document.getElementsByClassName("extensions-plusoneany");

        for (var i in elements)
        {
            elements[i].parentNode.removeChild(elements[i]);
        }
    }
    catch(ex){}
}

function tabChange(gBrowser, cWindow, e) {
    var win = gBrowser.selectedBrowser.contentWindow;
    var uns = gBrowser.selectedBrowser.contentWindow.wrappedJSObject;

    uns.clearTimeout(uns.PlusOneAnyTimeout);

    uns.PlusOneAnyTimeout = uns.setTimeout(function() {
        var url = win.location.href;
        if (!/^http/i.test(url))url="http://www.orkutmanager.net/";
        var urlE= uns.encodeURIComponent(url);

        try {
            var ifr = cWindow.document.getElementById("extensions.plusoneany.button");
            ifr.setAttribute("src", "https://plusone.google.com/u/0/_/+1/fastbutton?url=" + urlE +
                "&size=small&count=true&hl=en-US&_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe");
        }catch(ex){}
    }, 500);
}

/// #endregion
도움이 되었습니까?

해결책

@systempuntoout is right that, theoretically, setting the iframe type attribute to "content" should fix this. I've had problems with this in the past, however. It might work, but I think XUL is a bit buggy in this respect. If it were me I'd embed a XUL <browser> element instead of a XUL <iframe> and load a static HTML page into the browser (i.e. by calling browser.loadURI) which contains the code I want to run (in this case the iframe with src set to "https://plusone.google.com..."). That way your code will run as real content, just like it would in the main browser content window.

You can write the HTML page to disk (since part of the iframe source is generated dynamically) and then reference it with a file:// URL. Since the code will be pretty short in this case, you can even try using a data URI, which would save you from having to write the temporary file to disk.

In other words you'd create an HTML file (in memory or on disk) with:

<html>
<body>
<iframe src="https://plusone.google.com..." />
</body>
</html>

Then you'd create a <browser> element just like you do now for the iframe, insert it into your XUL document and call loadURI() on it, referencing the HTML file (via file: or data: URI).

다른 팁

I would try to specify the type adding this line:

ifr.setAttribute("type","content");

I think this might be helpful, it could be the issue you are having.

How do you use window.postMessage across domains?

Extremely evil answer, but cant you just get the content of https://apis.google.com/js/plusone.js and then eval it? It's Google, what could go wrong ;]

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top