admin管理员组

文章数量:1357307

I have a page and an iframe inside of the page. Both hosted on the same domain. I have a full control of the iframe, but don't have a control of the parent page.

So I need to establish a websocket connection from the iframe, but in context of the parent window and keep it alive while I'm navigating out of the iframe (to the other menu items of the parent page).

(see the image) Like establishing connection in A.html, and keep it alive while navigating to B and C.

is that possible?

I have a page and an iframe inside of the page. Both hosted on the same domain. I have a full control of the iframe, but don't have a control of the parent page.

So I need to establish a websocket connection from the iframe, but in context of the parent window and keep it alive while I'm navigating out of the iframe (to the other menu items of the parent page).

(see the image) Like establishing connection in A.html, and keep it alive while navigating to B and C.

is that possible?

Share Improve this question edited Dec 20, 2017 at 2:43 Andrew P. asked Oct 16, 2017 at 22:20 Andrew P.Andrew P. 791 gold badge1 silver badge6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Short answer:

Direct script injection to the parent window still might be a more elegant solution.

Long answer:

Websocket is just a kind of connection to the server. Once you create it - it persists in your browser's tab and it's not destroyed if you unload the script which created the websocket.

Two issues with creating websockets within iframes:

  1. you probably don't want to create a new websocket connection every time you load the same iframe content.
  2. once your iframe is unloaded - all websocket's event handlers are lost (like onopen, onclose, onmessage, etc).

You can try to create a websocket factory on the main window. The instance of this factory would be responsible for:

  1. create a websocket using data provided from an iframe and store it in the inner collection property
  2. clone provided websocket event handlers so they are reachable even when their original source is unloaded. It will work fine if the event handlers are simple.

There are some known issues with function cloning - ie, if they use outer closure defined in iframe's script - that closure will be lost. You may want to do a research on cloning libraries.

main.js (loaded in main index.html):

var socketsCollection = new SocketsCollection();

function SocketsCollection() {
    this.collection = {};

    this.add = function(key, obj) {
        if (this.exists(key)) return;

        // clone websocket event handlers
        // PS: this is not the best solution to clone a function. Need a better research here
        eval("var onopen = " + obj.onopen.toString());
        eval("var onclose = " + obj.onclose.toString());
        eval("var onmessage = " + obj.onmessage.toString());

        // create websocket
        var ws = new WebSocket(obj.url);
        ws.onopen = function(e) {
            onopen(e, key, ws);
        };
        ws.onclose = function(e) {
            onclose(e, key, ws);
        }
        ws.onmessage = function(e) {
            onmessage(e, key, ws);
        }

        this.collection[key] = {
            key: key,
            ws: ws
        };

        // test websocket is alive
        var self = this;
        var counter = 1;
        window.setInterval(function () {
            console.log('testing ' + key);
            self.collection[key].ws.send('ping # ' + counter + ' websocket ' + key);
            counter++;
        }, 2000);  
    }

    this.exists = function(key){
        return this.collection[key] !== undefined;
    }
}

iframed.js:

function foo(window, socketKey) {
    if (window.socketsCollection.exists(socketKey)) return;

    var newSocketData = {
        url: "wss://echo.websocket/",
        onopen: function(e, key, ws) {
            console.log(key + ' is OPEN', ws.readyState)
            ws.send('Hello socket ' + key);
        },
        onclose: function(e, key, ws) {
            console.log(key + ' is CLOSED', ws.readyState)
        },
        onmessage: function (e, key, ws) {
            console.log(key + ' response: ', e.data);
        }
    };

    window.socketsCollection.add(socketKey, newSocketData);
}

a.html:

<script src="iframed.js"></script>
<script>
    foo.call(window.parent, window.parent, 'A');
</script>

b.html:

<script src="iframed.js"></script>
<script>
    foo.call(window.parent, window.parent, 'B');
</script>

本文标签: javascriptWebsocket connection from an iframe in context of the parent windowStack Overflow