Chrome extensions: 'Unchecked runtime.lastError: Порт сообщения закрыт до получения ответа.' Это лучшее, что мы можем сделать? - PullRequest
0 голосов
/ 26 января 2020

Простите за любые явные ошибки, так как я новичок в chrome расширениях, но эта ошибка с API передачи сообщений Chrome обсуждалась здесь , здесь , и здесь в прошлом, и общий ответ выглядит так: «отключить существующие Chrome расширения, одно из которых вызывает ошибку». Это лучшее, что может быть достигнуто? Мы должны просто перевернуться и принять тот факт, что наши расширения будут конфликтовать с другими? Возвращение true или возвращение Promise для функции обратного вызова слушателя и использование sendResponse не решают проблему для меня.

В настоящее время я могу получить только новое значение, сохраненное в chrome.storage.local (без ошибок), путем , отключив все другие расширения chrome, удалив расширение и загрузив обратно распакованное расширение. Интересно, что код работает только на разработчика. chrome .com, он не работает на других «совпадающих» URL в manifest.json.

Я думаю, что в await и async операторы в решении этой проблемы, но я не уверен, как правильно ее реализовать.

манифест. json:

{
    "manifest_version": 2,
    "name": "my extension",
    "version": "1.0",
    "description": "its my extension",
    "permissions": [
        "declarativeContent", 
        "storage", 
        "activeTab"
    ],
    "content_scripts": [
        {
          "matches": [
            "*://developer.chrome.com/*",
            "*://bbc.co.uk/*",
            "*://theguardian.com/*",
            "*://dailymail.co.uk/*"
          ],
          "js": ["content.js"]
        }
      ],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "content_security_policy": "script-src 'self' https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js; object-src 'self'",
    "page_action": {
        "default_popup": "popup.html"
    },
    "icons": {
        "16": "images/icon16.png",
        "32": "images/icon32.png",
        "48": "images/icon48.png",
        "128": "images/icon128.png"
      }
}

popup. html:

<!DOCTYPE html>
  <html>
    <head>
      <title>my extension</title>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="popup.js"></script>
      <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
      <h1>my extension</h1>
      <h2>Article: <span id="article-headline"></span></h2>
      <button id="detect-article">Detect Article</button>
    </body>
  </html>

popup. js:

$(document).ready(function() {
    $("#detect-article").click(function() {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
            chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"}, function(response) {
                console.log("Requesting headline")
            });
        });
    });    
})

function getHeadline(changes) {
    let changedValues = Object.keys(changes);
    //console.log(changedValues);

    for (var item of changedValues) {
        console.log("new value: " + changes[item].newValue);
        $("#article-headline").text(changes[item].newValue)
    }
}

chrome.storage.onChanged.addListener(getHeadline);

content. js:

function handleRequest(message, sender, sendResponse) {
    console.log("Request recieved");
    let headlineList = document.getElementsByTagName("h1");
    chrome.storage.local.set({headline: headlineList[0].innerText}, function() {
        console.log("'" + headlineList[0].innerText + "' stored in local storage");
    });
    return true;
}

chrome.runtime.onMessage.addListener(handleRequest);

background. js:

chrome.runtime.onInstalled.addListener(function() {
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
      chrome.declarativeContent.onPageChanged.addRules([{
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'developer.chrome.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'bbc.co.uk' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'theguardian.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
              pageUrl: { hostContains: 'dailymail.co.uk' },
          }),
        ],
      actions: [new chrome.declarativeContent.ShowPageAction()]
    }]);
  });
});

Большое спасибо, что нашли время посмотреть / пересмотреть эту проблему, решения относящиеся к вышеупомянутому «отключить существующие расширения» - это не то, что я ищу.

1 Ответ

2 голосов
/ 26 января 2020

Когда вы указываете обратный вызов для sendMessage, вы сообщаете API, что вам НУЖЕН ответ , поэтому, когда ваш контент-скрипт не отвечает с помощью sendResponse, API думает, что произошло что-то ужасное, и сообщает об этом как таковой!

Напоминание: при редактировании сценариев содержимого обязательно перезагрузите расширение на странице chrome://extensions и вкладки, на которых должен быть этот сценарий содержимого.

Вы не нужно никакого ответа:

  • Удалить обратный вызов в sendMessage

    chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"});
    
  • Удалить return true - все это делает в настоящее время говорит API о том, чтобы порт сообщений оставался открытым в течение неопределенного времени, что вы никогда не будете использовать, так что это просто источник утечки памяти.

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      // do something
      // don't call sendResponse, don't return true
    });
    

Вам нужен ответ:

  • Заменить return true на sendResponse

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      sendResponse('whatever');
    });
    

Вам нужен ответ от chrome API callback (который всегда асинхронный):

  • Сохранить return true
  • Вызов sendResponse(someImportantData) внутри обратного вызова

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      chrome.storage.local.set({foo: 'bar'}, () => {
        sendResponse('whatever');
      });
      return true;
    });
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...