Примеры того что может контентный скрипт:
- найти ключевые слова на странице и преобразовать их в гиперссылки
- найти разметку микроформата и извлечь информацию
- изменить стиль страницы – увеличить шрифты, сделать их более контрастными, убрать рекламные блоки и т.д.
- использовать chrome.* API
- использовать переменные или функции определенные на странице или другими контентными скриптами
- использовать переменные или функции определенные на других страницах расширения
Манифест
{ "name": "My extension", ... "content_scripts": [ { "matches": ["http://www.google.com/*"], "css": ["mystyles.css"], "js": ["jquery.js", "myscript.js"] } ], ... }
Есть альтернативный способ вставить свой код :
{ "name": "My extension", ... "permissions": [ "tabs", "http://www.google.com/*" ], ... }
Используя свойство content_scripts можно вставлять много скриптов. Каждый элемент массива может содержать следующие свойства:
Имя | Тип | Описание |
---|---|---|
matches | array of strings | Обязательно. Указывает на какие страницы будет вставляться контент-скрипт. |
exclude_matches | array of strings | Опционально. Исключения – на какие страницы скрипт вставляться не будет. |
css | array of strings | Опционально. Список файлов CSS, которые будут подключаться к страницам. Подключаются в порядке объявления. |
js | Опционально. Список файлов JavaScript, которые будут подключаться к страницам. Подключаются в порядке объявления. | |
run_at | string | Опционально. Задает когда js файлы будут подключаться:
Какой вариант лучше зависит от того как долго загружается документ (на самом деле лучше – значение по умолчанию). По умолчанию document_idle |
all_frames | boolean | Опционально. Будет ли скрипт загружаться во всех фреймах или только в главном. По умолчанию false – скрипт запускается только в главном фрейме. |
include_globs | array of string | Опционально. Применяется после matches чтобы скрипт подключался только для URL которые входят сюда. Эмулирует поведение @include в Greasemonkey. . |
exclude_globs | array of string | Опционально. Аналогичным образом эмулирует @exclude. |
Паттерны
Скрипт подключается если он входит в matches или include_globs и при этом не входит в exclude_matches или exclude_globs. matches – обязательное свойство, прочие используются только чтобы уточнить к каким страницам скрипт будет подключаться.
Пусть в matches задано [http://*.nytimes.com/*]
- Если exclude_matches ["*://*/*business*"], тогда скрипт подключится к "http://www.nytimes.com/health" но не к "http://www.nytimes.com/business".
- Если include_globs ["*nytimes.com/???s/*"], тогда он подключится к "http:/www.nytimes.com/arts/index.html" и "http://www.nytimes.com/jobs/index.html" но не к "http://www.nytimes.com/sports/index.html".
- Если exclude_globs is ["*science*"], тогда скрипт подключится к "http://www.nytimes.com" но не к "http://science.nytimes.com" или "http://www.nytimes.com/science".
Вопрос на засыпку: подключится ли скрипт http://www.nytimes.com/jobs/business.html ?
Свойства include_globs и exclude_globs имеют более расширенный синтаксис по сравнению с matches и exclude_matches. * означает произвольную последовательность символов, включая пустую строку, а знак вопроса – одиночный символ.
Программное внедрение скриптов
Контент-скрипт можно внедрить на страницу программно – когда логика определения страницы куда необходимо внедрить скрипт выходит за рамки паттернов. Для этого требуется разрешение кросс-скриптинга в отношении этого сайта и на работу с вкладками, или “activeTab” – для внедрения в любой сайт в текущей вкладке. Выше был приведен примеры манифеста который позволяет внедрять контентные скрипты на сайт гугла. Первый пример – статическое внедрение, скрипт подключается всегда, второй – программное.
Делается это методами
- tabs.executeScript
- tabs.insertCSS
Пример:
chrome.browserAction.onClicked.addListener(function(tab) { chrome.tabs.executeScript({ code: 'document.body.style.backgroundColor="red"' }); });
При нажатии на иконку в панели инструментов, в текущую открытую страницу будет внедрен скрипт меняющий цвет фона на красный.
Обычно удобнее хранить скрипт в файле, метод executeScript позволяет это:
chrome.tabs.executeScript(null, {file: "content_script.js"});
Среда исполнения
Контентные скрипты выполняются в специальном, изолированном, окружении. Они имеют доступ к DOM страницы, куда внедрен скрипт, но не к переменным и скриптам этой страницы. Выглядит это так, будто скрипт работает на странице в гордом одиночестве. То же верно и в обратную сторону – скрипты на странице не видят внедренный. Хотя иногда это неудобно – хотелось бы вмешиваться в процессы происходящие на странице более агрессивно, но в общем случае это защищает нас от жуткой путаницы:
Что будет, если контент скрипт загружает одну версию популярного js-фреймворка, а страница – другую? При этом имена многих функций и переменных совпадают, но отличаются количеством параметров и реализацией.
Но все же, лучше бы такую возможность, подключаемую отдельной опцией манифеста, сделали.
Вы можете назначить собственные обработчики событий – они будут работать параллельно с родными. Исполняются обработчики в том порядке, в каком они были назначены.
Но взаимодействие возможно через DOM. Проще говоря, если скрипт на странице знает о существовании расширения, они могут обмениваться командами через механизм сообщений.
ContentScript.js
var port = chrome.runtime.connect(); window.addEventListener("message", function(event) { // We only accept messages from ourselves if (event.source != window) return; if (event.data.type && (event.data.type == "FROM_PAGE")) { console.log("Content script received: " + event.data.text); port.postMessage(event.data.text); } }, false);
Page.html
document.getElementById("theButton").addEventListener("click", function() { window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*"); }, false);
В этом примере вебстраница назначает обработчик нажатия кнопки, который пошлет сообщение контентному скрипту, а тот отправит его дальше, расширению (background или event странице).
Безопасность
- Будьте аккуратны с кросс-сайтовым скриптингом. Если вы берете какой-то контент на стороннем сайте и внедряете его на текущую страницу, то ответственность за безопасность лежит на вас. Особенно когда речь идет о https страницах, на которых, предположительно, может оказаться конфиденциальная информация.
- Хотя ваш скрипт изолирован от скриптов страницы, все же следует принимать меры предосторожности, в частности не использовать eval, а передавать только данные в формате JSON.
Обращение к файлам расширения
Выполняется следующим образом:
//Code for displaying <extensionDir>/images/myimage.png: var imgURL = chrome.extension.getURL("images/myimage.png"); document.getElementById("someImage").src = imgURL;
Здравствуйте, вы не подскажите, как удалить загруженный chrome.tabs.executeScript?
ОтветитьУдалитьОднако есть ограничения. Контентный скрипт не может
ОтветитьУдалитьиспользовать chrome.* API
Однако chrome.* работает!
Этот комментарий был удален автором.
УдалитьЗдравствуйте. Подскажите, пожалуйста, как получить данные из popup.html на страницу сайта?В popup в textarea клиент редактирует данные, которые сохраняются в localStorage[]. Далее клиент выделяет текст на странице, и по этому событию генерируется окно рядом с курсором, данные на котором должны сопоставлять выделенный текст и текст из textarea-popup. Никак не получатся получить textarea-popup (или localStorage-popup, или cookie-popup).
ОтветитьУдалить