Как написать расширение для chrome. Как создавать и публиковать приложения и расширения Chrome

08.03.2024
23 октября 2013 в 13:21 Создаём своё расширение для Google Chrome
  • Разработка веб-сайтов ,
  • JavaScript ,
  • Google Chrome
  • Tutorial

На хабре уже есть несколько статей о создании расширений для хрома, поделюсь своим опытом, затронув основные вещи и места, в которых у меня возникли трудности.
Что понадобится для создания расширения в двух словах:
1) Базовые знания Javascript
2) Базовые знания HTML
3) 5$

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

Итак, я начинаю создание расширения с создания папки самого расширения, в которую будем класть все создаваемые нами файлы. Назову её «losttime». Далее, я создаю файл manifest.json, выглядит он следующим образом:

manifest.json
{ "manifest_version": 2, "name": "Lost Time", "version": "1.0", "icons": { "128": "" }, "content_scripts": [ { "matches": [ "*://*/*" ], "js": [ "content.js" ] } ], "background": { "scripts": ["background.js"] }, "permissions": [ "http://losttime.su/*" ], "browser_action": { "default_title": "LostTime", "default_icon": "", "default_popup": "popup.html" } }

Некоторые из строк должны быть интуитивно понятны, но что обязательно нужно знать:
- Значение manifest_version должно быть обязательно «2»;
- В content_scripts пишем, какой скрипт будет запускаться на всех страницах отдельно;
- В background пишем общий скрипт(фоновый скрипт), который запускается при запуске браузера;
- В permissions пишем адрес сайта, с которого будет браться информация.

Все, что буду использовать я, не обязательно использовать Вам, если вам это по логике просто не нужно. .

То самое окошко, которое Вы можете видеть по клику на иконку расширения - это страница: popup.html.

Она у меня выглядит следующим образом:

popup.html
Потерянное время LostTime

Чтобы было понятнее, описание кода вставил в самом HTML. Меню я организую просто: на картинку ставлю внутреннюю ссылку расширения.

Раз уж начал про popup.html, то расскажу сразу и о popup.js

Выглядит он у меня весьма просто:

popup.js
var xhr = new XMLHttpRequest(); xhr.open("GET", "http://losttime.su/?tmpl=login&token="+localStorage["lostlogin"], true); // тут происходит ГЕТ запрос на указанную страницу xhr.onreadystatechange = function() { if (xhr.readyState == 4) // если всё прошло хорошо, выполняем, что в скобках { var dannie = document.getElementById("dannie"); dannie.innerHTML = xhr.responseText; // добавляем в блок с id=dannie полученный код } } xhr.send();

Описание кода также вставил.

Именно описанная выше конструкция позволяет вытащить и вывести содержание с Вашего, а может и не с Вашего сайта. Но, что важно знать:
- В файле манифеста обязательно в поле permissions пишем адрес сайта, с которого будет браться информация.
- Файл popup.js связан с фоновым скриптом background.js, т.к. данные, занесенные в локальное хранилище на background.js, видны и на popup.js.

Перед тем, как рассмотреть файл фонового скрипта background.js, рассмотрим файл скрипта, который запускается на каждой странице отдельно: content.js

У меня он выглядит так:

content.js
function onBlur() { // окно теряет фокус chrome.runtime.sendMessage({site:sait,time:localStorage}); // отправка сообщения на background.js localStorage = "0"; } window.onblur = onBlur; // если окно теряет фокус function sec() //выполняется каждую секунду { if(document.webkitVisibilityState == "visible")//если страница активна { localStorage = parseInt(localStorage,10) +1; // обновляем данные о сайте в локальном хранилище } } var sait=location.hostname; // на каком сайте находится скрипт localStorage = "0"; setInterval(sec, 1000);// запускать функцию каждую секунду

Наиболее интересный момент из моего скрипта, я считаю, должен быть:
chrome.runtime.sendMessage({site:sait,time:localStorage});
Тут происходит отправка сообщения background скрипту, а именно две переменные: site:sait - содержит адрес сайта, на котором скрипт
time:localStorage - количество времени, проведенное на этом скрипте.

background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { var a = request.site; // данные о сайте var b = request.time; // данные о проведенном времени // тут делаем с этими данными что хотим. });

Вот, собственно, и она. Разбирать подробно ничего не стану, т.к. это в принципе и не нужно. Достаточно знать наглядный пример, чтобы осуществить задуманное. Если в скрипте background.js добавить какие-либо данные в локальное хранилище(а также куки, web sql), то эти же данные можно будет использовать и в popup.js скрипте.

Вот собственно всё, что я хотел поведать о создании расширения, но я затрону еще один момент, в котором у меня возникли трудности.

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

Т.к. данные вставляются посредством InnerHtml, то данная возможность просто так не появится. Вот, что пришлось организовать:

$("#dannie").on("mouseover", ".sait", function() { $(this).css({"border":"3px solid #ffffff"}); }); $("#dannie").on("mouseout", ".sait", function() { $(this).css({"border":"3px solid black"}); }); $("#dannie").on("mousedown", ".sait", function() { $(this).css({"border":"3px solid black"}); }); $("#dannie").on("mouseover", ".sait", function() { $(".sait").draggable({ helper:"clone" }); });
вместо привычного:
$(".sait").mouseover(function(){ $("#"+this.id).css({"border":"3px solid #ffffff"}); }); $(".sait").mouseout(function(){ $("#"+this.id).css({"border":"3px solid black"}); }); $(".sait").mousedown(function(){ $("#"+this.id).css({"border":"0px solid black"}); }); $(".sait").draggable({ helper:"clone", });

В интернете много сайтов на которых реализована возможность пролистывать страницу вверх без помощи мыши или полосы прокрутки. Но в то же время еще есть сайты где такой реализации нет. "Почему бы не попробовать написать скрипт который бы добавлял такую кнопку на все сайты?" - подумал я и принялся за реализацию. Такие скрипты называются пользовательскими и имеют расширение *.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 = $("

"); $(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:\MyChromeExtensionUserJS\backTopUserJS . Добавляем файлы расширения в эту директорию.

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

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

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

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

Итог

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

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

В этой статье будет рассмотрено:

  • Как составлять манифест v.2
  • Как работать с удаленными ресурсами
  • Как работать с cookies
  • Как работать с local storage
  • Как работать с уведомлениями
Введение

К концу статьи у нас будет готово расширение-органайзер, в котором будет поле для добавления новой задачи, а так же список задач на текущий день. Обозначим все требования к органайзеру:

  • Должен иметь поле для добавления события (дата, время, событие)
  • Должен отображать все задачи на текущий день, отсортированные по времени
  • Все прошедшие события должен отображать зачеркнутыми
  • Должен иметь поле для ввода времени, за сколько надо показывать уведомление, а так же чекбокс разрешающий и запрещающий показывать уведомления
  • За указанное время до события должен отображать уведомление о приближающемся событии
Манифест

Начнем создавать расширение с самого начала, то есть с манифеста. Манифест – это тот самый файл, в котром прописываются все параметры расширения. Название, описание, версия, разрешение на доступ к сайтам, разрешение на использование кук, уведомлений, локального хранилища. В общем, манифест – это мозг расширения. Создаем файл manifest.json. Манифест – единственный файл, который должен иметь заранее предопределенное имя, все остальные файлы можно будет называть как угодно. В этом файле есть три обязательных поля:

manifest.json

{ “name”: “Organizer extension”, // Название расширения “version”: “1.0”, // Версия расширения. “manifest_version”: 2 // Версия манифеста }

Тут есть пара правил:

  • Версия манифеста должна быть целочисленной, то есть должна писаться как 2, а не “2”.
  • Версия расширения должна быть строковой, но содержать только числа и точки, то есть “1.0” - хорошо, а 1.0 и “0.9 beta” - плохо.

С обязательными полями – все, перейдем к созданию всплывающего окна расширения. Для того, чтобы по нажатию на пиктограмму, открывалось окно, необходимо добавить в манифест поле “browser_action”

manifest.json

{ … "browser_action": { "default_title": "Open organizer", // Заголовок. Его видно если навести курсор на иконку в браузере "default_icon": "icon_small.png", // Путь к иконке расширения "default_popup": "popup.html" // Путь к странице с попапом } }

Теперь создадим всплывающее окно. Это обычная html страница, которая может быть любого размера и цвета, никаких фокусов. Назовем файл “popup.html”. Создать этот файл мало – его надо указать в манифесте. Так мы и сделали: «default_popup»: «popup.html».

popup.html

It works!

Добавление расширения в браузер

Теперь пришло время проверить работоспособность нашего расширния. Для этого загрузим расширение в браузер. Открываем в хроме меню расширений. Ставим птицу на “Developer mode”.

После этого появятся три кнопки. Нажимаем “Load unpacked extension...”. Выбираем папку с файлами расширения. После этого появится наше расширение. Если все правильно, то по нажатию на иконку – повится окно:

Подключение скриптов

Теперь можно приступить к интересному. Подключим два javascript файла. Первый – popup.js, второй – jquery. С первым проблем не возникнет, но jquery будем подключать не локальный, а удаленный, взятый по адресу ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js . Проблемы возникнут от того, что по умолчанию расширение не имеет доступа к сторонним ресурсам. Чтобы получить доступ, надо его указать в манифесте. Доступ к чему-либо указывается в поле “permissions”. Так же, для удаленных скриптов и css надо указывать доступные удаленные ресурсы.

manifest.json

{ … "permissions": [ "https://ajax.googleapis.com/*" ], "content_security_policy": "script-src "self" https://ajax.googleapis.com; object-src "self"" }

Теперь подключим эти скрипты в popup.html

popup.html

Storage

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

manifest.json

{ ... "permissions": [ … "storage" ] ... }

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

popup.html

Date

Дата Время Задача

И сразу же добавим отображение даты в блоке #today_date.

popup.js

$(function(){ var today = new Date(); $("#today_date").html(today.getDate()+"."+(parseInt(today.getMonth())+1)+"." + today.getFullYear()); }

Выглядеть должно так:

Итак, при нажатии на кнопку “+” у нас должно добавляться событие. Вначале файла объявим глобальную переменную storage – объект для работы с storage, а так же глобальный массив tasks для хранения событий.

popup.js

Var storage = chrome.storage.sync; var tasks = new Array(); $(function(){ … $("#add_task").click(function(){ var new_task = new Object(); new_task.date = validateField($("#new_date").val(), "date"); new_task.time = validateField($("#new_time").val(), "time"); new_task.task = $("#new_task").val(); if(!new_task.task || !new_task.date || !new_task.task){ return false; } tasks = new_task; storage.set({ tasks:tasks }); }); });

Функция валидации проверяет, что дата записана в формате d.m.yyyy, а время в формате hh:mm, а так же, что в описании события не меньше трех символов.

popup.js

Var validateField = function(val, type){ if(type == "date"){ var date = val.split("."); var year = new Date(); year = year.getFullYear(); if(date.length == 3 && parseInt(date) == date && date = 3){ return val; } return null; }

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

popup.js

$(function(){ … var now_hours = today.getHours() < 10 ? "0" + today.getHours() : today.getHours(); var now_minutes = today.getMinutes() < 10 ? "0" + today.getMinutes() : today.getMinutes(); var now_time = now_hours + "" + now_minutes; storage.get("tasks",function(items){ if(items.tasks){ tasks = items.tasks; var today_tasks = getTodayTasks(tasks); if(today_tasks.length >0){ for(var i in today_tasks){ var this_time = today_tasks[i].time.replace(":", ""); var add = this_time > now_time ? "" : " class="done""; var add_html = ""+today_tasks[i].time+" "+today_tasks[i].task+""; $("ul").append(add_html); } } } }); … });

Функция getTodayTasks() возвращает из общего списка только события с сегодняшней датой.

popup.js

Var getTodayTasks = function(tasks){ var today_tasks = new Array(); var today = new Date(); var today_date = today.getDate()+"."+(today.getMonth() + 1)+ "." + today.getFullYear(); for(var i in tasks){ if(tasks[i].date == today_date){ today_tasks = tasks[i]; } } if(today_tasks.length > 0){ today_tasks = sortTasks(today_tasks); } return today_tasks; }

Функция sortTasks() сортирует события по возрастанию времени.

popup.js

Var sortTasks = function(tasks){ if(tasks.length > 0){ var swapped = true; while (swapped) { swapped = false; for (var i=0; i < tasks.length-1; i++) { var this_time = tasks[i].time.replace(":", ""); var next_time = tasks.time.replace(":", ""); if (this_time > next_time) { var temp = tasks[i]; tasks[i] = tasks; tasks = temp; swapped = true; } } } } return tasks; }

Уведомления

Пришло время настроить отображение уведомлений на экране. Добавим во всплывающее окно специальный чекбокс. Если этот чекбокс будет отмечен – уведомлениея будут показываться, если не будет отмечен – не будут. Так же добавим текстовый инпут. Цифра в этом инпуте будет показывать, за какое время до событя будет показываться уведомление. То есть если у нас событие назначено на 19:00, в этом текстовом инпуте будет 5, значит в 18:55 появится уведомление. Добавим в popup.html код с этими инпутами

popup.html

Показывать уведомления

Теперь давайте разберемся с тем, как это будет работать. При нажатии на чекбокс, будет проверяться его атрибут checked, значение атрибута будет записываться в cookie “show_notifications”. Перейдем к текстовому инпуту. По изменению его значения, новое значение будет валидироваться, если оно целочисленное и не больше 120, записываем новое значение в cookie “when_to_notify”.

Но для того, чтобы у нас это заработало, надо открыть доступ к cookies. Для этого заходим в manifest.json и добавляем в “permissions”

manifest.json

{ ... "permissions": [ … “cookies” ] ... }

Теперь можно приступать к скрипту. Заходим в popup.js. Для начала установим первоначальные значения в инпутах. По-умолчанию чекбокс не отмечен, то есть уведомления не показываются, а время равно 0. При клике на чекбокс, будет меняться значение cookie “show_notifications”. При изменении значения в тектовом поле, будет меняться значение cookie “when_to_notify”.

popup.js

$(function(){ setCheckbox(); setWhenToNotify(getCookie("when_to_notify")); ... $("#show_notifications").click(function(){ setCookie("show_notifications", document.getElementById("show_notifications").checked); }); $("#when_to_notify").change(function(){ setWhenToNotify($(this).val()); }); });

Рассмотрим подробнее функции. Начнем с функций работы с cookies. В данном случае были взяты готовые функции с w3schools.com.

popup.js

Var setCookie = function(c_name,value,exdays){ /* *Взято с http://www.w3schools.com/js/js_cookies.asp */ var exdate=new Date(); exdate.setDate(exdate.getDate() + exdays); var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString()); document.cookie=c_name + "=" + c_value; } var getCookie = function(c_name){Позвонить Васе П. /* *Взято с http://www.w3schools.com/js/js_cookies.asp */ var i,x,y,ARRcookies=document.cookie.split(";"); for (i=0;i