Question

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
Was it helpful?

Solution

@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).

OTHER TIPS

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 ;]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top