Not getting onReceive callback for UDP socket on chrome after event page is unloaded

孤人 提交于 2020-01-15 11:32:09

问题


I am creating a chrome app (packaged) and I have to create a UDP socket and listen for the incoming broadcast messages as soon as chrome browser starts up.

Everything works fine as I start browser , I get the callback registered through chrome.sockets.udp.onReceive.addListener() API and the data as well.

The problem starts when the event page is unloaded (after about 10-15 secs).

Any new UDP packets are not received.

But as seen in Chrome Apps & Extensions Developer Tool , onReceive callback triggered once even after the event page is unloaded (but not for subsequent UDP packets),but it doesn't hit my callback function.

And I have kept the persistent flag true while creating the UDP socket.

Here is the manifest of my app:

{
  "manifest_version": 2,

  "name": "App Name",
  "description": "Description",
  "version": "1.0",

  "app": {
    "background": {
      "scripts": ["socket.js","eventPage.js"],
    "persistent": true
    }
  },
  "sockets":{
    "udp": {"send":["*:*"], "bind":["*:*"]}
  }, 
  "permissions":["system.network","notifications"]
}

Event page and socket code:

// eventPage.js

chrome.runtime.onStartup.addListener(function() { 
    console.log("I started up!");
    socket.cleanup_create();
});

chrome.runtime.onSuspend.addListener(function() {
    console.log("I am being suspended!");
});

// socket.js

function show(jsontext) {

    var json_object = JSON.parse(jsontext);

    console.log(json_object.TitleText); 
    console.log(json_object.MainText);

    chrome.notifications.create("", 
            {type:'basic',iconUrl:'icon.png',title:json_object.TitleText,message:json_object.MainText}, 
            function callback(){})
}

var socket = {

    socketId:null,

    /*==========Receive Callback=================*/
    recieve_callback:function(rc){
    console.log("Received on socket ID "+rc.socketId);

    var dataView = new DataView(rc.data);


    var decoder = new TextDecoder("utf-8");
    var decodedString = decoder.decode(dataView);


    console.log("Data Received and it is "+decodedString);

    show(decodedString);

    },

    /*==========Receive Error Callback=================*/

    recieve_error_callback:function(info){
    console.log("Error on socket with code "+info.resultCode);
    },

    /*==========Bind Callback=================*/

    bind_cb: function(s){
    console.log("Socket seems to be binded result "+s);
    chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
    chrome.sockets.udp.onReceiveError.addListener(socket.recieve_error_callback)
    },

    /*==========Create Callback=================*/

    create_cb: function(s){
    console.log("Socket seems to be created id is "+s.socketId);
    socket.socketId = s.socketId;
    chrome.sockets.udp.bind(socket.socketId,"0.0.0.0",8080,socket.bind_cb);
    },

    /*==========Create Method=================*/

    create: function(){
    chrome.sockets.udp.create({persistent:true,name:"udp_socket",bufferSize:15000},socket.create_cb);   
    },

    cleanup_create:function(){
    chrome.sockets.udp.getSockets(function cleanup_create_cb(socketInfos){
    console.log("Cleaning up existing sockets  "+socketInfos.length);

    for (i = 0; i < socketInfos.length; i++) {
    chrome.sockets.udp.close(socketInfos[i],function socket_close_cb(){});
    }

    socket.create();

    });
    }
};

Is there any way I can keep the event page always loaded or any other means through which I can ensure that I always get the onReceive event?


回答1:


How do Chrome event pages work? Here's the documentation, but in a nutshell:

  1. Your page's top level context executes, registering listeners for events.
  2. Chrome builds a list of events that it should wake the page for.
  3. Page unloads: note that it completely destroys JS context, including listeners and any objects initialized (e.g. your socket object).
  4. Event happens. Chrome looks up if it needs to wake up your page. Suppose it does.
  5. The page is loaded again, listeners register again, and then Chrome calls them.

To quote the docs:

Because the listeners themselves only exist in the context of the event page, you must use addListener each time the event page loads; only doing so at runtime.onInstalled by itself is insufficient.

Now let's look at this line:

// Called in a callback to chrome.sockets.udp.bind()
bind_cb: function(s){
  /* ... */
  chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
  /* ... */
}

When the page is loaded again, this does not execute synchronously. Therefore, at step 5, Chrome fails to find an appropriate listener and it's not called.

Do note that the event is global, i.e. it's not bound to a socket object (that does not exist after unloading). So you can (and should) safely bind it to one function that analyzes the callback parameters to understand which socket it operates on.

So, to make your code work, addListener must be called synchronously when the event page loads.



来源:https://stackoverflow.com/questions/28393684/not-getting-onreceive-callback-for-udp-socket-on-chrome-after-event-page-is-unlo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!