Как написать скрипт для браузера хром

Время на прочтение
7 мин

Количество просмотров 278K

Доброго времени суток всем желающим приобщиться к миру пользовательских скриптов (они же userscript, userJS, юзерскрипты).

В этой статье я хочу поведать о том, что такое юзерскрипты, c чем их едят и, главное, как их готовят!

Внимание: предполагается минимальное знание javascript.
На практике доказано: юзерскрипты может писать человек, не знакомый с программированием, но обладающий усидчивостью и желанием изучить javascript!
О том, что такое javascript и как с ним обращаться, можно узнать на javascript.ru.

Что такое юзерскрипты?

Кратко: юзерскрипт — это программа, написанная на языке JavaScript, хранящаяся на компьютере пользователя и подключаемая браузером на определенных страницах. Юзерскрипт представляет собой файл с расширением .user.js (именно по расширению браузеры понимают, что файл является юзерскриптом), содержащий метаданные и непосредственно javascript-код.

При подключении к странице юзерскрипт выполняется так же, как и обычные javascript-сценарии.
У юзерскрипта есть доступ к DOM-дереву страницы, в контексте которой он выполняется.
В современных браузерах у юзерскрипта есть доступ к localStorage и прочим HTML5 API.

Юзерскрипты поддерживаются всеми основными современными браузерами (и даже кое-как поддерживаются IE7 и выше).

Самый известный портал юзерскриптов — userscripts.org. Тут можно найти хранилище скриптов, инструменты управления своими скриптами на портале и, что не маловажно, отзывчивый форум (всё на английском).

Немного общей теории

Самыми распространенными являются скрипты под расширение GreaseMonkey для браузера Firefox.
Подробную информацию по GreaseMonkey и написанию юзерскриптов под GreaseMonkey можно узнать на http://wiki.greasespot.net.
Так сложилось исторически, что данный браузер был (и остаётся по сей день) первым, в котором поддержка юзерскриптов была выполнена на высоком уровне.

Не все скрипты, написанные для GreaseMonkey, могут запускаться в других браузерах. Причина в

криворукости

том, что во многих скриптах используется GM API — набор javascript-функций, специфичных для GreaseMonkey.

Однако, проще всего писать юзерскрипты под браузер Google Chrome.
На это есть ряд причин:

  1. Простым скриптам не нужна поддержка GM API (библиотека, доступная в GreaseMonkey)
  2. Google Chrome, в отличие от Firefox+GreaseMonkey, имеет отличнейший дебаггер.
  3. Сообщения об ошибках юзерскрипта в Firefox ужасны! Если вы не обладаете даром телепатиитвердыми знаниями GreaseMonkey и javascript, написание юзерскрипта может превратится в муки!
  4. Google Chrome не требует расширений для поддержки юзерскриптов. Интерфейс для удаления/отключения юзерскриптов доступен «из коробки».

Очевидные минусы Google Chrome:

  1. Нет доступа к «родному» window.
  2. Не поддерживается директива @ include метаданных. Директива @ match глючит, можно сказать, что она тоже не поддерживается.

Особенности юзерскриптов

Код юзерскриптов может посмотреть любой желающий, вооруженный блокнотом.
Базовые знания javascript позволяют отсечь угрозу установки шпионских и вредоносных скриптов простым анализом кода скрипта (придётся задействовать мозг).

Важно:Если вы не доверяете автору скрипта, главное удостовериться, что скрипт не отсылает пользовательские данные (куки, вводимый текст) на сторонние сервисы!

Все юзерскрипты запускаются после того, как загрузились все основные элементы страницы, но ещё не загрузились картинки. Можно сказать, что юзерскрипты грузятся по событию DOMContentLoaded.
В любом случае, проверки на window.onload не нужны.

Каждый браузер накладывает свои ограничения на исполнение юзерскриптов, но в целом юзерскрипты могут делать почти всё, что могут скрипты на странице.
Чаще всего юзерскрипты используются для изменения интерфейса страницы или для добавления плюшек, блекджека

и шлюх

(юзерскрипты для социальных сетей).
Бывают и продвинутые юзерскрипты, которые представляют собой самостоятельные программы (аукционные и игровые боты, плагины-помощники и т.д).

Анатомия юзерскриптов

Юзерскрипт — это текстовый файл с расширением user.js. В начале файла располагается блок метаданных — описание самого скрипта. После блока метаданных следует javascript-код, который и будет исполняться браузером.

Рассмотрим тестовый скрипт, который показывает alert с текстом на определенной странице.

// ==UserScript==
// @name myUserJS
// @description Мой самый первый юзерскрипт 
// @author Vasya Pupkin
// @license MIT
// @version 1.0
// @include http://userscripts.org/*
// ==/UserScript==
// [1] Оборачиваем скрипт в замыкание, для кроссбраузерности (opera, ie)
(function (window, undefined) {  // [2] нормализуем window
    var w;
    if (typeof unsafeWindow != undefined) {
        w = unsafeWindow
    } else {
        w = window;
    }
    // В юзерскрипты можно вставлять практически любые javascript-библиотеки.
    // Код библиотеки копируется прямо в юзерскрипт.
    // При подключении библиотеки нужно передать w в качестве параметра окна window
    // Пример: подключение jquery.min.js
    // (function(a,b){function ci(a) ... a.jQuery=a.$=d})(w);

    // [3] не запускаем скрипт во фреймах
    // без этого условия скрипт будет запускаться несколько раз на странице с фреймами
    if (w.self != w.top) {
        return;
    }
    // [4] дополнительная проверка наряду с @include
    if (/http://userscripts.org/.test(w.location.href)) {
        //Ниже идёт непосредственно код скрипта
        alert("Userscripts приветствует вас навязчивым окном.");
    }
})(window);

Важно: данный скрипт представляет собой оболочку для кроссбраузерных юзерскриптов. Этот же скрипт, но с английскими комментариями, можно стянуть с pastebin.com и использовать безнаказанно.

В самом начале располагается блок метаданных (в виде комментария).

// ==UserScript==
// ...
// ==/UserScript==

Этот блок состоит из директив описания юзерскрипта. Ниже в таблице представлены основные директивы и их назначение.

Важно:Все директивы, как и сам блок метаданных, могут отсутствовать.

Директива Назначение
@ name Название юзерскрипта.
Это название будет отображаться в интерфейсе управления
юзерскриптами. Если директива отсутствует, то название
юзерскрипта будет таким же, как и название файла.
@ description Описание юзерскрипта.
Это описание будет отображаться в интерфейсе управления
юзерскриптами.
@ namespace Пространство имён.
Определяет уникальность набора скриптов.
Сюда можно вписать имя домена, принадлежащего вам. Или любую другую строку.
Считайте, что это второе название скрипта. Обязательная директива для Trixie!
@ author Имя автора.
@ license Название лицензии, по которой распространяется юзерскрипт.
@ version Номер версии юзерскрипта.
К сожалению, механизма автообновления нету ни в одном браузере,
поэтому номер версии — это просто цифры, которые отображаются в интерфейсе.
@ include Директива описания url страницы,
на которой нужно запускать юзерскрипт.
Поддерживает вайлдкард *(применимо в GreaseMoneky, Opera, IE).
Для каждого отдельного url нужно использовать отдельную директиву @ include.
@ exclude Директива описания url страницы,
на которой не нужно запускать юзерскрипт.
Поддерживает вайлдкард *(применимо в GreaseMonkey, Opera, IE).
Для каждого отдельного url нужно использовать отдельную директиву @ exclude.
@ match Аналогично @ include, но с более жесткими ограничениями
(применимо в GreaseMonkey старше 0.9.8, Google Chrome).
Подробнее об ограничениях и формате директивы можно
прочитать на этой странице.
Для каждого отдельного url нужно использовать отдельную директиву @ match.

Важно: Как показала практика, полагаться на директиву @ match в юзерскриптах не стоит.
Google Chrome периодически отказывается учитывать @ match
и запускает юзерскрипты на всех страницах.
Для предотвращения такой ситуации в юзерскрипты,
которые будут запускаться не только в Firefox,
нужно добавлять код проверки адреса страницы (см. ссылку [4] в коде юзерскрипта).

Важно: При отсутствии директив @ include или @ match, юзерскрипты будут запускаться на всех страницах.

В нашем юзерскрипте использован ряд хитростей:

  1. Для того, чтобы юзерскрипты имели одинаковое поведение и не загрязняли глобальную область видимости, код оборачивается в замыкание (см. [1] в коде скрипта).
  2. Для правильного подключения библиотек внутри юзерскрипта и для обхода некоторых хитрых особеннойстей GreaseMonkey, необходимо «нормализовать» ссылку на глобальную область видимости window (см. [2] в коде скрипта).
  3. Для того, чтобы юзерскрипт не запускался несколько раз на одной и той же странице, необходимо останавливать работу при запуске юзерскрипта во фреймах (см. [3] в коде скрипта).
  4. Для того, чтобы юзерскрипт запускался только на нужных нам страницах, необходимо явно проверять url страницы (см. [4] в коде скрипта).
  5. Благодаря такой структуре, юзерскрипт может быть относительно просто преобразован в букмарклет.

Результат

Наш юзерскрипт готов к использованию!
Нет, серьёзно, вы можете скопировать код юзерскрипта в файл, назвать его my.user.js, и закинуть полученный файл в браузер (используйте Chrome или Firefox с установленным GreaseMonkey).

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

Остаётся вопрос: как «раздать» наш скрипт пользователям (ведь мы писали скрипт не только для себя)?
Варианты:

  • Зарегестрироваться на портале userscripts.org и загружать скрипты туда.
  • Завести репозиторий на code.google.com или github.com.
  • Создать свой простой сервис/сайт/страничку.
    Важно:Если хотите, чтобы у пользователей GreaseMonkey автоматически открывался диалог установки юзерскрипта, отдавайте файл прямиком с файловой системы (url файла должен заканчиваться на .user.js). В противном случае пользователь увидит исходный код скрипта и панель с кнопкой «установить». Эта кнопка не работает!

Рецепт для непрограммистов (похожими методами пишется ~70% скриптов):

  1. Придумываем, что будет делать наш юзерскрипт (перекрашивать ссылки, например)
  2. Берём шаблон из статьи
  3. Сохраняем в файл my.user.js
  4. Удаляем строку с alert(…).
  5. Идём на форум (userscripts.org или любой форум по javascript).
  6. Спамим, флудим и достаём людей вопросами «как перекрашивать ссылки», «дайте код» и т.д.
  7. Изменяем метаданные и проверку url страницы на нужные нам.
  8. Вставляем полученный на форуме код в юзерскрипт.
  9. Сохраняем файл.
  10. PROFIT!!1!

Полезные ссылки:

  • Userscripts.org
  • wiki.greasespot.net
  • Userscript -> Firefox Extension Compiler
  • Writing userscripts
  • Правила директивы @ match

Список статей:

  1. » Учимся писать userscript’ы
  2. Userscripts. Углубляемся.
  3. Userscripts. Упаковываем юзерскрипт для Chrome
  4. Usersctripts. Кроссдоменные запросы

P.S. Хотелось бы увидеть блог Userscripts на хабре. Ибо не одним GreaseMonkey едины.

В конце 2020 года мы делали проект со снежинками — писали специальный скрипт, который запускал падающий снег на сайтах. Если бы мы хотели сделать такой снег на любом своём сайте, это не составило бы труда: добавляешь скрипт в код страницы, и готово.

А вот на чужих сайтах была проблема. Скрипт нужно было вставлять через консоль. А если на сайте была настроена политика безопасности, которая запрещает запуск внешних скриптов, то магия не срабатывала. 

Сегодня мы это исправим — сделаем расширение для браузера, которое может запускать любой скрипт на любой странице. Мы охватим принцип, на основе которого вы сможете сделать собственные расширения, в том числе намного более сложные. 

👉 Что такое расширение

Расширение для Chrome — это небольшая программа, которая выполняется внутри браузера и помогает расширить возможности сайтов. Сила расширения в том, что оно может выполняться прямо из меню браузера и не зависит от политик безопасности. 

Примеры того, что может сделать расширение: 

  • Сохранить ваши пароли и другие личные данные,
  • Выдрать из страницы скрытые данные (например, ссылку на скачивание музыки).
  • Менять что-то на странице, например, отключать рекламу, переводить текст, удалять ненужное.
  • Собирать статистику вашей работы в интернете.
  • Подключаться к другим сервисам (почте, чатам, файлообменникам) и взаимодействовать с ними из браузера.

В этой статье

Мы сделаем самое простое расширение для браузера Chrome, которое позволит запускать скрипт со снежинками на любом сайте, независимо от настроенной политики безопасности. Для этого воспользуемся официальным руководством Google по созданию расширений.

Манифест

В каждом расширении для браузера должен быть манифест — документ, в котором написано:

  • как называется расширение;
  • к чему расширение может получить доступ;
  • какие скрипты будут работать в фоне;
  • как должна выглядеть иконка расширения;
  • что показать или что выполнить, когда пользователь нажмёт на иконку расширения.

Манифест задаёт общие правила для всего расширения, поэтому манифест — единственный обязательный компонент. Можно обойтись без иконок и скриптов, но манифест обязательно должен быть.Каждый манифест хранится в файле manifest.json — создадим пустой файл с таким именем и напишем внутри такое:

{
«name»: «Запускаем снежинки на любом сайте»,
«description»: «Проект журнала Код»,
«version»: «1.0»,
«manifest_version»: 3
}

Первые две строчки — это название и подробное описание расширения. Третья отвечает за номер версии расширения, а последняя говорит браузеру, какая версия манифеста используется в описании. На момент выхода статьи в феврале 2021 года используется третья версия.

Сохраняем файл и всё, расширение готово. Оно ничего не умеет, ничего не делает, зато мы уже можем добавить его в браузер. Для этого запускаем Хром и в адресной строке пишем:

chrome://extensions/

Мы попадаем на страницу, которая нам покажет все установленные расширения:

Делаем своё расширение для браузера за 10 минут

Чтобы добавить своё расширение, в правом верхнем углу включаем режим разработчика, а затем нажимаем «Загрузить распакованное расширение»:

Делаем своё расширение для браузера за 10 минут

Теперь выбираем папку, в которой лежит наш манифест:

Делаем своё расширение для браузера за 10 минут

Отлично, мы только что добавили в браузер новое расширение:

Делаем своё расширение для браузера за 10 минут

Теперь мы можем обновлять наш манифест, класть в ту же папку дополнительные файлы, а для обновления в браузере достаточно будет нажать на круглую стрелку на карточке расширения.

Чтобы было проще работать и тестировать расширение, закрепим его на панели браузера:

Делаем своё расширение для браузера за 10 минут

Иконки

У расширения есть две иконки, которыми мы можем управлять: 

  1. Картинка в карточке расширения на странице настроек.
  2. Иконка на панели браузера.

Чтобы не рисовать всё с нуля, скачаем папку с иконками из того же руководства Google и положим её в ту же папку, что и манифест:

Теперь добавим иконки в манифест. За картинку в карточке отвечает блок icon, а за иконку на панели —  блок action. Разные размеры картинки нужны для того, чтобы на разных мониторах с любой плотностью пикселей иконки выглядели хорошо:

{
  "name": "Запускаем снежинки на любом сайте",
  "description": "Проект журнала Код",
  "version": "1.0",
  "manifest_version": 3,

  "action": {
    "default_icon": {
      "16": "/images/get_started16.png",
      "32": "/images/get_started32.png",
      "48": "/images/get_started48.png",
      "128": "/images/get_started128.png"
    }
  },
  "icons": {
    "16": "/images/get_started16.png",
    "32": "/images/get_started32.png",
    "48": "/images/get_started48.png",
    "128": "/images/get_started128.png"
  }
}

Сохраняем манифест, обновляем расширение на странице настроек и смотрим результат:

Добавляем иконки в манифест

Настраиваем разрешения

Разрешения — это то, что браузер позволяет делать расширению со страницами и с их содержимым. Для запуска снежинок нам нужно сделать две вещи:

  1. Понять, какая вкладка сейчас активная, чтобы запустить снежинки именно на ней.
  2. Запустить наш скрипт со снежинками.

Чтобы получить доступ к активной вкладке и к запуску скриптов, добавим в манифест такую строку:

"permissions": ["activeTab", "scripting"],

Показываем меню

Если мы сейчас нажмём на иконку расширения на панели браузера, то ничего не призойдёт, потому что мы ничего не запрограммировали. Исправим это — сделаем так, чтобы при нажатии расширение показывало кнопку запуска. Когда расширение будет уметь больше, вместо одной кнопки можно будет показать целое меню.

Чтобы сделать всплывающее меню, добавим в манифест в раздел action такую строку:

    "default_popup": "popup.html",

Она означает, что при нажатии на иконку мы увидим рядом с ней мини-страничку, на которой что-то будет.Создадим в той же папке расширения файл popup.html и добавим в него такой код:

<!DOCTYPE html>
<html lang="ru">
  <head>
  	<meta charset="UTF-8">
    <style type="text/css">

    	/* задаём размеры кнопки и размер текста на кнопке  */
    	button {
	      font-size: 12px;
		  height: 40px;
		  width: 80px;
		}
    </style>
  </head>
  <body>
  	<!-- создаём кнопку на странице -->
    <button id="snow">Запустить снежинки</button>
    <!-- подключаем скрипт, который обработает нажатие на эту кнопку -->
    <script src="popup.js"></script>
  </body>
</html>

Чтобы браузер не ругался, что у нас нет файла popup.js, создадим пустой файл с таким названием и положим его в ту же папку:

Показываем меню расширения

Сохраняем манифест, обновляем его на странице настроек и видим, что у нашего расширения появилось меню с кнопкой:

Показываем меню расширения

Запускаем снежинки

Вся магия будет происходить в файле popup.js — откроем его и добавим такой код:

// получаем доступ к кнопке
let snow = document.getElementById("snow");
// когда кнопка нажата — находим активную вкладку и запускаем нужную функцию
snow.addEventListener("click", async () => {
  // получаем доступ к активной вкладке
  let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  // выполняем скрипт
  chrome.scripting.executeScript({
  	// скрипт будет выполняться во вкладке, которую нашли на предыдущем этапе
    target: { tabId: tab.id },
    // вызываем функцию, в которой лежит запуск снежинок
    function: snowFall,
  });
});

// запускаем снег
function snowFall() {
}

Последнее, что нам осталось сделать, — положить в функцию snowFall() полный код скрипта из проекта со снежинками и сохранить файл.

Проверка

В прошлый раз мы не смогли запустить скрипт на любой странице Яндекса — мешала политика безопасности. Теперь всё работает:

Проверяем расширение

Скачать упакованное расширение. Перед установкой его нужно распаковать в любую папку.


June 27, 2014

javascript userjs frontend Chromium browser russian

В интернете много сайтов на которых реализована возможность пролистывать страницу вверх без помощи мыши или полосы прокрутки. Но в то же время еще есть сайты где такой реализации нет. «Почему бы не попробовать написать скрипт который бы добавлял такую кнопку на все сайты?» — подумал я и принялся за реализацию. Такие скрипты называются пользовательскими и имеют расширение *.user.js. Почитать к примеру можно на хабре. К сожалению без «подводных камней» не обходится. Существуют некоторые различия в реализации userjs под разные браузеры. Я остановлюсь на описании реализации нашего userjs скрипта как расширения для браузера Google Chrome.

manifest.json

Обязательным для расширения Google Chrome является файл manifest.json в котором описываются параметры, пути к внешним файлам (*.js, *.css и др.), поддержка версии и т.п. для расширения. Подробнее о файле можно почитать тут. В нашем случае файл manifest.json выглядит следующим образом:

{
    "manifest_version": 2,
    "content_scripts": [ {
        "exclude_globs":    [  ],
        "include_globs":    [ "*" ],
        "js":               [ "jquery.js", "backTopUserJS.user.js" ],
        "css":              [ "css/style.css" ],
        "matches":          [   "http://*/*",
                                "https://*/*"
                            ],
        "run_at": "document_end"
    } ],
    "converted_from_user_script": true,
    "description":  "Back top userscript extension for google chrome",
    "name":         "backTopUserJS",
    "version":      "1"
}

Для удобства мы используем библиотеку JQuery которую положили рядом с файлом manifest.json и основным файлом скрипта (в нашем случае это backTopUserJS.user.js). Его содержимое следующее:

// ==UserScript==
// @name backTopUserJS
// @author Aleksandr Filatov
// @license MIT
// @version 1.0
// ==/UserScript==

function main() {
    var disp = $(window).scrollTop() > 400 ? 'block' : 'none';
    var $upButton = $('<div class="up-button" title="Наверх" style="display:' + disp + '">Наверх</div>');

    $(document).find('body').append($upButton);
    $upButton.click(function () {
        $('html, body').animate({ scrollTop: 0 }, 'slow');
    });

    $(window).scroll(function () {
        if ($(window).scrollTop() > 400) $upButton.fadeIn('slow');
        else $upButton.fadeOut('slow');
    });
};

var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);

Думаю скрипт достаточно понятен, чтобы его подробно рассматривать. Пояснить стоит лишь последние 3 строчки. На самом деле это мелкий хак, который вставляет наш скрипт в код страницы сайта. Если кто-то из вас найдет способ лучше можете написать к комментах свои фиксы :)

Установка расширения в браузере

В Google Chrome можно устанавливать пользовательские скрипты, аналогично другим браузерам, но поскольку Google печется о нашей с вами безопасности, то их приходится оборачивать в расширения для браузера. Разберем установку по шагам.

Создаем папку для нашего расширения например так C:MyChromeExtensionUserJS

Для каждого расширения создаем свою директорию например в нашем случае назовем ее так C:MyChromeExtensionUserJSbackTopUserJS. Добавляем файлы расширения в эту директорию.

Заходим «О браузере Google Chrome» -> вкладка «Расширения» или в адресной строке пишем chrome://extensions/

Ставим галочку «Режим разработчика»
developer_mode

Нажимаем кнопку «Загрузить распакованное расширение» и выбираем директорию нашего расширения. Нажимаем «OK».

Расширение установлено и готово к работе. Чтобы обновить расширения после того как вы внесли в него изменения достаточно просто нажать кнопку «Обновить расширение» или в режиме разработчика сочетание клавиш Ctrl+R.

Итог

Посмотреть исходники скрипта можно на github. Скрипт не претендует на звание идеального, а служит лишь примером и толчком к написанию собственных пользовательских скриптов для Google Chrome.

Manifest

To use the chrome.scripting API, declare the "scripting" permission in the manifest plus the host permissions for the pages to inject scripts into. Use the "host_permissions" key or the activeTab permission, which grants temporary host permissions. The following example uses the activeTab permission.

{
"name": "Scripting Extension",
"manifest_version": 3,
"permissions": ["scripting", "activeTab"],
...
}

Usage

You can use the chrome.scripting API to inject JavaScript and CSS into websites. This is similar to what you can do with content scripts. But by using the chrome.scripting namespace, extensions can make decisions at runtime.

Injection targets

You can use the target parameter to specify a target to inject JavaScript or CSS into.

The only required field is tabId. By default, an injection will run in the main frame of the specified tab.

function getTabId() { ... }

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("script injected"));

To run in all frames of the specified tab, you can set the allFrames boolean to true.

function getTabId() { ... }

chrome.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
files : [ "script.js" ],
})
.then(() => console.log("script injected in all frames"));

You can also inject into specific frames of a tab by specifying individual frame IDs. For more information on frame IDs, see the chrome.webNavigation API.

function getTabId() { ... }

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
frameIds : [ frameId1, frameId2 ],
files : [ "script.js" ],
})
.then(() => console.log("script injected on target frames"));

You cannot specify both the frameIds and allFrames properties.

Injected code

Extensions can specify the code to be injected either via an external file or a runtime variable.

Files

Files are specified as strings that are paths relative to the extension’s root directory. The following code will inject the file script.js into the main frame of the tab.

function getTabId() { ... }

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("injected script file"));

Runtime functions

When injecting JavaScript with scripting.executeScript(), you can specify a function to be executed instead of a file. This function should be a function variable available to the current extension context.

function getTabId() { ... }
function getTitle() { return document.title; }

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
func : getTitle,
})
.then(() => console.log("injected a function"));

function getTabId() { ... }
function getUserColor() { ... }

function changeBackgroundColor() {
document.body.style.backgroundColor = getUserColor();
}

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
func : changeBackgroundColor,
})
.then(() => console.log("injected a function"));

You can work around this by using the args property:

function getTabId() { ... }
function getUserColor() { ... }
function changeBackgroundColor(backgroundColor) {
document.body.style.backgroundColor = backgroundColor;
}

chrome.scripting
.executeScript({
target : {tabId : getTabId()},
func : changeBackgroundColor,
args : [ getUserColor() ],
})
.then(() => console.log("injected a function"));

Runtime strings

If injecting CSS within a page, you can also specify a string to be used in the css property. This option is only available for scripting.insertCSS(); you can’t execute a string using scripting.executeScript().

function getTabId() { ... }
const css = "body { background-color: red; }";

chrome.scripting
.insertCSS({
target : {tabId : getTabId()},
css : css,
})
.then(() => console.log("CSS injected"));

Handling results

The results of executing JavaScript are passed to the extension. A single result is included per-frame. The main frame is guaranteed to be the first index in the resulting array; all other frames are in a non-deterministic order.

function getTabId() { ... }
function getTitle() { return document.title; }

chrome.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
func : getTitle,
})
.then(injectionResults => {
for (const {frameId, result} of injectionResults) {
console.log(`Frame ${frameId} result:`, result);
}
});

scripting.insertCSS() does not return any results.

Promises

If the resulting value of the script execution is a promise, Chrome will wait for the promise to settle and return the resulting value.

function getTabId() { ... }
async function addIframe() {
const iframe = document.createElement("iframe");
const loadComplete =
new Promise(resolve => iframe.addEventListener("load", resolve));
iframe.src = "https://example.com";
document.body.appendChild(iframe);
await loadComplete;
return iframe.contentWindow.document.title;
}

chrome.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
func : addIframe,
})
.then(injectionResults => {
for (const frameResult of injectionResults) {
const {frameId, result} = frameResult;
console.log(`Frame ${frameId} result:`, result);
}
});

Examples

Unregister all dynamic content scripts

The following snippet contains a function that unregisters all dynamic content scripts the extension has previously registered.

async function unregisterAllDynamicContentScripts() {
try {
const scripts = await chrome.scripting.getRegisteredContentScripts();
const scriptIds = scripts.map(script => script.id);
return chrome.scripting.unregisterContentScripts(scriptIds);
} catch (error) {
const message = [
"An unexpected error occurred while",
"unregistering dynamic content scripts.",
].join(" ");
throw new Error(message, {cause : error});
}
}

Unregistering content scripts will not remove scripts or styles that have already been injected.

executeScript

chrome.scripting.executeScript(
  injection:
ScriptInjection,
  callback?:
function,

)

Injects a script into a target context. The script will be run at document_idle. If the script evaluates to a promise, the browser will wait for the promise to settle and return the resulting value.

Parameters

  • The details of the script which to inject.

  • callback

    function optional

    The callback parameter looks like:
    (results:
    InjectionResult[])
    =>

    void

Returns

  • Promise<InjectionResult[]>

    Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

getRegisteredContentScripts

chrome.scripting.getRegisteredContentScripts(
  filter?:
ContentScriptFilter,
  callback?:
function,

)

Returns all dynamically registered content scripts for this extension that match the given filter.

Parameters

  • filter

    ContentScriptFilter optional

    An object to filter the extension’s dynamically registered scripts.

  • callback

    function optional

    The callback parameter looks like:
    (scripts:
    RegisteredContentScript[])
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

insertCSS

chrome.scripting.insertCSS(
  injection:
CSSInjection,
  callback?:
function,

)

Inserts a CSS stylesheet into a target context. If multiple frames are specified, unsuccessful injections are ignored.

Parameters

  • The details of the styles to insert.

  • callback

    function optional

    The callback parameter looks like:
    ()
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

registerContentScripts

chrome.scripting.registerContentScripts(
  scripts:
RegisteredContentScript[],
  callback?:
function,

)

Registers one or more content scripts for this extension.

Parameters

  • Contains a list of scripts to be registered. If there are errors during script parsing/file validation, or if the IDs specified already exist, then no scripts are registered.

  • callback

    function optional

    The callback parameter looks like:
    ()
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

removeCSS

chrome.scripting.removeCSS(
  injection:
CSSInjection,
  callback?:
function,

)

Removes a CSS stylesheet that was previously inserted by this extension from a target context.

Parameters

  • The details of the styles to remove. Note that the css, files, and origin properties must exactly match the stylesheet inserted through insertCSS. Attempting to remove a non-existent stylesheet is a no-op.

  • callback

    function optional

    The callback parameter looks like:
    ()
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

unregisterContentScripts

chrome.scripting.unregisterContentScripts(
  filter?:
ContentScriptFilter,
  callback?:
function,

)

Unregisters content scripts for this extension.

Parameters

  • filter

    ContentScriptFilter optional

    If specified, only unregisters dynamic content scripts which match the filter. Otherwise, all of the extension’s dynamic content scripts are unregistered.

  • callback

    function optional

    The callback parameter looks like:
    ()
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

updateContentScripts

chrome.scripting.updateContentScripts(
  scripts:
RegisteredContentScript[],
  callback?:
function,

)

Updates one or more content scripts for this extension.

Parameters

  • Contains a list of scripts to be updated. A property is only updated for the existing script if it is specified in this object. If there are errors during script parsing/file validation, or if the IDs specified do not correspond to a fully registered script, then no scripts are updated.

  • callback

    function optional

    The callback parameter looks like:
    ()
    =>

    void

Returns

  • Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.

Applying JavaScript: User Scripts

by Thomas Noe

NgPJAVqUOAt1M4JQzWvriuFYKUNwTgUcFuFj

Art credit

Writing a Userscript is a fun way to use your JavaScript skills. It takes you out of the editor into the browser with real time feedback and validation.

What is a user script?

Userscripts (a.k.a User Scripts, User scripts, or .user.js) are open-source licensed add-ons for web browsers that change web pages as they are loaded. They give users the power to make websites do what they want them to, rather than what was originally intended.

User scripts are written in JavaScript and allow you to tweak the look and feel of a webpage on your browser. The scripts only effect your browser, not the actual webpage.

A quick warning

You should be aware of privacy issues when using userscripts, and should not install them from sources you do not trust. Userscripts can carry out actions on your behalf and can potentially access any information on a website you have access to, or that you enter into a website. They are often permitted to carry out functions that scripts on normal websites cannot, such as storing information on your computer and sharing it between website. Badly written userscripts could potentially also be exploited by malicious websites.

explanations taken from https://github.com/OpenUserJs/OpenUserJS.org/wiki/Userscript-Beginners-HOWTO

Why user scripts?

Free Code Camp has a lot of great real world projects that will enrich your skill set and portfolio. I personally like using the skills I have learned in JavaScript, jQuery, and CSS to modify my day to day browsing.

Some User Scripts have been extremely popular and were made into browser extensions. An example of one would be the Reddit Enhancement Suite found at http://redditenhancementsuite.com/.

You too could use your user script as a base of a browser extension!

Getting started

User scripts are run from browser extensions themselves. Grease Monkey (FireFox) was the pioneer add on to allow people to customize their browsing experience. Install the appropriate plug in for your browser.

For FireFox: Grease Monkey

Greasemonkey
The Development Channel lets you test an experimental new version of this add-on before it’s released to the general…addons.mozilla.org

For Chrome: Tamper Monkey

Tampermonkey
The most popular userscript manager for Blink-based browserschrome.google.com

For this tutorial I will be using Chrome with Tamper Monkey.

There shouldn’t be any significant differences with the process after installing either Grease Monkey or Tamper Monkey.

Just in case, here is a quick link to installing Grease Monkey (as well as making a few things with it.)

Greasemonkey Tutorial for Beginners
In Greasemonkey tutorial, I have covered how to write Greasemonkey user scripts. After this tutorial,you will be able…hayageek.com

the project

We are going to be making a slight change to the home page on Hacker News http://news.ycombinator.com.

6ICv092GpRSQFSCbogHBMCj3IBqWVqV0d7il

HackerNews homepage

We will be using jQuery to make alternating links background colors slightly different to improve readability.

start a new script

Click on the Tamper Monkey icon in the top right and select ‘Add a new script’ from the dialog box.

You should be brought to a new tab that looks like this

MnG62eij5rouor9HWsShflip5d1uJAH7bGGf

new script page

Fill in the information

After starting a new script the first thing we want to do is fill in the script information at the top. Go ahead and fill in the following attributes how ever you want

  • name
  • description
  • author

I will show you what mine looks like as well.

Add jQuery

right before the line

// ==/UserScript==

add a line with the text of

// @require http://code.jquery.com/jquery-latest.js

Think of this as importing/requiring jQuery for a JS project.

here is mine

9BlQRN0ORWp6K2ak0A-f6UD71dWwN4bTrDYp

script info filled out

Hello script.js!

Let’s see if it our script loads on http://news.ycombinator.com and jQuery is good to go.

After the // your code here line add the following code

$(document).ready(function() {  alert('WINNING');});

and enter Ctrl + s or click on the save button on the left

You may be brought to the following page. If not, click on the Installed userscripts tab.

RwzBGDralHUJYCaJUxb6ZFE1J-fo-IKkp1RT

installed userscripts page

Awesome! Out script is loaded into Tamper Monkey. The green dot on the left means that the script is turned on. You can even see the Hacker News logo in the screenshot.

execute the script

Visit Hacker News in your browser and if you’ve been following along and everything went well, you should see

kjO1MKNyMj0C1jza9KjXNqozJbJVwQJNjAJ2

working alert dialog

Fire up the debugger

It’s time to find the post elements we want to modify. Enter Ctrl + Shift + i to bring up the browser debugger.

Now we want to select an element to take a closer look. Clicking on the blue square with the mouse in it at the top left of the debugger will open the element selector. You can also use the key command Ctrl + Shift + c.

K57nqIwcj2tQz8CqY31YuHLVdClePaxYqHFX

element selector

As you can see I found an element called td.title. After clicking on it the element is highlighted in the elements tab of the debugger (also shown above.)

Highlighting the element above our title called

<tr class="athing">

selects this in the browser

3jTJbC0gL7Irgh-qfpzNbW5hksEdjfTKC6O5

BINGO

Bingo. It looks like we found the element we want. Hacker News has a clean HTML layout so it wasn’t too difficult to find our target element.

If you remember your jQuery, all you have to do to find all of the post elements is use the selector

$('.athing')

do something to our post element

Now that we have a way to select our element with jQuery we can alter our element. Let’s change the background color of the posts using the following code. Change the $(document).ready() code to this

$(document).ready(function() {  $('.athing').css('background-color', '#DDD');});

note: #DDD is shorthand for #DDDDDD;

let’s look at the resulting page. Remember to save your userscript then refresh the HackerNews page. You may have to close your debugger to view the whole page.

vkeMepNz7Ixs6vh5lBbQqqBrtqwSaqnKK4TG

altered Hacker News front page

Are we done yet? Not quite. We have changed all of our post elements instead of alternating. It may look like the zebra effect we wanted but that’s only because the score/subinfo element isn’t effected. If you feel inclined to alter that element as well please do and feel free to post your method in the comments. It’s outside of the scope of this guide.

Oh no?! What do we do… I don’t want to write any loops!

jQuery to the rescue

Have no fear, fellow Campers. jQuery has come to the rescue yet again.

jQuery provides special selectors just for an occasion like this.

Now introducing :odd

:odd Selector
Description: Selects odd elements, zero-indexed. See also even. In particular, note that the 0-based indexing means…api.jquery.com

all we have to do is add :odd to the end of our selector so that the line looks like this. note: I have also changed the color to #EEE; to blend in better.

    $(‘.athing:odd’).css(‘background-color’, ‘#EEE’);

Save your script and refresh HackerNews and you should see this final product

U2VcB-db2IvtuKrjzSfEfcKxU3jYxARMG1rV

final product

Wraping up

There you have it. Now you have another creative outlet to unleash your budding coding wizardry on! User Scripts can be used to tweak the functionality or look of a site, to add a feature you’ve always wanted, plus much more.

Homework

Write your own User Script to add something to a website you use often. Whether it be styling or a button that can toggle the visibility of certain elements, it’s all up to you. Provide your product in the comments here!

Go forth and conquer Campers!

More reading

Tampermonkey
Tampermonkey is a free browser extension and the most popular userscript manager for Blink-based Browsers like Chrome…tampermonkey.netGreaseSpot Wiki
GreaseSpot is community documentation for user scripting with Greasemonkey.wiki.greasespot.netGreasy Fork — safe and useful user scripts
User scripts put you in control of your browsing experience. Once installed, they automatically make the sites you…greasyfork.orgGetting Started: Building a Chrome Extension
Extensions allow you to add functionality to Chrome without diving deeply into native code. You can create new…developer.chrome.comHow to develop a Firefox extension
This blog post is very outdated. If you want a more recent guide to extension development, please read the new How to…blog.mozilla.org


Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

В этой инструкции я покажу, как создать расширение для браузера Google Chrome и при желании опубликовать его в открытом доступе.

Расширение или плагин для Chrome – это приложение, которое добавляет новые возможности браузеру. В магазине Chrome порядка 200 тысяч расширений для разработчиков, маркетологов, дизайнеров и других пользователей браузера.

Идея

Больше года назад я заметил, что ссылки «Входящие» и «Написать письмо» на главной странице почты, которой я часто пользуюсь, стали открываться в новом окне. По ответу эксперта стало понятно, что придется привыкать к этому спорному нововведению.

Я привыкнуть не смог: каждый раз возвращаться и закрывать вкладку браузера неудобно. Так появилась идея простого расширения для Chrome, которое вернет прежнее поведение при открытии Входящих и написании нового письма.

SimilarWeb показывает 1,141 млрд посещений главной страницы за август. Если хотя бы 10% из них приходится на десктопный браузер и целевое действие, то это 141 млн открытых вкладок в месяц. На возврат и закрытие вкладки уходит не меньше секунды. Получается, мы собираемся сэкономить 31,5 тысячи человеко-часов в месяц.

Шаг 1. Подготовка расширения

Приготовим минимальный стартовый набор.

1. Создайте папку проекта. Назовите ее именем вашего расширения.

2. Создайте javascript-файл, в котором будет реализована логика приложения. Я назвал его app.js.

3. Добавьте в созданный файл команду для тестирования: вывод строки в консоль или в диалоговое окно браузера.

alert(‘Hello from my extension!’);

4. Создайте manifest.json – служебный файл, который должен быть в каждом расширении.

{
«manifest_version»: 2,
«name»: «Mail link healer»,
«version»: «1.0»,
«description»: «Ссылка «Входящие» и «Написать письмо» снова открываются в той же вкладке!»,
«icons»: {
«128»: «128.png»
},
«content_scripts»: [
{
«matches»: [ «<all_urls>» ],
«js»: [ «app.js» ]
}
]
}

Обязательные параметры, должны быть в каждом manifest.json:

  • manifest_version – целое число, обозначает версию формата манифеста. Для современных версий браузера значение равно 2;

  • name – название расширения, до 45 символов. К названию стоит подойти ответственно – оно отображается в магазине, при установке и на странице управления расширениями (chrome://extensions);

    version – строка с версией расширения. Содержит до четырех чисел, разделенных точками, например 2.19.7.0.

Необязательные параметры:

  • description – простой текст, до 132 символов. Отображается в магазине и на странице управления расширениями;

  • icons – список из иконок расширения;

  • content_scripts – скрипты, которые загружает приложение. Мы прописали запуск app.js на всех веб-страницах. Позже мы изменим этот параметр, чтобы запускать скрипт только на целевой странице. Строго говоря, в нашем случае content_scripts – обязательный параметр. Если его не задать, расширение не сделает ничего полезного.

5. Подготовьте иконку в формате png размером 128х128 пикселей и положите ее в папку проекта. Эта версия отображается при установке и в магазине расширений. Рекомендуют также добавить иконку размером 48х48 пикселей – она отображается на странице управления расширениями. И можно добавить версию 16х16 пикселей, которая будет использоваться как фавикон.

К этому моменту в нашем проекте есть иконка расширения, manifest.json со служебной информацией и app.js, в котором позже появится код приложения.

.
├── 128.png
├── app.js
├── manifest.json

Примечание: расширение может состоять из нескольких JS-файлов, HTML-верстки и CSS-стилей.

Теперь можно проверить, что мы выполнили минимальные требования к расширению.

Шаг 2. Промежуточное тестирование

1. Войдите в свой аккаунт в браузере Chrome.

2. Перейдете на страницу chrome://extensions.

3. В правом верхнем углу включите Режим разработчика.

4. Нажмите Загрузить распакованное расширение и выберите папку проекта. В результате вы увидите похожую картинку:

Расширение после загрузки в браузер.

5. В новой вкладке браузера откройте любую веб-страницу. Отлично, работает!

alert из app.js сработал. Можно двигаться дальше.

Теперь мы готовы добавить полезное действие.

Шаг 3. Код приложения

Проверим код ссылок «Входящие» и «Написать письмо» на странице почты с помощью инструментов разработчика браузера. Нажимаем правую кнопку на ссылке и выбираем Посмотреть код. Видно, что ссылки открываются в новой вкладке из-за атрибута target=”_blank”.

Кусочек кода в этой рамке доставляет столько неудобств. Избавимся от него!

Получается, с помощью javascript нам нужно выбрать две ссылки и удалить этот атрибут.

1. В app.js сохраните ссылки в переменные:

const inboxLink = document.getElementById(‘mailbox:unreadEmails:link’); // ссылка на Входящие
const composeLink = document.getElementById(‘mailbox:write_letter’); // ссылка «Написать письмо»

Здесь мы выбираем элементы по их идентификатору (id).

2. Если такие ссылки найдены, удалите у них атрибут target.

if (inboxLink && composeLink) {
// если ссылки есть на странице
// удаляем у них атрибут ‘target’
inboxLink.removeAttribute(‘target’);
composeLink.removeAttribute(‘target’);
}

Похоже, этого кода достаточно для решения проблемы.

Заодно давайте пропишем в manifest.json правило, по которому расширение будет запускать наш скрипт только на целевой странице. Для этого в параметре content_scripts в ключе matches пропишем конкретный URL:

«content_scripts»: [
{
«matches»: [ «https://mail.ru/*» ],
«js»: [ «app.js» ]
}
]

Звездочку в конце URL я поставил, чтобы скрипт срабатывал на всех страницах, начинающихся с https://mail.ru/.

Кстати, после обновления расширения стоит обновить версию и в manifest.json:

«version»: «1.1»,

После внесения правок важно обновить расширение в браузере. Для этого нажмите на стрелку на странице управления расширениями (chrome://extensions/).

Быстрый способ обновить расширение.

Готово! Проверим расширение в боевых условиях.

Шаг 4. Финальное тестирование

Открываем целевую страницу и переходим по ссылкам «Входящие» и «Написать письмо». Победа! Ссылки открываются в той же вкладке, как в старые добрые времена.

Шаг 5. Публикация расширения

Этот шаг необязательный. Во-первых, возможно, вы не хотите делать доступным для всех свое расширение. А во-вторых, возможно, не захотите платить за это $5. Такой регистрационный сбор должен оплатить разработчик Chrome Web Store.

  1. Создайте zip-архив с файлами проекта.
  2. Зарегистрируйтесь как разработчик Chrome Web Store. Для этого войдите в консоль разработчика под своим аккаунтом Chrome, примите условия соглашения и Политику конфиденциальности.
  3. Оплатите регистрационный сбор $5. Оплатить можно картой, как в обычных интернет-магазинах.
  4. На дашборде разработчика в разделе Аккаунт добавьте адрес электронной почты. Без этого не получится отправить расширение на проверку.
  5. В личном кабинет разработчика нажмите Добавить продукт и загрузите zip-архив проекта.
  6. В разделе Описание продукта заполните описание расширения, выберите категорию и язык. Добавьте хотя бы один скриншот расширения.
  7. В разделе Конфиденциальность коротко опишите единственное назначение расширения, обоснование для использования разрешения и отметьте, что не используете разрешение «удаленный код».
  8. В разделе Цель и распространение задайте, кому будет доступно расширение.
  9. Нажмите Отправить на проверку в правом верхнем углу.

Это всё. Остается ждать результат проверки, которая может занять несколько недель.

Я отправил расширение на проверку параллельно с публикацией статьи. Как только получу ответ, добавлю комментарий со ссылкой на опубликованное расширение.

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

27.06.2014, 08:45. Показов 57589. Ответов 1


1. Что такое расширения к браузерам?
Расширения к браузерам — это программы, которые внедряются в браузер и добавляют в него новые функции или настраивают имеющиеся.
Расширения к браузерам могут:

  • изменять html-код страниц, открываемых в браузере. В том числе внедрять в них скрипт, который на страницах не отображается, но выполняется для каждой странице при её загрузке.
    В хроме такой скрипт называется скриптом содержимого или контентным скриптом, в мазиле и опере — юзерскриптом.
    Примечание: в отличие от обычных видимых скриптов, этот скрипт может делать кроссдоменные запросы XMLHttpRequest.
  • добавлять кнопки на панели инструментов браузера и создавать новые тулбары
  • управлять вкладками браузера: создавать, закрывать, обновлять, посылать по определённому urlу
  • управлять закладками браузера: создавать, изменять, удалять
  • делать редиректы с одних url на другие, причём не только при открытии того или иного url во вкладке, но и при доступе к нему из фреймов, а также через XMLHttpRequest или через script, img, video.
  • просматривать и изменять историю посещенных страниц в браузере
  • и другое, в зависимости от браузера и его версии

Расширения можно публиковать в магазине расширений для соотв. браузера, откуда пользователи смогут их скачивать бесплатно или покупать за деньги.
Ссылки на магазины даны ниже.

Не стоит путать расширения с плагинами.

2. Что представляют собой расширения и как их пишут?
Расширения к браузерам обычно состоят из:

  • файла настроек расширения (ini, json, xml), где указаны, например, название расширения, его версия, автор, поддерживаемые версии браузера, а также файлы скриптов и html страниц, необходимых расширению
  • фонового JS-скрипта (или фоновой страницы с таким скриптом), который выполняется 1 раз при загрузке браузера, не отображается ни на каких страницах, но может менять какие-то настройки в браузере, скажем добавлять кнопку на тулбар
  • юзерскрипта, который внедряется в страницы, не отображается в их коде, но может их изменять так же свободно, как и если бы он был на данном сайте изначально
  • вспомогательных html-страниц, например, страницы настроек для пользователя или диалогового окна, открывающегося при нажатии на кнопку на тулбаре

Всё это либо упаковывают в zip-архив и устанавливают в браузер через страницу Расширения/Дополнения (предварительно сменив расширение архива в зависимости от браузера), либо просто помещают в отдельную папку и опять устанавливают через страницу Расширения/Дополнения, указав путь к этой папке (ручная установка в распакованном виде доступна в хроме).
Возможна программная установка расширений.

Логику расширения пишут на JS, интерфейс пользователя создают с помощью HTML+CSS, а файл настроек пишут на INI/JSON/XML.
Для написания расширений достаточно блокнота.

Исключение — Internet Explorer, расширения для которого пишутся на компилируемом ЯП (C#, C++, Delphi, ..) с помощью COM. Его мы здесь рассматривать не будем.

3. С чего начать?
1. Сначала Chrome.
Во-первых, по нему больше всего инфы в инете.
Во-вторых, он попросту проще.
В-третьих, он не только популярнее сам по себе, но имеет множество клонов, которые, также как и он, основаны на Chromium и обычно совместимы с расширениями Chrome. Это Яндекс.Браузер, Амиго, Интернет от Mail.Ru… Тысячи их.
2. Потом Opera.
Когда вышла Opera 15 (Opera Next) на хромовском движке, оф. документацию по расширениям к старой опере аффффтары просто потёрли, глубоко наплевав на тех, кто привык к старой опере и вообще в гробу видел хром. А таких вот топиков в своё время никто не создал. В результате инфы в инете по опере не Next почти не осталось.
Мы в данном топике будем рассматривать оперу ниже 15, т.е. не Next.
3. Потом Firefox.
Расширения к нему можно создавать двумя способами — как я описал в пункте 2 и каким-то левым способом с помощью специального SDK, причём способы плохо совмещаются друг с другом. Поэтому добрая половина кода в инете, касаемо огнелиса, у вас может просто не заработать. Мы в данном топике будем учиться юзать именно способ без SDK, ибо он проще.
4. Ну и потом IE.
Который по вышеупомянутой причине рассматриваться в топике не будет.

4. Зачем нужен этот топик? Вон статья на хабре, вон оф. документация, вон ещё статья на хабре, что ещё надо?
1) Вам не нужно — вы и не создавайте топиков, и этот не читайте. А некоторым нужно. Мне бы в своё время пригодился.
2) По расширениям к хрому инфа и правда есть, но вот с огнелисом и оперой сложнее. Про оперу — см. выше.
3) Я не прошу отправлять этот топик в важные (хотя буду рад, если он туда попадёт), не буду его апить каждые полчаса. Так что вам он не мешает ничем. Не нужно его трогать.
4) Этот топик нужен мне. Чтобы в свободное время или просто когда лень работать продолжать углублять свои знания и расширять специализацию. И вы бы лучше занялись чем-то таким, нежели ругать и портить чужое.

5. Пишем простое расширение к Chrome.
Расширение будет добавлять всплывающий баннер с текстом «Ура!» на каждую страницу в браузере, в левый-верхний угол.
Итак, приступим.
1. Создаём отдельную папку. Называем её, например, HelloChromeAPI.
2. В папке создаём файл настроек расширения.
Для этого запускаем блокнот, пишем такой код

JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "name": "Hello Chrome API",
    "version": "1.0.0.0",
 
    "manifest_version": 2,
 
    "content_scripts": [
        {
            "matches": [ "http://*/*" ],
            "js": [ "content_scripts/end.js" ],
            "run_at": "document_end"
        }
    ]
}

сохраняем в нашу папку под именем manifest.json обязательно в кодировке UTF-8.
Такой формат представления данных называется JSON: записи через запятую, имена их в кавычках, каждая запись может включать в себя подзаписи разного типа (тогда заключается в {}) или подзаписи одного и того же типа (тогда называется массивом и заключается в []).
«name» — имя расширения, которое будет видно в браузере
«version» — версия расширения, которую тоже будет видно в браузере
«manifest_version», равное 2, указывает, что расширение будет совместимо с Chrome выше версии 13. Если вместо 2 указать 1, то расширение будет работать в хромах с 5 по

12. Такие хромы сейчас редки, но если уж писать серьёзный проект, то нужно сделать дубликаты расширения для обоих поколений хрома.
«content_scripts» — это массив контентных скриптов (то есть скриптов, которые, как говорилось выше, выполняются на каждой странице в браузере). В данном случае в списке один элемент (он ограничен скобками {}), так как скрипт в нашем расширении будет только 1
«matches» — маска, указывающая, на каких страницах будет выполняться скрипт. * означает любую последовательность символов. Наш скрипт будет выполнять на всех страницах протокола http. Почему только http? Потому что на страницах протокола https браузер проверяет, нет ли левого html-кода, и если есть, то ругается. Может ругаться и антивирус.
«run_at» указывает, на каком этапе загрузки страницы скрипт будет выполняться.
Значение «document_start» = не загружено ничего (скрипт сможет вывести окошко alert или изменить window.location.href, но не сможет работать с document.body, его просто не будет)
Значение «document_end» = загружен код страницы, доступны document и document.body, но могут выполнять какие-то скрипты, которые ещё просто не успели выполниться
Значение «document_idle» = простой, когда никакой другой скрипт не выполняется. точнее ближайший период простоя с начала загрузки. Рекомендуется использовать для сложных ресурсоёмких скриптов, когда в то же время не требуется, чтобы скрипт выполнился прямо сразу после загрузки.
«js» — это массив путей к скриптам, выполняющимся с данными matches. Скрипт один, он будет называться end.js (это будет означать, что скрипт выполняется по document_end) и лежать в подпапке content_scripts в нашей папке расширения.
3. Создадим подпапку content_scripts, а в ней скрипт end.js.
В нём пропишем код

Javascript
1
document.body.innerHTML += '<div style="background-color: #FFFFFF; border-color: black; border-style: solid; color: black; font-family: 'Segoe UI'; font-size: 24px; position: fixed; left: 0; top: 0; width: 300px; height: 110px; padding: 8px; z-index: 1000000000">Ура!</div>';

Этот скрипт добавляет код баннера в код body той страницы, на которой выполняется.
Он тоже обязательно должен быть сохранён в UTF-8.
Примечание: стилей так много затем, чтобы перекрыть стили, применённые на сайте, куда вставляется баннер, и баннер на всех сайтах выглядел одинаково.
4. Установим расширение в браузер.
Откроем меню браузера кнопкой справа-вверху, затем пункт Инструменты, затем выберем пункт Расширения.
Или просто пройдём по ссылке chrome://extensions
Поставим флажок Режим разработчика, нажмем Загрузить распакованное расширение и укажем нашу папку.
5. Теперь зайдём на любую страницу, использующую http (см. выше)
mail.ru подойдёт, наш форум подойдёт, а google.ru нет.
Когда страница загрузится до конца, слева-вверху появится обещанный баннер.
6. На странице расширений мы можем отключить или удалить расширение с помощью соотв. кнопок.
А если мы решим изменить код manifest.json, end.js и т.д., то чтобы изменения применились, мы должны воспользоваться кнопкой Обновить.

6. Добавляем кнопочку на панель инструментов Chrome
Теперь оно будет ещё добавлять кнопочку на панель инструментов хрома и при нажатии на кнопку открывать диалоговое окно.
Нам понадобится Chrome 20 или новее.
1. Откроем наш файл manifest.json
Изменим его таким образом

JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
    "name": "Hello Chrome API",
    "version": "1.0.0.0",
 
    "manifest_version": 2,
 
    "content_scripts": [
        {
            "matches": [ "http://*/*" ],
            "js": [ "content_scripts/end.js" ],
            "run_at": "document_end"
        }
    ], // <-- здесь добавим запятую
 
    "browser_action": {
          "default_icon": {                       // иконки для кнопки 
            "19": "/images/br-icon19.png",         // иконка 19x19 пкс
            "38": "/images/br-icon38.png"          // иконка 38x38 пкс
          },
          "default_title": "Наша кнопка",         // всплывающая подсказка появл при наведении мыши на кнопку
          "default_popup": "popup/popup.html"     // страница появл во всплывающем окне откр при нажатии на кнопку
    }
}

и сохраним.
2. Создадим подпапки images и popup.
В images создадим две картинки, как указано в манифесте. Картинки могут быть одинаковыми, отображается только одна, в зависимости от расширения монитора (на больших мониторах — 38×38, на маленьких — 19×19).
В popup создадим файл popup.html и запишем в него такой код

HTML5
1
<div style="width: 300px; height: 100px">Ура!</div>

Сохранять тоже лучше в UTF-8.
3. Чтобы изменения вступили в силу, зайдём в Расширения и нажмём кнопку Обновить под нашим расширением.
4. На панели инструментов (слева вверху) появится кнопка с заданной иконкой.
Нажав на кнопку, увидим окошко, в котором будет надпись «Ура!».
Заметим, что размер окошка соответствует размеру, указанному в style корневого элемента popup.html (т.е. 300 x 100 пкс).
Если этот размер не указывать, окошко будет таким, чтобы в него поместилось содержимое этого элемента, т.е. надпись «Ура!».

7. Добавляем иконку в расширение к Chrome.
1. Подправим манифест.

JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
    "manifest_version": 2,
 
    "name": "Hello Chrome API",
    "version": "1.0.0.0",
 
    "manifest_version": 2,
 
    // добавим такие строчки
    "icons": {
        "48": "/images/icon48.png"
    },
 
    "content_scripts": [
        {
            "matches": [ "http://*/*" ],
            "js": [ "content_scripts/end.js" ],
            "run_at": "document_end"
        }
    ],
 
    "browser_action": {
          "default_icon": {
            "19": "/images/br-icon19.png",
            "38": "/images/br-icon38.png"
          },
          "default_title": "Наша кнопка",
          "default_popup": "popup/popup.html"
    }
}

2. Создадим файл icon48.png в папке images.
Это будет иконка расширения, отображаемая на странице расширений вместо дефолтного значка с фрагментом мозаики.
Примечание: помимо иконки размером в 48 пкс, мы можем сделать иконки размером 16, 32, 128 пкс, дописав внутрь ветви «icons:» соотв. строчки, не забывая про запятые. Но это нужно только если мы решим нарисовать действительно разные иконки для расширения. Просто растянув иконку под 16, 32, 128 пкс, мы ничего не достигнем — хром это сделает и сам, где оно понадобится. Я ограничился 48 пкс.
3. Обновим расширение на странице расширений.

8. Пишем простое расширение к Opera.
Расширение будет работать аналогично расширению к хрому.
Опера у меня версии 12. На других не пробовал. На 15 и выше, ещё раз, работать не должно.
Все файлы, как и с хромом, лучше сохранять в UTF-8, иначе кириллица будет отображаться неверно.
Приступим.
1. Создаём отдельную папку. Называем её, например, HelloOperaAPI.
2. В папке создаём файл настроек расширения.
Для этого запускаем блокнот, пишем такой код

XML
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets">
    <name>Hello Opera API</name>
    <version>1.0.0.0</version>
</widget>

сохраняем в нашу папку под именем config.xml обязательно в кодировке UTF-8.
Такой формат представления данных называется XML.
<name> — имя расширения, которое будет видно в браузере
<version> — версия расширения, которую тоже будет видно в браузере
А вот никакого упоминания о скриптах в файле не будет. Мы просто создадим в папке с расширением подпапку include и файл .js с любым именем. Этого будет достаточно, чтобы скрипт работал.
3. Сказано — сделано. Создаём подпапку include и файл script_end.js

Javascript
1
2
3
4
5
6
7
// ==UserScript==
// @include [url]http://*/*[/url]
// ==/UserScript==
 
document.addEventListener("DOMContentLoaded", function() {
    document.body.innerHTML += '<div style="background-color: #FFFFFF; border-color: black; border-style: solid; color: black; font-family: 'Segoe UI'; font-size: 24px; position: fixed; left: 0; top: 0; width: 300px; height: 110px; padding: 8px; z-index: 1000000000">Ура!</div>';
}, false);

DOMContentLoaded позволяет создать эффект «document_end» из хрома (а сам юзерскрипт в опере выполняется фактически по «document_start».
«==UserScript==…==/UserScript==» вверху — это не просто комментарий. Там указываются настройки данного скрипта. @include здесь работает по принципу «matches» из Chrome.
Скрипт тоже обязательно должен быть сохранён в UTF-8.
Этот скрипт добавляет код баннера в код body той страницы, на которой выполняется.
4. В папке с расширением создадим index.html. Это фоновая страница. Мы можем оставить её пустой, потому что фоновых скриптов пока нет и она нам не нужна, но в расширении для оперы она должна быть обязательно.
5. Упакуем расширение в zip-архив. Сменим его расширение с zip на oex.
6. Запустим оперу, зайдём в меню, выберим пункт Дополнения, перетащим туда oex.
7. Проверим, появляются ли баннеры при загрузке страниц.

9. Добавляем кнопку на панель инструментов Opera
На панели инструментов справа-вверху появится кнопка. При нажатии на неё откроется всплывающее окошко с заданной страницей. Всё как в хроме.
Нам понадобится Chrome 20 или новее.
1. Изменим фоновую страницу index.html таким образом

HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!doctype html>
<html lang="en">
    <head>
        <script>
            window.addEventListener("load", function(){
                var ToolbarUIItemProperties = {
                    title: "Наша кнопка",
                    icon: "/images/br-icon19.png",
                    popup: {
                        href: "popup/popup.html",
                        width: 300,
                        height: 100
                    }
                }
                opera.contexts.toolbar.addItem(opera.contexts.toolbar.createItem(ToolbarUIItemProperties));
            }, false);
        </script>
    </head>
    <body>
    </body>
</html>

и сохраним.
opera.contexts.toolbar — это класс из Opera API.
У хрома тоже есть API — chrome.*.
2. Создадим подпапки images и popup.
В images создадим картинку, как указано в манифесте.
В popup создадим файл popup.html и запишем в него такой код

Примечание:

в отличие от хрома, размер окошка формируется не через style корневого элемента popup.html, а через width и height, прописанные в ToolbarUIItemProperties в index.html.
3. Чтобы изменения вступили в силу, удалим расширение и установим его обратно.
4. На панели инструментов (слева вверху) появится кнопка с заданной иконкой.
Нажав на кнопку, увидим окошко, в котором будет надпись «Ура!».

10. Добавляем иконку в расширение Opera.
1. Путь к иконке указывается в файле настроек — config.xml.
За него отвечает тэг icon с атрибутом src, в котором указывается относительный путь к иконке (относительно основной папке расширения).
Откроем файл config.xml.
Внутри <widget> добавим строчку

XML
1
<icon src="/images/icon48.png" />

Должно получиться так:

XML
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets">
    <name>Hello Opera API</name>
    <version>1.0.0.0</version>
    <icon src="/images/icon48.png" />
</widget>

2. Создадим файл icon48.png (это может любая картинка 48×48 пкс) в папке images.
3. Перепакуем и переустановим расширение.
В списке расширений вместо дефолтного значка (сиреневого фрагмента мозаики) будет отображаться наша иконка.


11. Пишем простое расширение Firefox.
12. Добавляем панель инструментов в Firefox.
13. Добавляем иконку в расширение Firefox.

Продолжение следует…
Пока что читаем здесь и экспериментируем.

Пара советов и ссылок на закуску
Конечно, информации из этого топика ещё недостаточно, чтобы написать любое расширение к браузеру Chrome, Firefox или Opera.
Но общее представление о расширениях и особенностях их разработки вы получили.
Поэтому, воспользовавшись данными ссылками в связке с гуглом, Вы при желании сможете углубиться в расширения и писать крупные, уникальные продукты.
Здесь же обещанные магазины расширений.
CHROME
https://developer.chrome.com/extensions/ — официальная документации.
Вот описание в ней контентных скриптов и кнопки browser-action:
https://developer.chrome.com/e… nt_scripts
https://developer.chrome.com/e… wserAction
https://chrome.google.com/webs… ions?hl=ru — магазин.
OPERA
https://addons.opera.com/ru/extensions/ — магазин.
FIREFOX
https://addons.mozilla.org/ru/firefox/ — магазин.

Добавлено через 2 минуты
В процессе написания топика нашёл на форуме баг.
В кодах JSON, XML и др. текст «https://www.cyberforum.ru/images/картинка.png» заменяется на «https://www.cyberforum.ru/images/картинка.png».
То есть если написать

JSON
1
2
3
{
    "48": "ЗДЕСЬ_НЕТ_НИЧЕГОimages/icon48.png"
}

то получится

JSON
1
2
3
{
    "48": "https://www.cyberforum.ru/images/icon48.png"
}

Правда, написав

JSON
1
2
3
{
    "48": "/images/icon48.png"
}

мы получим то, что ожидали. Но иной код от этого может сделаться также нечитабельным, как и из-за добавления «https://www.cyberforum.ru/».



2



Понравилась статья? Поделить с друзьями:
  • Как написать скрипт для windows cmd
  • Как написать скрипт для powershell
  • Как написать скрипт для linux ubuntu
  • Как написать скрипт для imacros
  • Как написать скрипт для excel