Приложение Chrome не получает внешние данные UDP в background.js, пока не будет создано окно

Приложение, которое я пытаюсь создать для Chromebook (Chrome OS 60.0.3112.114 64 бит), прослушивает широковещательные передачи UDP, и когда приходят такие сообщения, я хочу, чтобы оно открывало окно. Пока все хорошо, и все работает, когда JS добавляется в окно, но смысл приложения в том, чтобы тихо слушать сообщения, и только после получения сообщения оно открывает окно.

Весь код был перенесен в background.js, и теперь он никогда не получает сообщение ouside. Первое, что приходит в голову, это то, что он приостанавливается, поэтому я добавил setInterval в background.js для отправки данных самому себе, имитируя поступление внешних данных, и эти сообщения принимаются правильно, скрипт не спит. Волшебство начинается, когда я создаю любое окно, и сразу же начинаю получать трансляции. И как только я закрываю окно, внешние данные прерываются, я все равно получаю все свои собственные сообщения, отправленные из setInterval.

Есть ли какое-нибудь решение для этого? Следующее, что я попытался сделать, это создать скрытое окно, но такого не было, также попытался использовать background.html и поместить iframe внутри с кодом background.js, что приведет к такому же поведению.

manifest.json

{
  "name": "UDP Sample",
  "description": "Can't receive data",
  "version": "0.1",
  "manifest_version": 2,

  "app": {
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    }
  },

  "icons": {
    "16": "calculator-16.png",
    "128": "calculator-128.png"
  },

  "sockets": {
      "udp": {
        "send": "*",
        "bind": "0.0.0.0:13000"
      }
  },
}

фон.js:

chrome.app.runtime.onLaunched.addListener(StartApp);

var socketId;

function StartApp()
{
  console.log('app started');

  chrome.sockets.udp.onReceive.addListener(SockRecv);
  chrome.sockets.udp.onReceiveError.addListener(SockError);

  SockBind(AppReady, AppError);
}

function AppReady()
{
  setInterval(function()
  {
    console.log("self sending data");

    var buf = new Uint8Array([70, 73, 82, 69]);
    SockSend(false, buf.buffer);
  }, 4000);

  console.log('listening for net events.');
}

function AppError()
{
  console.log('bind failed, retrying in 10 seconds.');
  setTimeout(StartApp, 10000);
}

function LaunchWindow()
{
  chrome.app.window.create('about.html', 
  {
    frame: "none",
    resizable: false,
    outerBounds: {
      'width': 400,
      'height': 300
    }
  });
}

function SockRecv(info)
{
  console.log("data received " + info.remoteAddress + " bytes");

  if (info.socketId !== socketId || info.remoteAddress == '127.0.0.1')
    return;

  LaunchWindow();
}

function SockSend(ip,data)
{
  chrome.sockets.udp.send(socketId, data, '127.0.0.1', 13000, function()
  {
    console.log("data sent");
  });
}

function SockError(info)
{
  console.log("something bad happened");
  if (info.socketId !== socketId)
    return;

  chrome.sockets.udp.setPaused(socketId, false, function(){});
}

function SockBind(ready_func, error_func)
{
  // Create the Socket
  chrome.sockets.udp.create({persistent: true},
  function(socketInfo)
  {
    console.log("new socket created");
    socketId = socketInfo.socketId;
    try
    {
      chrome.sockets.udp.bind(socketId, "0.0.0.0", 13000, function(result)
      {
        if (result < 0)
        {
          result = socketId;
          socketId = false;
          chrome.sockets.udp.close(result, error_func);
        }
        else
          ready_func();
      });
    }
    catch(err)
    {
      error_func();
    }
  });
}

Консольная отладка (я вручную выполнил функцию LaunchWindow и вдруг приходят внешние данные):

background.js:7 app started
background.js:80 new socket created
background.js:25 listening for net events.
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
LaunchWindow()
undefined
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data

Вывод netstat -l, подтверждающий, что сокет ожидает данных:

chronos@localhost / $ netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN     
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN     
udp        0      0 0.0.0.0:13000           0.0.0.0:*                          
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*                          
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                          
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                          
udp6       0      0 [::]:mdns               [::]:*                             

person André Dias    schedule 24.10.2017    source источник
comment
Похоже на ошибку с "persistent": false - теоретически она должна поддерживать работу фоновой страницы, если есть активные слушатели. Переключитесь на "persistent": true.   -  person wOxxOm    schedule 24.10.2017
comment
Это не работает, при переключении на true приложение больше не загружается: Недопустимое значение для «app.background.persistent». Упакованные приложения не поддерживают постоянные фоновые страницы и должны использовать страницы событий.   -  person André Dias    schedule 24.10.2017
comment
Ага, понятно. Затем попробуйте пожаловаться на crbug.com.   -  person wOxxOm    schedule 24.10.2017
comment
Спасибо за ответ, я попробую это, пока жду параллельных ответов здесь.   -  person André Dias    schedule 24.10.2017
comment
Если вы еще этого не сделали, попробуйте преобразовать фоновую страницу в страницу событий.   -  person Teyam    schedule 25.10.2017


Ответы (1)


ChromeOS имеет брандмауэр, который не позволяет прослушивающим сокетам принимать новые подключения, если нет активных окон приложений.

Лучшее решение, которое я нашел, это создать окно типа panel, которое не скрыто, а свернуто. Вы можете увидеть пример реализации с помощью https://github.com/kzahel/connection-forwarder. или просмотрите демоверсию в интернет-магазине: https://chrome.google.com/webstore/detail/connection-forwarder/ahaijnonphgkgnkbklchdhclailflinn

person kzahel    schedule 10.11.2017
comment
Спасибо, я проверю это, и спасибо за объяснение о брандмауэре, это имеет смысл. - person André Dias; 12.11.2017