Большое спасибо, код работает в основном как есть. У меня были небольшие проблемы, так как конфиг не передавался как event.details. Я считаю, что это потому, что один из его членов является указателем на функцию. Я могу обойти, выборочно передавая параметры, которые мне нужны, а не весь конфиг.

аюсь создать расширение, которое будет иметь боковую панель. Эта боковая панель будет иметь кнопки, которые будут выполнять действия в зависимости от состояния страницы хоста.

Я последовал заэтот пример чтобы ввести боковую панель, и я могу подключить кнопку onClick слушателя. Однако я не могу получить доступ к глобальной переменной js. В консоли разработчика в области страницы хоста я вижу переменную (имя переменной - config), за которой я работаю. но когда я в контексте боковой панели (popup.html) я получаю следующую ошибку -
VM523: 1 Uncaught ReferenceError: config не определена. Кажется, что popup.html также работает в отдельном потоке.

Как я могу получить доступ к глобальной переменной js для обработчика onClick моей кнопки?

Мой код:

manifest.json

{
    "manifest_version": 2,

    "name": "Hello World",
    "description": "This extension to test html injection",
    "version": "1.0",
    "content_scripts": [{
        "run_at": "document_end",
        "matches": [
            "https://*/*",
            "http://*/*"
        ],
        "js": ["content-script.js"]
    }],
    "browser_action": {
        "default_icon": "icon.png"
    },
    "background": {
        "scripts":["background.js"]
    },
    "permissions": [
        "activeTab"
    ],
    "web_accessible_resources": [
        "popup.html",
        "popup.js"
    ]
}

background.js

chrome.browserAction.onClicked.addListener(function(){
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
        chrome.tabs.sendMessage(tabs[0].id,"toggle");
    })
});

контент-script.js

chrome.runtime.onMessage.addListener(function(msg, sender){
    if(msg == "toggle"){
        toggle();
    }
})

var iframe = document.createElement('iframe'); 
iframe.style.background = "green";
iframe.style.height = "100%";
iframe.style.width = "0px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.frameBorder = "none"; 
iframe.src = chrome.extension.getURL("popup.html")

document.body.appendChild(iframe);

function toggle(){
    if(iframe.style.width == "0px"){
        iframe.style.width="400px";
    }
    else{
        iframe.style.width="0px";
    }
}

popup.html

<head>
<script src="popup.js"> </script>
</head>
<body>
<h1>Hello World</h1>
<button name="toggle" id="toggle" >on</button>
</body>

popup.js

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById("toggle").addEventListener("click", handler);
});

function handler() {
  console.log("Hello");
  console.log(config);
}
 Jerinaw22 окт. 2017 г., 04:02
Расширение JS не может взаимодействовать со страницей JS. Они говорят вам это в документах.
 Leon22 окт. 2017 г., 04:10
или я должен внедрить этот скрипт в контент-скрипт и подключить слушателя onClick по-другому?
 Leon22 окт. 2017 г., 04:08
@wOxxOm Спасибо за ссылку. Я сталкивался с этим, но кое-что смущало это. Можете ли вы помочь мне понять. Я должен ввести другой сценарий с целью извлечения переменной JS и обмена сообщениями?
 Leon22 окт. 2017 г., 04:11
Хорошо, спасибо, как мне вызвать этот скрипт с кнопки?
 Leon22 окт. 2017 г., 03:59
У меня нет доступа к странице хоста. Страница хоста не хранит ее в chrome.storage.local

Ответы на вопрос(1)

Решение Вопроса

сширения, вам необходимовставить код вscript элемент, чтобы он работал в контексте страницы и передает переменную в скрипт контента через обмен сообщениями DOM. Затем скрипт содержимого может передать сообщение в iframe.

контентный скрипт:

runInPage(initConfigExtractor);

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  switch (msg) {
    case 'toggle':
      toggle();
      return;
    case 'getConfig':
      window.addEventListener(chrome.runtime.id + '-config', event => {
        sendResponse(event.detail);
      }, {once: true});
      window.dispatchEvent(new Event(chrome.runtime.id));
      return true;
  }
})

function initConfigExtractor(extensionId) {
  window.addEventListener(extensionId, () => {
    window.dispatchEvent(new CustomEvent(extensionId + '-config', {
      detail: window.config,
    }));
  });
}

function runInPage(fn) {
  const script = document.createElement('script');
  document.head.appendChild(script).text =
    '((...args) => (' + fn + ')(...args))(' + JSON.stringify(chrome.runtime.id) + ')';
  script.remove();
}

сценарий iframe:

function handler() {
  chrome.tabs.getCurrent(tab => {
    chrome.tabs.sendMessage(tab.id, 'getConfig', config => {
      console.log(config);
      // do something with config
    });
  });  
}

альтернативный случай - всплывающий скрипт:

function handler() {
  chrome.tabs.query({active: true, currentWindow: true}, tabs => {
    chrome.tabs.sendMessage(tabs[0].id, 'getConfig', config => {
      console.log(config);
      // do something with config
    });
  });  
}

Итак, в основном:

сценарий iframe получает собственный идентификатор вкладки и отправляет сообщение в сценарий содержимогоскрипт содержимого отправляет сообщение DOM на ранее вставленный скрипт страницыскрипт страницы прослушивает это сообщение DOM и отправляет другое сообщение DOM обратно в скрипт контентаСценарий содержимого отправляет его в ответ обратно в сценарий iframe.

Все это асинхронно, такreturn true был необходим в слушателе onMessage, чтобы держать канал сообщений открытым.

 Leon22 окт. 2017 г., 04:56
Огромное спасибо. Я должен бежать, но через несколько часов буду тестировать
 Leon23 окт. 2017 г., 15:25
Большое спасибо, код работает в основном как есть. У меня были небольшие проблемы, так как конфиг не передавался как event.details. Я считаю, что это потому, что один из его членов является указателем на функцию. Я могу обойти, выборочно передавая параметры, которые мне нужны, а не весь конфиг.

Ваш ответ на вопрос