Расширение Chrome - получение глобальной переменной со страницы - PullRequest
42 голосов
/ 07 марта 2012

Я работаю над расширением для Chrome. Я хочу проанализировать содержание "оригинального" сообщения Gmail (текущего просматриваемого сообщения).

Я пытался использовать jQuery.load () следующим образом

$(windows).load(function() { alert(GLOBALS); });

и поместите его в скрипт контента, но он тоже не работает. Я использую инструменты разработчика Chrome, которые возвращают следующую ошибку при вызове alert(GLOBALS);

Uncaught ReferenceError: GLOBALS не определено

Хотя при использовании консоли инструментов разработчика при вводе в консоль GLOBALS возвращается массив.

Любая подсказка, как получить доступ к GLOBALS из скрипта контента?

Ответы [ 5 ]

87 голосов
/ 09 марта 2012

Сценарии содержимого работают в изолированной среде. Чтобы получить доступ к любым глобальным свойствам (window) страницы, вы должны либо внедрить новый элемент <script>, либо использовать прослушиватели событий для передачи данных.

См. этот ответ , например, о введении элемента <script> в контекст страницы.

Пример

contentscript.js ("run_at": "document_end" в манифесте):

var s = document.createElement('script');
s.src = chrome.extension.getURL('script.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
    s.remove();
};

// Event listener
document.addEventListener('RW759_connectExtension', function(e) {
    // e.detail contains the transferred data (can be anything, ranging
    // from JavaScript objects to strings).
    // Do something, for example:
    alert(e.detail);
});

script.js - расположен в каталоге расширений, он будет вставлен в саму страницу:

setTimeout(function() {
    /* Example: Send data from the page to your Chrome extension */
    document.dispatchEvent(new CustomEvent('RW759_connectExtension', {
        detail: GLOBALS // Some variable from Gmail.
    }));
}, 0);

Поскольку этот файл загружается через расширение Chrome: URL из DOM, необходимо добавить «script.js» в раздел web_accessible_resources файла манифеста. В противном случае Chrome откажется загружать файл скрипта.

Вы должны использовать как можно меньше логики на веб-странице и обрабатывать большую часть своей логики в скрипте контента. Это имеет несколько причин. Прежде всего, любой сценарий, внедренный на странице, выполняется в том же контексте, что и веб-страница, поэтому веб-страница может (преднамеренно или непреднамеренно) изменять методы JavaScript / DOM таким образом, что ваше расширение перестает работать. Во-вторых, у скрипта контента есть доступ к дополнительным функциям, таким как ограниченное подмножество API-интерфейсов chrome. * И сетевые запросы разных источников (при условии, что расширение объявило разрешения для них).

20 голосов
/ 02 февраля 2013

Более современным решением для связи между расширением chrome content_script и javascript на странице было бы использование html5 postMessage API.Любые сообщения, отправленные в «окно», видны как из javascript на веб-странице, так и из content_script расширения.

content_script.js расширения:

window.addEventListener('message', function(event) {
    console.log('content_script.js got message:', event);
    // check event.type and event.data
});

setTimeout(function () {
    console.log('cs sending message');
    window.postMessage({ type: 'content_script_type',
                         text: 'Hello from content_script.js!'},
                       '*' /* targetOrigin: any */ );
}, 1000);

JavaScript, запущенный на веб-странице:

window.addEventListener('message', function(event) {
    console.log('page javascript got message:', event);
});

setTimeout(function() {
    console.log('page javascript sending message');
    window.postMessage({ type: 'page_js_type',
                         text: "Hello from the page's javascript!"},
                       '*' /* targetOrigin: any */);
}, 2000);

Также см. http://developer.chrome.com/extensions/content_scripts.html#host-page-communication

3 голосов
/ 17 августа 2013

Существует новый API-интерфейс для веб-страниц, позволяющий безопасно и без каких-либо побочных эффектов взаимодействовать (window.postMessage может иметь других слушателей!) К скрипту содержимого.

"С веб-страницы используйте API-интерфейсы runtime.sendMessage или runtime.connect для отправки сообщения определенному приложению или расширению"

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
  function(response) {
    if (!response.success)
    handleError(url);
});

"Из вашего приложения или расширения вы можете прослушивать сообщения с веб-страниц через API runtime.onMessageExternal или runtime.onConnectExternal, аналогичные обмену сообщениями между расширениями. Только веб-страница может инициировать соединение. [...] «

(из http://developer.chrome.com/extensions/messaging.html) Это все еще доступно только в канале разработчиков Chrome, но похоже, что это будет в следующей версии или около того.

Не спрашивайте меня, как это работает, это кажется очень запутанным. Как же chrome.runtime определяется на веб-странице? Что если сценарий уже определил эту переменную по какой-то причине? Я также не смог найти отчет об ошибке хрома, чтобы увидеть историю развития этой функции.

0 голосов
/ 29 мая 2019

Добавьте к своему контенту скрипт:

function executeOnPageSpace(code){

  // create a script tag
  var script = document.createElement('script')
  script.id = 'tmpScript'
  // place the code inside the script. later replace it with execution result.
  script.textContent = 
  'document.getElementById("tmpScript").textContent = JSON.stringify(' + code + ')'
  // attach the script to page
  document.documentElement.appendChild(script)
  // collect execution results
  let result = document.getElementById("tmpScript").textContent
  // remove script from page
  script.remove()
  return JSON.parse(result)

}

Теперь вы можете сделать:

let window = executeOnPageSpace('window')

или даже так:

executeOnPageSpace('window.location.href = "http://stackoverflow.com"')

ПРИМЕЧАНИЕ: я не проверял это для долго работающего кода.

0 голосов
/ 19 июля 2017

У меня был немного другой подход, основанный на доступных HTML-страницах вашего расширения.

Добавьте свою страницу в манифест:

"web_accessible_resources": ["variables.html"]

Создайте свою страницу (здесь, variables.html) и извлеките данные содержимого (т.е. window.contentVar):

<script type="text/javascript">
  $("#my-var-name").text(window["contentVar"]);
</script>
<div id="my-var-name" style="display: none;"></div>

Доступ из JavaScript вашего расширения:

var myVarName = $("#my-var-name").text();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...