Передача сообщения из background.js в popup.js

Я пытаюсь реализовать собственное расширение Chrome, в котором при определенном событии создается уведомление браузера и заполняется всплывающее окно данными, рассчитанными в background.js

Вот мой manifest.json файл:

{
    "name": "Dummy name",
    "description": "Description",
    "manifest_version": 2,
    "version": "1.1.3",
    "icons": {
        "16": "icon_16.png",
        "48": "icon_48.png",
        "128": "icon_128.png",
        "256": "icon_256.png"
    },
    "browser_action": {
        "default_icon": "icon_48.png",
        "default_title": "Test",
        "default_popup": "popup.html"
    },
    "permissions": ["background","webRequest","webRequestBlocking","webNavigation","tabs","notifications"],
    "background": {
        "scripts":["jquery-1.8.1.min.js","classy.js","background.js"]
    }
}

Мой звонок sendMessage через background.js

show : function(result) {
    var that = this;
    chrome.extension.sendMessage({greeting: "hello"}, function(response) {
        console.log(response);
    });

    if(window.webkitNotifications) {
        var notification = webkitNotifications.createHTMLNotification('notification.html');
        notification.show();
        setTimeout(function(){
            notification.cancel();
            }, '7000');
        }
    }

Мой слушатель сообщений в popup.js (из примеров расширения Chrome)

chrome.extension.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello")
      sendResponse({farewell: "goodbye"});
  });

Единственная ошибка, которую я получаю, - это

Ошибка порта: не удалось установить соединение. Приемного конца не существует.

Спасибо за помощь!


person François Pérez    schedule 04.09.2012    source источник
comment
Фоновая страница загружается задолго до отображения всплывающего окна с действиями браузера. Очевидно, что во всплывающем скрипте не было изменений для привязки прослушивателя событий через chrome.extension.onMessage.   -  person Rob W    schedule 04.09.2012
comment
Как было сказано ранее, это запускается на основе события. Поскольку событие происходит через несколько секунд после загрузки страницы, можно ли считать, что оно не прослушивается во всплывающем окне?   -  person François Pérez    schedule 05.09.2012
comment
Убедитесь, что то, что вы говорите, правда. Вы можете вставить alert('') диалоговое окно, чтобы увидеть, выполняются ли методы в ожидаемом порядке. Боковое примечание: вы можете напрямую общаться между всплывающим окном / фоном через chrome.extension.getBackgroundPage() ( получает доступ к глобальному объекту window фона из всплывающего окна) и chrome.extension.getViews({type:'popup'})[0] ( чтобы получить глобальный объект window всплывающего окна, если он существует, с фоновой страницы).   -  person Rob W    schedule 05.09.2012
comment
Я только что это проверил, и на самом деле любое действие во всплывающем окне может быть запущено только тогда, когда оно открыто. Есть идеи, как имитировать отправку сообщения? К сожалению, то же самое и с getBackgroundPage () и getViews () ... работают только тогда, когда всплывающее окно открыто :(   -  person François Pérez    schedule 05.09.2012
comment
Очевидно ... Представление всплывающего окна активно только тогда, когда оно отображается. Если функциональность должна выжить в течение всего времени существования всплывающего окна, вы должны переместить его на фоновую страницу.   -  person Rob W    schedule 05.09.2012
comment
chrome.extension устарел с Chrome v58, используйте chrome.runtime   -  person evandrix    schedule 29.04.2018
comment
Очевидно, также устарел, и его следует избегать.   -  person jbarr    schedule 22.01.2019
comment
Всплывающее окно не имеет постоянного состояния. Одним из решений было бы сохранить состояние всплывающего окна в localStorage, чтобы его можно было легко предварительно загрузить, а затем использовать событие storage для отслеживания изменений состояния, пока всплывающее окно открыто (что эквивалентно отправке сообщения во всплывающее окно). Я разместил ответ ниже.   -  person Maciej Krawczyk    schedule 22.06.2021


Ответы (5)


У всплывающего окна нет идентификатора вкладки, поэтому вы получите сообщение об ошибке.

В этом случае вы можете использовать chrome.runtime.sendMessage и chrome.runtime.onMessage.addListener.

Итак, в background.js

chrome.runtime.sendMessage({
    msg: "something_completed", 
    data: {
        subject: "Loading",
        content: "Just completed!"
    }
});

И в popup.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if (request.msg === "something_completed") {
            //  To do something
            console.log(request.data.subject)
            console.log(request.data.content)
        }
    }
);

Надеюсь, это будет вам полезно.

Спасибо,

person Perfect    schedule 19.04.2017
comment
что, если я открыл несколько вкладок и отправил сообщение на popup.js. какой popup.js получит его? как отправить сообщение туда, куда я хочу отправить сообщение @Perfect - person Stephen; 06.12.2018
comment
Вы должны отправить сообщение из всплывающего окна в серверный скрипт. На этом этапе вы можете получить tab_id в бэкэнд-скрипте, чтобы определить, какое всплывающее окно вкладки отправлено в фоновый режим. Невозможно отправить сообщение из внутреннего сценария во всплывающее окно, но вы можете отправить серверный сценарий в сценарий содержимого конкретной вкладки. Или вы можете создать соединение между серверной частью и всплывающим окном. Посмотри по этой ссылке. stackoverflow.com/questions/13546778/ - person Perfect; 10.12.2018
comment
Я сделал то же самое, используя tabid, прежде чем увидеть это. Спасибо @Perfect за другой способ. - person Stephen; 17.12.2018

Чтобы решить эту проблему, вам нужно сначала отправить сообщение о подтверждении связи в background.js, а затем отправить фактические данные из background.js в popup.js. Например: в моем случае то, что я сделал, было

popup.js

chrome.runtime.sendMessage({data:"Handshake"},function(response){
	
			});
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
	str = JSON.stringify(message.data);
});

background.js

chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
//alert(message.data);
	chrome.runtime.sendMessage({data:datax},function(response){
			});
			});

Что я пытаюсь сделать, так это то, что как только мы щелкаем по значку, сообщение рукопожатия отправляется в background.js, и когда оно его получает, мы можем отправить переменную или любые данные, которые мы хотели отправить на popup.js, чтобы отобразить его. на popup.html.

person Akshay Singh    schedule 22.08.2016
comment
Мне нравится идея рукопожатия, она гарантирует, что всплывающее окно живо (не уничтожено) и может прослушивать входящие данные. Кроме того, это похоже на одноразовое событие для каждой загрузки страницы, которое следует за простым однократным методы запроса - person A13X; 02.04.2017
comment
Но это означает, что вызов инициируется Popup. Я считал, что OP хочет, чтобы разговор начался от фона до всплывающего окна. Если всплывающее окно хочет получить данные из фона, оно также может использовать стандартный подход: let bg = chrome.runtime.getBackgroundPage (), а затем получить сообщение по console.log (bg.message); Здесь 'message' - это объект в файле background.js - person sunny_dev; 19.06.2018

Используйте runtime.sendMessage для отправки сообщений в фоновый сценарий и tabs.sendMessage из фона в сценарий содержимого.

Обратите внимание, что вам необходимо указать идентификатор вкладки:

chrome.tabs.query({ active: true }, (tabs) => {
    chrome.tabs.sendMessage(tabs[0].id, { greeting: 'hello' }, (response) => {
        console.log(response);
    });
});

Вы можете найти полный пример и документацию здесь: https://developer.chrome.com/extensions/messaging#simple

person i11v    schedule 26.01.2017

Я нашел два простейших способа отправки данных из background.js в popup.js:

1) Использование хранилища

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

background.js

chrome.storage.sync.set({ 'dataValue1': 'Some data 1.' });
chrome.storage.sync.set({ 'dataValue2': 'Some data 2.' });

popup.js

function updatePopup() {
    chrome.storage.sync.get(['dataValue1', 'dataValue2'], function (data) {
        document.getElementById("popupElement1").innerText = data.dataValue1;
        document.getElementById("popupElement2").innerText = data.dataValue2;
    });
}    
document.addEventListener('DOMContentLoaded', updatePopup);

popup.html

<html>    
<head>
    <script src="popup.js"></script>
</head>    
<body>
    <p id="popupElement1"></p>
    <p id="popupElement2"></p>
</body>    
</html>

manifest.json

{
    "name": "Background2popup",
    "version": "1.0",
    "manifest_version": 2,
    "description": "This is a demo",
    "browser_action": {
        "default_popup": "popup.html"
    },
    "background": {
        "scripts": [
            "background.js"
        ]
    },
    "permissions": [
        "<all_urls>",
        "storage",
        "tabs"
    ]
}

2) Использование chrome.runtime.sendMessage ()

Как только всплывающее окно открывается, вы отправляете сообщение из всплывающего окна в фоновый режим, чтобы установить соединение / рукопожатие (в противном случае вы получите сообщение «Unchecked runtime.lastError: не удалось установить соединение. из фона во всплывающее окно, а всплывающее окно не открывается). После установления соединения вы используете sendResponse из фона, чтобы отправить данные, которые вы хотели отправить, во всплывающее окно.

background.js

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.method == "getStatus") {
        console.log(request.data)
        sendResponse({ method: "peepee", data: "poopoo" })
    }
});

popup.js

chrome.runtime.sendMessage({ method: "getStatus", data: "xxx" }, function (res) {
    document.getElementById("popupElement1").innerText = res.method;
    document.getElementById("popupElement2").innerText = res.data;
return true;
});

popup.html и manifest.json такие же, как в первом примере.

person jlo    schedule 07.11.2020

решение localStorage

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

Фон:

localStorage.setItem('popupData', JSON.stringify({ tabReady: true }));

Неожиданно возникнуть:

// Load the state from localStorage when popup opens
let popupData = JSON.parse(localStorage.getItem('popupData'));

// Keep track of changes to the popup state while the popup is open
window.addEventListener('storage', (e) => {
  if (e.key === 'popupData') {
    popupData = JSON.parse(e.newValue);
    console.log(popupData.tabReady);
  } 
});
person Maciej Krawczyk    schedule 22.06.2021