Как сделать расширение для браузера
Traffic Cardinal Traffic Cardinal  написал 09.03.2026

Как сделать расширение для браузера

Traffic Cardinal Traffic Cardinal  написал 09.03.2026
11 мин
0
51
Содержание

Несмотря на засилье разного рода прилок, большая часть интернет-трафика — это все еще те, кто сидит через браузер. Точнее — это те же люди, что сидят в прилах, но браузерами они пользуются все еще достаточно часто. А значит, и браузерными расширениями пользуются тоже. А уже это, в свою очередь, означает, что всю эту темку можно монетизировать. Вот только чтобы монетизировать расширение, сначала нужно научиться его создавать.

Вжух — и вы умеете делать расширения
Вжух — и вы умеете делать расширения

Собственно, именно о том, как создать свое расширение для браузера, и будет данная статья. А чтобы не скатываться в банальщину по типу «Hello World», мы сделаем расширение, убирающее инфу об источнике скопированной в сети инфы. Не то чтобы мы были против указания источника — отнюдь. Просто кто работает с текстами, не даст соврать: немного надоедает убирать одну и ту же инфу после каждого скопированного предложения. В качестве бонуса мы также прикрутим к расширению простенький интерфейс.

Ну, как говорил классик — поехали!

Пара минут ликбеза

Мы, конечно, могли бы просто сразу сделать все то, о чем ранее написали — но чему бы вы тогда научились? Копировать конкретное расширение? Нет-нет — мы все же хотим научить вас делать расширения и без нашего участия. А посему держите план, как сделать свое расширение:

  1. Продумать, что оно должно делать.
  2. Разобраться, как это сделать.
  3. Сделать это.
  4. Протестить/допилить, если надо.

Один раз удалить не сложно. Но 100500 раз удалять одно и то же — немного подбешивает
Один раз удалить не сложно. Но 100500 раз удалять одно и то же — немного подбешивает

И если кто-то скажет, что это очевидно, мы скажем: тогда пойди и сделай сам. Это не очевидно — это текстовое представление того, как делаются расширения. И если 3-й и 4-й пункты действительно походят на «воду», то вот 1-й и 2-й — критически важны!

Итак, рассмотрим процесс на примере нашей убиралки инфы об источнике:

  1. Продумать, что оно должно делать — убирать лишний текст, который сайт добавляет в буфер обмена. А сделать это можно либо убрав этот текст, либо не дав его добавить. И здесь как раз раскрывается важность пункта 2. Ведь именно исходя из понимания того, как это сделать, и будет рождаться реализация.
  2. Разобраться, как это сделать — так как сайт уже отрендерен в браузере, то нужный нам текст уже есть. И есть он, как видите, без мусора. В теории, конечно, какие-то извращенцы могут сделать невидимый текст, который будет еще и смещаться из-за спецсимволов — но это прям максимально маловероятно. А посему в 99,9% случаев сайт будет добавлять инфу уже к копируемому тексту, отслеживая собственно копирование. Делается это через JS. И можно было бы его просто отключить — да только тогда полсайта перестанет работать. Посему мы сделаем проще — мы запретим реагировать на «копирование» с помощью своего, более приоритетного JS.
  3. Сделать это — собственно, запрещаем браузеру запускать какие-либо JS при инициализации копирования. Делается это до ужаса просто, через stopImmediatePropagation(); с предварительным соблюдением JS-синтаксиса.

В общем, выглядит все это вот так:

document.addEventListener('copy', function(e) {e.stopImmediatePropagation();}, true);

Где:

  • document — текущая страница.

  • addEventListener — добавление обработчика события.

  • 'copy' — событие копирования.

  • e — объект события.

  • stopImmediatePropagation() — метод объекта события, останавливает дальнейшую реакцию на него. То есть — наш запрет сайту.

  • function(e) {…} — обработчик события.

  • true — перехватчик (вообще, capture-фаза, но перехватчик — понятнее) приоритета, чтобы наш скрипт выполнялся раньше скрипта сайта.

Из всего этого важны лишь 'copy', stopImmediatePropagation() и true. Все остальное — фактически просто вспомогательные элементы самого JS.

Сложно? Вроде бы нет. Правда, это мы сделали JS, а не расширение.

Как сделать расширение из JS

Как же сделать из него разрешение? Проще простого! Добавить к нему манифест, засунуть все это в папку и загрузить в браузер.

Ищем справа вверху
Ищем справа вверху

Да-да, буквально:

  1. Создаем папку с названием расширения.
  2. Создаем манифест.
  3. Закидываем наш скрипт и манифест в папку.
  4. Закидываем все это в браузер.

Что за манифест? Файл, поясняющий браузеру, что делать.

Самый простой манифест будет выглядеть вот так:

{

"manifest_version": 3, // версия манифеста

"name": "Пустышка", // имя расширения

"version": "1.0" // версия расширения

}

Но это для расширения, которое не делает ничего. Для нашего же будет немного сложнее:

{

"manifest_version": 3,

"name": "Clean Copy",

"version": "1.0",

"permissions": ["scripting"],

"content_scripts": [

{

"matches": ["<all_urls>"],

"js": ["content.js"],

"run_at": "document_start"

}

]

}

В целом тут как будто бы пояснения излишни. Разве что на permissions остановимся — флаг scripting подразумевает, что скрипт будет интегрироваться в уже отрендеренную страницу. Все остальное вроде бы понятно. Если нет — переводчик в помощь. Глубоких смыслов там нет.

Ищем вверху страницы слева
Ищем вверху страницы слева

Далее мы просто закидываем наш JS под именем content.js и наш манифест под именем manifest.json в любую (лучше с именем на латинице) папку. Переходим в «Управление расширениям» в браузере, жмем «Загрузить распакованное расширение» и выбираем нашу папку. Перезагружаем страницу — копируем без «мусора». Источник инфы все же не забудьте указать (зато всего один раз и в удобном вам месте) — а то негоже.

Вот и все — расширение создано и загружено. Вы великолепны!

Бонус

В качестве бонуса — патч с «интерфейсом». На самом деле он не столько для интерфейса, сколько для того, чтоб не ломать вам копирование из гугл-таблиц. Так как в них все тоже через JS, то наш скрипт его ломает. Посему мы сделаем так, чтоб его можно было включать и выключать для конкретных сайтов. Делается это через добавление popup.

Вжух
Вжух

Итак, content.js будет выглядеть как:

chrome.storage.sync.get(["disabledSites"], (result) => {

const disabledSites = result.disabledSites || [];

const isDisabled = disabledSites.some(domain =>

location.hostname.endsWith(domain)

);

if (!isDisabled) {

document.addEventListener(

"copy",

(e) => {

e.stopImmediatePropagation();

},

true

);

}

});

Манифест manifest.json как:

{

"manifest_version": 3,

"name": "Clean Copy",

"version": "1.0",

"permissions": ["storage", "tabs"],

"action": {

"default_popup": "popup.html"

},

"content_scripts": [

{

"matches": ["<all_urls>"],

"js": ["content.js"],

"run_at": "document_start"

}

]

}

Фронт popup как:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

</head>

<body style="font-family:sans-serif; width:200px;">

<button id="toggle"></button>

<script src="popup.js"></script>

</body>

</html>

И бэк popup как:

const toggleBtn = document.getElementById("toggle");

async function init() {

const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

const hostname = new URL(tab.url).hostname;

chrome.storage.sync.get(["disabledSites"], (result) => {

const disabledSites = result.disabledSites || [];

const isDisabled = disabledSites.includes(hostname);

toggleBtn.textContent = isDisabled

? "Включить на этом сайте"

: "Выключить на этом сайте";

toggleBtn.onclick = () => {

let updated;

if (isDisabled) {

updated = disabledSites.filter(d => d !== hostname);

} else {

updated = [...disabledSites, hostname];

}

chrome.storage.sync.set({ disabledSites: updated }, () => {

chrome.tabs.reload(tab.id);

});

};

});

}

document.addEventListener("DOMContentLoaded", init);

Как видите, мы добавили в манифест инфу о новом скрипте, а в изначальный скрин — инфу о состоянии «переключателя». Также мы добавили простенький интерфейсик для нашей кнопки, 99% которого — это тупо синтаксис HTML. Ну и отдельный скрипт для нашего popup тоже добавили. Расписывать его столь же подробно, как content.js, мы не будем. Поясним лишь, что он находит в HTML-интерфейсе кнопку toggle, раскидывает ее по вкладкам, считывает ее состояние и засовывает его в массив внутренней БД, в поля, соответствующие сайту.

Выжух
Выжух

На человеческом это означает, что вы можете открыть 100500 вкладок одного и того же сайта, туда-сюда жмакать кнопку, но реальным будет лишь ее самое «последнее» состояние. То есть если вы не перезагрузите «старую» вкладку, то на ней все еще будет «выключено», даже если на последнем уже «включено». Но при этом реагировать скрипт будет на актуальное состояние. Впрочем, вряд ли вы будете сами себе усложнять жизнь. Посему «фикс от этого прикола» было решено не добавлять, чтобы не утяжелять «обучательный» код.

Далее мы закидываем все это в папку, как и в разделе выше, обзываем ее как-нибудь, снова открываем в браузере меню «Управление расширениям», снова жмем «Загрузить распакованное расширение» и, опять же, выбираем нашу папку. А вот страницу можно не перезагружать, ибо состояние теперь зависит от кнопки. Для переключения просто жмем на иконку нашего расширения и на кнопку «Включить на этом сайте» или «Выключить на этом сайте» — в зависимости от состояния.

Всего 4 КБ — зато сколько радости :D
Всего 4 КБ — зато сколько радости :D

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

Но ведь это только для Chrome!

Ну да — это для Chromium-браузеров. А вы знаете другие? Нет, они, конечно, есть — но сегодня их днем с огнем не сыщешь. И уж тем более они не являются чем-то массовым. Да блин — даже антики сегодня пилят на Chromium-движке. Посему как будто бы для других браузеров и смысла делать расширения нет. Если есть — напишите в комментариях, расскажем как.

И да — мы научились просто создавать расширения. О том, как добавить его в магазин расширений, мы не рассказывали. Почему? Да потому, что это абсолютно отдельная тема. Это как создать прилу для ведроида и протолкнуть ее в Google Play — разные материи. И описывать все это в рамках одной статьи нецелесообразно. Банально потому, что никто столь длинную статью не осилит. Посему — на этом все.

Подводя итоги

Как видите, в базе создание расширений — до ужаса простой процесс. Манифест, скрипт и пара нажатий в настройках браузера. Конечно, чем больше фич мы будем добавлять, тем все будет становиться сложнее. Но ведь в любом деле так. Зато, имея представления об азах, гораздо проще разбираться и в чем-то сложном. Ну и надеемся, что наше расширение будет полезным. Ибо навязчивое добавление источника в буфер — это не более чем попытка «испортить жизнь» тем, кто копирует инфу.

Здравствуйте! У вас включен блокировщик рекламы, часть сайта не будет работать!