Я учусь создавать расширения Chrome. Я только начал разрабатывать один, чтобы ловить события YouTube. Я хочу использовать его с YouTube Flash Player (позже я постараюсь сделать его совместимым с HTML5).
manifest.json:
{
"name": "MyExtension",
"version": "1.0",
"description": "Gotta catch Youtube events!",
"permissions": ["tabs", "http://*/*"],
"content_scripts" : [{
"matches" : [ "www.youtube.com/*"],
"js" : ["myScript.js"]
}]
}
myScript.js:
function state() { console.log("State Changed!"); }
var player = document.getElementById("movie_player");
player.addEventListener("onStateChange", "state");
console.log("Started!");
Проблема в том, что консоль дает мне «Начато!» , но нет "Государство изменилось!" когда я играю / приостанавливаю видео на YouTube.
Когда этот код помещен в консоль, он работал. Что я делаю неправильно?
player.addEventListener("onStateChange", state);
https://
илиhttp://
, этоwww.youtube.com/*
не позволит вам пакет расширения и будет бросать недостающее ошибку схема сепаратораОтветы:
Сценарии содержимого выполняются в среде «изолированного мира» . Вы должны внедрить свой
state()
метод в саму страницу.Если вы хотите использовать один из
chrome.*
API-интерфейсов в сценарии, вам необходимо реализовать специальный обработчик событий, как описано в этом ответе: Расширение Chrome - получение исходного сообщения Gmail .В противном случае, если вам не нужно использовать
chrome.*
API, я настоятельно рекомендую внедрить весь код JS на странице, добавив<script>
тег:Оглавление
Способ 1: добавить другой файл
Это самый простой / лучший метод, когда у вас много кода. Включите ваш фактический код JS в файл, например, в вашем расширении
script.js
. Затем пусть ваш контент-скрипт будет следующим (объяснено здесь: Google Chome «Ярлык приложения», пользовательский Javascript ):Примечание. Если вы используете этот метод, внедренный
script.js
файл необходимо добавить в"web_accessible_resources"
раздел ( пример ). Если вы этого не сделаете, Chrome откажется загружать ваш скрипт и отобразит в консоли следующую ошибку:Способ 2: внедрить встроенный код
Этот метод полезен, когда вы хотите быстро запустить небольшой фрагмент кода. (См. Также: Как отключить горячие клавиши facebook с расширением Chrome? ).
Примечание: литералы шаблонов поддерживаются только в Chrome 41 и выше. Если вы хотите, чтобы расширение работало в Chrome 40-, используйте:
Способ 2b: использование функции
Для большой части кода цитирование строки неосуществимо. Вместо использования массива можно использовать функцию и строку:
Этот метод работает, потому что
+
оператор над строками и функция преобразуют все объекты в строку. Если вы собираетесь использовать код более одного раза, целесообразно создать функцию, чтобы избежать повторения кода. Реализация может выглядеть так:Примечание. Поскольку функция сериализована, исходная область действия и все связанные свойства теряются!
Способ 3: использование встроенного события
Иногда вы хотите сразу запустить некоторый код, например, запустить некоторый код перед
<head>
созданием элемента. Это можно сделать, вставив<script>
тег с помощьюtextContent
(см. Метод 2 / 2b).Альтернативой, но не рекомендуется, является использование встроенных событий. Это не рекомендуется, поскольку, если на странице определена политика безопасности содержимого, которая запрещает встроенные сценарии, то прослушиватели встроенных событий блокируются. С другой стороны, встроенные сценарии, введенные расширением, все еще работают. Если вы все еще хотите использовать встроенные события, вот как:
Примечание. Этот метод предполагает отсутствие других глобальных прослушивателей событий, которые обрабатывают
reset
событие. Если есть, вы также можете выбрать одно из других глобальных событий. Просто откройте консоль JavaScript (F12), введитеdocument.documentElement.on
и выберите доступные события.Динамические значения в введенном коде
Иногда вам нужно передать произвольную переменную введенной функции. Например:
Чтобы внедрить этот код, вам нужно передать переменные в качестве аргументов анонимной функции. Будьте уверены, чтобы реализовать это правильно! Следующее не будет работать:
Решение заключается в использовании
JSON.stringify
перед передачей аргумента. Пример:Если у вас много переменных, целесообразно использовать
JSON.stringify
один раз, чтобы улучшить читаемость, следующим образом:источник
script-src
директивы, которая исключает источник расширения, метод 2 может быть заблокирован с помощью CSP, который исключает «unsafe-inline» `.script.parentNode.removeChild(script);
. Моя причина в том, что я люблю убирать беспорядок. Когда встроенный скрипт вставляется в документ, он немедленно исполняется, и<script>
тег можно безопасно удалить.location.href = "javascript: alert('yeah')";
любом месте вашего скрипта контента. Это проще для коротких фрагментов кода, а также для доступа к JS-объектам страницы.javascript:
. Код, охватывающий несколько строк, может работать не так, как ожидалось. Линия-комментарий (//
) будет укоротить остаток, так что это будет не в состоянии :location.href = 'javascript:// Do something <newline> alert(0);';
. Это можно обойти, если вы используете многострочные комментарии. Другая вещь, о которой следует быть осторожным, заключается в том, что результат выражения должен быть пустым.javascript:window.x = 'some variable';
приведет к выгрузке документа и замене фразой «некоторая переменная». При правильном использовании это действительно привлекательная альтернатива<script>
.Единственное
отсутствуетОтличный ответ Роба У - как связать введенный сценарий страницы и сценарий содержимого.На принимающей стороне (либо ваш скрипт контента, либо внедренный скрипт страницы) добавьте прослушиватель событий:
На стороне инициатора (скрипт контента или внедренный скрипт страницы) отправьте событие:
Ноты:
В Firefox, чтобы отправить объект (то есть не примитивное значение) из скрипта содержимого в контекст страницы, вы должны явно клонировать его в цель, используя
cloneInto
(встроенную функцию), иначе он потерпит неудачу с ошибкой нарушения безопасности ,источник
CustomEvent
Конструктор заменяет устаревшийdocument.createEvent
API.CustomEvent
конструктору. Я испытал 2 очень запутанных неудачи: 1. просто помещая одинарные кавычки вокруг «детализации», сбивало с толку значение,null
полученное слушателем моего Content Script. 2. Что еще более важно, по какой-то причине я должен былJSON.parse(JSON.stringify(myData))
или иначе это также стало быnull
. Учитывая это, мне кажется, что следующее утверждение разработчика Chromium - что алгоритм «структурированного клона» используется автоматически - не соответствует действительности. bugs.chromium.org/p/chromium/issues/detail?id=260378#c18Я также столкнулся с проблемой упорядочения загруженных скриптов, которая была решена путем последовательной загрузки скриптов. Нагрузка основана на ответе Роба W в .
Пример использования будет:
На самом деле, я немного новичок в JS, так что не стесняйтесь пинговать меня в лучшую сторону.
источник
formulaImageUrl
илиcodeImageUrl
, то вы фактически разрушаете функциональность страницы. Если вы хотите передать переменную на веб-страницу, я предлагаю присоединить данные к элементу script (e.g. script.dataset.formulaImageUrl = formulaImageUrl;
) и использовать, например,(function() { var dataset = document.currentScript.dataset; alert(dataset.formulaImageUrl;) })();
в сценарии для доступа к данным.dataset
?document.currentScript
указывает только на тег сценария во время его выполнения. Если вы когда-нибудь захотите получить доступ к тегу скрипта и / или его атрибутам / свойствам (напримерdataset
), вам нужно сохранить его в переменной. Нам нужен IIFE, чтобы получить замыкание для хранения этой переменной без загрязнения глобального пространства имен.return;
).в Content script я добавляю скрипт script к заголовку, который связывает обработчик onmessage, внутри обработчика, который я использую, eval для выполнения кода. В скрипте содержимого стенда я также использую обработчик onmessage, поэтому я получаю двустороннюю связь. Chrome Docs
pmListener.js - это сообщение прослушивателя URL
Таким образом, я могу иметь двухстороннюю связь между CS и Real Dom. Это очень полезно, например, если вам нужно прослушать события веб-скета или какие-либо переменные или события в памяти.
источник
Вы можете использовать созданную мной служебную функцию для запуска кода в контексте страницы и получения возвращенного значения.
Это делается путем сериализации функции в строку и внедрения ее на веб-страницу.
Утилита доступна здесь, на GitHub .
Примеры использования -
источник
Если вы хотите ввести чистую функцию вместо текста, вы можете использовать этот метод:
И вы можете передавать параметры (к сожалению, никакие объекты и массивы не могут быть преобразованы в строку) в функции. Добавьте это в голые вещи, вот так:
источник