Расширение Chrome: Как отправить сообщение из фона в контентный скрипт новой страницы - PullRequest
0 голосов
/ 26 апреля 2019

Извините за мой английский, я сделаю все возможное.

Мне нужно создать расширение, в котором всплывающее окно содержит поле и кнопку.

Цель состоит в том, чтобы после нажатия кнопки открылось новое окно (другой веб-сайт), и в этом новом окне необходимо отправить информацию о поле попина.

Вот мой манифест.json

{
  "name": "Webrelief extension",
  "version": "1",
  "browser_action":
  {
    "default_icon": "webrelief.ico",
    "default_popup": "popup.html",
    "default_title": "Webrelief extension - Iello"
  },
  "background":
  {
    "scripts": ["background.js"],
    "persistent": true
  },
  "content_scripts": [
    {
      "run_at": "document_end",
      "matches": [
        "https://www.iello.pro/iello-c102x3259540",
        "https://www.google.com/"
      ],
      "js": ["jquery.min.js","content.js"]
    }
  ],
  "permissions": ["tabs","activeTab","<all_urls>"],
  "manifest_version": 2,
  "content_security_policy": "script-src 'self' https://www.iello.pro/iello-c102x3259540; object-src 'self'"
}

Мой фон.js

$('#validate').on('click',function(activeTab){
    var newURL = "https://www.iello.pro/iello-c102x3259540";
    chrome.tabs.create(
        {
            url: newURL
        }, function() {
            chrome.tabs.query({active: false, currentWindow: true}, function(tabs) {
                chrome.tabs.sendMessage(tabs[tabs.length - 1].id, {greeting: "hello"}, function(response) { // tabs[tabs.length - 1] to get the new windows ? I'm not sure
                    console.log(response);
                });
            });
        }
    );
});

My content.js

chrome.runtime.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"});
    });

И мой popup.html

<!doctype html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Webrelief Extension</title>
    <link href="css/main.css" rel="stylesheet">
</head>
<body>
<img width="400px" src="webrelief_logo.svg" alt="Bannière webrelief">
<hr>
<div>
    <textarea placeholder="Veuillez saisir le json ici ..." name="json" id="json_iello" cols="30" rows="10"></textarea>
</div>
<button id="validate">Go !</button>
<script src="background.js"></script>
</body>
</html>

enter image description here

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

Можете ли вы сказать мне мои ошибки

Спасибо!

1 Ответ

1 голос
/ 26 апреля 2019

Здесь есть три принципиальных проблемы.

Время отправки сообщения на вкладку

На самом деле нет хорошего дубликата этого вопроса ( это ближайший кандидат), но основная проблема, с которой вы столкнулись, - это время.

После открытия вкладки вызывается обратный вызов create до того, как страница будет достаточно загружена.Ваш контент-скрипт может просто не быть там, чтобы прослушать сообщение.С document_end таймингом это почти наверняка не так.

Единственный безопасный способ сделать это - перевернуть связь: пусть скрипт контента запрашивает данные, чтобы вы знали, что они готовы.

Это приводит к следующей проблеме ..

Закрытие всплывающего окна при открытии сообщения

Когда вы создаете вкладку, которая сфокусирована, это приводит к потере всплывающего окнаСфокусируйтесь и закройте.

Когда это произойдет, выполняемый там скрипт завершится - как если бы вы закрыли вкладку со страницей.

Так что остальная часть вашего кода даже не запускается(независимо от предыдущего номера).У вас есть два варианта:

  1. Вы можете создать вкладку с установленным active: false.Это не теряет фокус, поэтому всплывающее окно остается активным, но оно менее удобно для пользователя, хотя вы все равно можете сделать его активным после этого.

    Как несвязанная заметка, вы не должны query когда такие функции, как tabs.create, явно возвращают объект tab в своем обратном вызове.

  2. Лучший вариант: вам следует делегировать сообщение открытия, затем связи на фоновую страницу,Он невосприимчив к эффекту закрытия всплывающих окон и, как правило, лучше подходит в качестве «коммуникационного маршрутизатора».

, что приводит нас к последней проблеме ..

Неправильное пониманиеархитектура фоновой страницы

Вы объявили скрипт background.js в манифесте как фоновый скрипт.Что это значит?

Это означает, что отдельная, невидимая, пустая страница создается и загружается при запуске этого скрипта.

Если вы включаете скрипт background.js в других местах расширенияэто не будет «тот» экземпляр скрипта.Это будет независимая копия, работающая и подчиненная всем ограничениям ее нового контекста.

Очень сильный совет: не пытайтесь повторно использовать целые сценарии в своем коде.Хорошо иметь некоторый общий код (скажем, utils.js, содержащий некоторые общие функции и включенный перед соответствующими сценариями), но позаботьтесь о том, чтобы ваши сценарии назывались описательно и разделяли код.

Для взаимодействия с«Настоящая» фоновая страница, вам нужно отправлять сообщения chrome.runtime.sendMessage).


Собрав все это вместе, ваша логика должна быть:

  1. Во всплывающем окне (сделайте его отдельным сценарием popup.js) прослушайте событие пользовательского интерфейса.
  2. Когда это произойдет, отправьте его в фоновый режим (через message ) или сохраните(в chrome.storage) пользовательских данных.
  3. Затем с помощью обмена сообщениями попросите фоновую страницу выполнить операцию.Подготовьте всплывающее окно к закрытию на этом этапе.
  4. Ваш фон может открыть страницу, запрошенную на этом этапе.Это убьет всплывающее окно, но вам все равно.
  5. Ваш скрипт контента после инициализации может либо напрямую получать пользовательские данные из chrome.storage, либо запрашивать их (через runtime.sendMessage) изфоновая страница.

Существует опасение, что ваш скрипт контента запускается каждый раз, когда открывается целевая страница, даже если вы не хотите использовать пользовательские данные.Вы можете либо реализовать какой-либо механизм, чтобы использовать данные только один раз (например, очистить / пометить их после использования), или только программно внедрить скрипт содержимого (хотя у вас снова возникнут проблемы с синхронизацией после tabs.create)

...