KangoExtensions / kango

Kango framework issue tracker
74 stars 7 forks source link

[Firefox][1.8.0], content-script's messageListener callback doesn't have access to window.* properties #167

Open ferdibiflator opened 8 years ago

ferdibiflator commented 8 years ago

There is a problem with access to window.* properties inside message listener's callback in Firefox with kango 1.8.0. This problem doesn't occur in kango 1.7.9.

For example, if I do in content-script:

kango.addMessageListener('msg', function() {
    document.querySelectorAll('input');
});

and in background-script:

tab.dispatchMessage('msg');

I'll get a message from Firefox:

Error: Permission denied to access property "document"

I solved this problem by calling a callback in Promise:

// Custom message listener

'use strict';

function MessageListener() {
    this.addedListeners = new Map();
}

MessageListener.prototype.add = function (message, callback) {
    const isFirefox = typeof InstallTrigger !== 'undefined';
    let adaptedCallback = callback;

    if(isFirefox) {
        adaptedCallback = runAsync.bind(null, callback)
    }

    kango.addMessageListener(message, adaptedCallback)

    this.addedListeners.set(callback, adaptedCallback);
};

MessageListener.prototype.remove = function (message, callback) {
    const adaptedCallback = this.addedListeners.get(callback);

    kango.removeMessageListener(message, adaptedCallback);

    this.addedListeners.delete(callback);
};

module.exports = MessageListener;

function runAsync(callback, event) {
    new Promise(resolve => {
        callback(event);

        resolve();
    }).catch(e => console.log(e));
}
emmabartner commented 8 years ago

Hello, could you tell me where do you place this file in order to MessageListener object to be available in content scripts ?

Thx !

ferdibiflator commented 8 years ago

Hello @emmabartner. I have complex structure for my project and I build bundle with Webpack.

Webpack bundle approach You can place it next to content script. As this is CommonJS module. In content script you need to do const MessageListener = require('./MessageListener'); Then use webpack for bundle building and describe the resulting bundle file in extension_info.json file:

"content_scripts": [
    "bundle.js"
 ]

In the end do

python ./kango/kango.py build ./kango-project

Native require approach I haven't used it. See http://kangoextensions.com/docs/general/content-scripts.html#require

The simplest method Delete the string module.exports = MessageListener; from code above and put it in the beginning of your content script. For example:

// ==UserScript==
// @name Unnamed
// @include http://*
// @include https://*
// @all-frames true
// ==/UserScript==

'use strict';

function MessageListener() {
    this.addedListeners = new Map();
}

MessageListener.prototype.add = function (message, callback) {
    const isFirefox = typeof InstallTrigger !== 'undefined';
    let adaptedCallback = callback;

    if(isFirefox) {
        adaptedCallback = runAsync.bind(null, callback)
    }

    kango.addMessageListener(message, adaptedCallback)

    this.addedListeners.set(callback, adaptedCallback);
};

MessageListener.prototype.remove = function (message, callback) {
    const adaptedCallback = this.addedListeners.get(callback);

    kango.removeMessageListener(message, adaptedCallback);

    this.addedListeners.delete(callback);
};

function runAsync(callback, event) {
    new Promise(resolve => {
        callback(event);

        resolve();
    }).catch(e => console.log(e));
}

const listener = new MessageListener();

// use your listener...
emmabartner commented 7 years ago

Thank you for the answer. It works, but the problem is not fully resolved.

It seems that some previous listeners are still present even after reloading the page. This cause multiple calls to old & invalid listeners.

We can clearly see this problem with Kango's MessagingDemo.

After loading twitter.com and refreshed 2 times (see the triple message for the same listener on just one tab) : image

Anyone have a workaround for this ?