Передача сообщений расширения Chrome: не проверено runtime.lastError: не удалось установить соединение. Получающий конец не существует - PullRequest
0 голосов
/ 14 января 2019

У моего расширения Chrome есть следующие два javascript:

background.js, работает как фоновый скрипт:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.data == "takeScreenshot") {
        var resp = sendResponse;
        chrome.tabs.captureVisibleTab(function(screenshotUrl) {
            resp({
                screenshot: screenshotUrl
            });
        });
        return true; // Return true to tell that the response is sent asynchronously
    } else {
        return "TestReply";
    }
});

api.js, работает как веб-ресурс:

window.takeScreenshot = (function() {
    var isTakingScreenshot = false; // Semaphore
    return function() {
        if(isTakingScreenshot) return Promise.reject();
        isTakingScreenshot = true;
        return new Promise(function(resolve, reject) {
            chrome.runtime.sendMessage("eomfljlchjpefnempfimgminjnegpjod", "takeScreenshot", function(response) {
                console.log(response);
                isTakingScreenshot = false;
                resolve(response.screenshot);
            });
        });
    }
})()
window.test = (function() {
    return function() {
        return new Promise(function(resolve, reject) {
            chrome.runtime.sendMessage("eomfljlchjpefnempfimgminjnegpjod", "test", function(response) {
                console.log(response);
                resolve(response.length);
            });         
        });
    }
})();

Когда я выполняю в консоли вкладки любую функцию (автозаполнение знает их, поэтому они доступны), я получаю сообщение об ошибке:

Не проверено runtime.lastError: Не удалось установить соединение. Получающий конец не существует.

и возвращенный респон не определен.

Я проверил, что идентификатор в sendMessage такой же, как в манифесте и на странице расширений chrome: //, и я открыл фоновую страницу DevTools расширения и вручную добавил туда того же слушателя, чтобы сделать уверен, что слушатель действительно зарегистрирован.

Мои поиски обнаружили, что эта ошибка означает, что слушатель не был правильно зарегистрирован, но я не могу найти причину. У вас есть идея, что вызывает эту ошибку?

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Вот шаблон, который я использую для решения этой проблемы. Контентный скрипт пытается достичь фонового скрипта. Если фоновый скрипт еще не доступен, мы можем увидеть это из chrome.runtime.lastError, установленного (вместо того, чтобы быть неопределенным). В этом случае повторите попытку через 1000 мс.

contentScript.js

function ping() {
  chrome.runtime.sendMessage('ping', response => {
    if(chrome.runtime.lastError) {
      setTimeout(ping, 1000);
    } else {
      // Do whatever you want, background script is ready now
    }
  });
}

ping();

backgroundScript.js

chrome.runtime.onConnect.addListener(port => {
  port.onMessage.addListener(msg => {
    // Handle message however you want
  }
);

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => sendResponse('pong'));
0 голосов
/ 14 февраля 2019

OK. Я выяснил, в чем проблема. Это изменение в поведении цветности с 72, я думаю. Проблема в том, что если вы попытаетесь вызвать chrome.runtime.connect () до того, как откроете канал на другом конце фоновой или всплывающей страницы, вы получите эту ошибку.

В документации Chrome говорится, что вы можете отправить сообщение немедленно. В прошлом это работало, и сообщения доставлялись или удалялись. Но сейчас это терпит неудачу.

chrome docs : при вызове tabs.connect, runtime.connect или runtime.connectNative создается порт. Этот порт можно сразу использовать для отправки сообщений на другой конец через postMessage.

Таким образом, наш обходной путь - убедиться, что слушатель соединения настроен на первый шаг перед вызовом connect (), просто задержав вызов connect ():

    chrome.runtime.onConnect.addListener(port => {
        console.log('connected ', port);

        if (port.name === 'hi') {
            port.onMessage.addListener(this.processMessage);
        }
    });

Если вы настраиваете прослушиватель для события отключения на стороне скрипта контента, он фактически вызывается, когда вы пытаетесь выполнить chrome.runtime.connect, и у вас ничего не слушает на другом конце. Какое правильное поведение в соответствии с Port LifeTime

   port = chrome.runtime.connect(null, {name: 'hi'});      
   port.onDisconnect.addListener(obj => {
            console.log('disconnected port');
    })

Я не знаю, есть ли способ избежать этого, чем с помощью setTimeout и попыткой заставить chrome.runtime.connect появиться после вызова chrome.runtime.onConnect.addListener. Это не очень хорошее решение, потому что оно приводит к ошибкам синхронизации. Может быть, другой обходной путь - изменить направление канала. И инициируйте соединение из всплывающего окна вместо содержимого.

Обновление : я установил минимальное расширение репро для этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...