Создание своих собственных расширений для браузера: Часть 1. Расширение возможностей Chrome

Написание простого расширения для браузера Chrome

У каждого браузера свои сторонники и противники ― и свои преимущества и недостатки. Связывает их то, что люди проводят в браузерах все больше и больше времени. В этом цикле статей показано, как самостоятельно написать расширение для браузеров Chrome, Firefox, Internet Explorer и Safari. Читателю предлагается построить одно и то же простое расширение для каждого браузера, чтобы он смог почувствовать, во что это выливается, насколько трудно или легко решить те или иные типичные задачи и что нужно для распространения своего расширения. Эта статья посвящена расширению для браузера Chrome.

Подготовка

Для этой статьи необходимо загрузить и установить Google Chrome версии 19 или более поздней версии (приведенные здесь примеры относятся к версии 19). Кроме того, понадобится что-то, что можно использовать для редактирования HTML, CSS и JavaScript. Хорошо, если уже есть некоторый опыт работы с Chrome и его расширениями. Покопайтесь в интернет-магазине Chrome (см. раздел Ресурсы). Посмотрите, какие расширения существуют, попробуйте какие-нибудь из них. Это послужит контекстом для настоящей статьи.


Зачем нужны расширения для браузера?

Расширение для браузера может понадобиться по нескольким причинам. Обычно расширения используются для связи браузера с другим приложением или службой. Эту задачу решают Evernote, 1Password и Adobe Shadow и множество других расширений. Или может потребоваться добавить в браузер какие-то новые, недостающие функции, инструменты разработки или средства захвата изображений с экрана. Существуют узкоспециализированные расширения — для отслеживания спортивных результатов, усовершенствования конкретных Web-сайтов, наблюдения за прогнозами погоды и т.п. Расширения используются для самых разных целей. А какое расширение напишем мы?


Какое расширение написать?

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

  • всплывающее окно (отображает черный список);
  • видимый значок браузера (точка входа в расширение);
  • страница свойств (настройка доменов, которые нужно заблокировать, и заменяющих их страниц).

Вкратце, Gawkblocker прикрепляет к каждой вкладке и каждому окну прослушивающий процесс и при изменении URL вкладки или окна проверяет его по черному списку. Если URL соответствует заблокированному домену, запрос перенаправляется на собственную страницу расширения (см. рисунок 1).

Рисунок 1. Расширение Gawkblocker
Расширение Gawkblocker

Gawkblocker определенным образом проникает в браузер и делает некоторые вещи, типичные для расширений. Нам нужно получить ответы на следующие вопросы:

  • Насколько трудно внедриться в пользовательский интерфейс браузера?
  • Как сохранить данные между сеансами браузера?
  • Как разные части расширения взаимодействуют друг с другом?
  • Насколько глубоко можно проникнуть в данные пользователя?

Ответы на все эти вопросы должен дать процесс написания Gawkblocker.


Справочная документация

Вашей справочной документацией будет служить Chrome Extension docs (см. раздел Ресурсы). В основном документация по написанию расширений для Chrome достаточно подробна. Простое одностраничное руководство по написанию расширения Hello World дает самое общее представление о процессе создания расширений, но мало помогает, когда требуется копнуть глубже.


Анатомия расширения для Chrome

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

Все начинается с файла манифеста с именем manifest.json. Этот файл содержит информацию, необходимую Chrome для того, чтобы загрузить расширение — заголовок, описание, необходимые разрешения, ярлык и т.п.

Фоновая страница – это страница, которая запускается и выполняется в своем собственном контексте, независимо от того, сколько вкладок или окон открыто. У расширения может быть только одна фоновая страница. Она нужна для расширений, где должен выполняться процесс, охватывающий все страницы Chrome.

Страницы пользовательского интерфейса (UI Pages) ― это любые страницы, которые расширение представляет пользователю. Это может быть всплывающее окно, страница свойств, страница в составе расширения или страница, заменяющая страницу Chrome по умолчанию (например, страница новой вкладки).

Сценарии ― это файлы JavaScript, которые внедряются в Web-страницы для взаимодействия с ними. Сценарии выполняются в собственном изолированном контексте, но могут получать доступ к модели DOM страницы. Сценарии могут устанавливать связь с другими страницами расширения с помощью специального API передачи сообщений.

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


Манифест Gawkblocker

В листинге 1 представлена файл манифеста Gawkblocker manifest.json.

Листинг 1. Файл manifest.json для Gawkblocker
{
  "name": "GawkBlocker",
  "version": "1.7",
  "description": "Tired of taking the Nerd Bait? Use GawkBlocker!",
  "background_page" : "background.html",
  "options_page": "options.html",
  "icons": {
    "16" : "images/GB-19.png",
    "48" : "images/GB-48.png",
    "128" : "images/GB-128.png"
  },
  "browser_action": {
    "default_icon": "images/GB-19.png",
    "default_title": "GawkBlocker",
    "default_popup": "popup.html"
  },
  "permissions": ["tabs"]
}

Рассмотрим некоторые из этих операторов подробнее.

version
Всякий раз при загрузке новой версии расширения в интернет-магазин Chrome нужно увеличивать номер версии, иначе загрузка не произойдет.
icons
Свойство icons содержит список доступных значков, отсортированный по размерам. Chrome находит значки определенного размера и использует их в разных контекстах. В листинге 1 указаны пути к файлам значков, относящихся к расширению.
browser_action
Параметр browser_action сообщает Chrome, что значок должен располагаться справа от поля адреса (которое в Chrome называется Omnibar) и что нажатие на значок должно вызывать то или иное действие. В данном случае нажатие на кнопку действия браузера открывает всплывающее окно.
Параметр browser_action указывается только тогда, когда расширение применимо к любой Web-странице. Если нужно, чтобы оно применялось только к определенным страницам или типам страниц, следует указывать page_action. Нельзя указать и page_action, и browser_action — только то или другое.
permissions
В данном случае единственное разрешение, которое нужно запросить, это tabs — оно обеспечит получение некоторой информации об отдельных вкладках (на самом деле нужен только URL). Доступны и другие разрешения, но следует запрашивать только те, которые действительно нужны. Chrome и Android обрабатывают разрешения очень похожими способами — когда пользователь устанавливает расширение, Chrome явно показывает разрешения, запрашиваемые этим расширением, что очень напоминает список разрешений, который появляется при установке Android-приложения.

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


Основной класс Gawkblocker

Большинством действий Gawkblocker управляет один основной файл JavaScript. В этом файле определяется объект Storage Manager (SM) для сохранения данных между сеансами (пока это просто оболочка для localStorage) и объект Gawkblocker (GB), который управляет некоторыми общими функциями (черным списком и свойствами). См. листинг 2.

Листинг 2. Определение объектов Storage Manager и Gawkblocker
var SM = (function () {

    var my = {};

    my.get = function (key) {
        return localStorage.getItem(key);
    }

    ...

    return my;

}());

var GB = (function (SM) {
    var my = {};

    my.blockTheseSites = {
        "gawker.com"        : "Gawker Media",
        "io9.com"           : "SciFi Blog",
        "gizmodo.com"       : "Gadget Blog",
        ...
    }

    if (!SM.get("blocklist")) {
        SM.put("blocklist", JSON.stringify(my.blockTheseSites));
    }

    my.getBlockedSites = function () {
        return JSON.parse(SM.get("blocklist"));
    }

    my.setWatchThisInstead = function (value) {
        ...
    }

    my.getWatchThisInstead = function () {
        return SM.get("instead");        
    }

    my.addBlockedSite = function (site) {
        my.blockedSites = JSON.parse(SM.get("blocklist"));
        my.blockedSites[site] = "Custom Add";
        SM.put("blocklist", JSON.stringify(my.blockedSites));
    }

    my.removeBlockedSite = function (site) {
        my.blockedSites = JSON.parse(SM.get("blocklist"));
        delete my.blockedSites[site];
        SM.put("blocklist", JSON.stringify(my.blockedSites));
    }

    return my;
}(SM));

Здесь для создания объектов, которые должны быть в разумных пределах переносимыми, я использовал Module Patten. Теперь посмотрим, как их использовать на фоновой странице.


Фоновая страница

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

В листинге 3 приведен код, который прослушивает вкладки на наличие изменений.

Листинг 3. Прослушивание вкладок на обновление
chrome.tabs.onUpdated.addListener(function(tabId, changedInfo, tab) {
    for (site in GB.getBlockedSites()) {
        if (tab.url.match(site)) {
            chrome.tabs.update(tabId, {"url" : GB.getWatchThisInstead()}, 
function () {});
        }
    }
});

Существуют более эффективные способы поиска сайтов в черном списке, но мы не будем останавливаться на этом. Лучше рассмотрим, как подключиться к Chrome с помощью chrome.tabs.onUpdated.addListener и передать обратный вызов.

Каждый вызов API chrome.* индивидуален, но в целом все они следуют одной и той же модели вызова метода и передачи обратного вызова. Большинство вызовов API асинхронны. Это может вызвать проблемы синхронизации, если такое поведение не запланировано, поэтому следует прочесть документацию на эту тему.


Всплывающее окно

На самом деле всплывающее окно для Gawkblocker не обязательно, но его добавление обеспечит легко доступное место, где пользователь может увидеть, какие сайты в настоящее время заблокированы. В листинге 4 показана наиболее интересная часть кода этого окна.

Листинг 4. Всплывающее окно
$(document).ready(function(){
    $.each(chrome.extension.getBackgroundPage().GB.getBlockedSites(), 
function (index, value) {
        $("#blockedlist").append("<div class='siterow' title='"+value+"'>
<div class='sitename'>"+index+"</div><span class='sitedesc'> : 
"+value+"</span></div>");
    });
});

Вызов chrome.extension.getBackgroundPage().GB.getBlockedSites() - это способ передачи информации из фоновой страницы во всплывающее окно. Это один из способов связи между страницами внутри расширения, хотя в случае всплывающего окна это делать не обязательно. Можно включить файл gawkblocker.js и непосредственно обратиться к объекту GB. Но если у вас много асинхронных действий, то полезно сделать так, чтобы разные компоненты задавали вопросы из одного и того же места.

Всплывающее окно запрашивает у фоновой страницы список заблокированных сайтов. Затем этот список просматривается, и информация о заблокированных сайтах добавляется в тег div отображения всплывающего окна (см. рисунок 2).

Рисунок 2. Всплывающее окно
Всплывающее окно Gawkblocker

Страница свойств

Где-то нужно управлять поведением расширения. Если указать страницу Options в манифесте (как мы и сделали), то пользователь сможет легко получить доступ к этой странице как со страницы управления расширениями, так и щелкнув правой кнопкой мыши на кнопке действия браузера. Сами страницы свойств тоже настраиваются (см. Рисунок 3).

Рисунок 3. Страница свойств
Страница свойств Gawkblocker

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

Листинг 5. Страница свойств
$("#blockthistoo").click(function () {
    GB.addBlockedSite($("#dontgothere").val());
    ...
});

С фоновой страницей можно поступить точно так же, как со всплывающим окном (см. листинг 6).

Листинг 6. Фоновая страница
$("#blockthistoo").click(function () {
    chrome.extension.getBackgroundPage().GB.addBlockedSite($("#dontgothere").val());
    ...
});

В зависимости от расширения можно отдать предпочтение тому или иному методу.


Переадресация

Наконец, когда запрос перенаправлен, он должен адресоваться к локальной странице. Это самая простая страница. Как следует из надписи, это просто страница с видеороликом из YouTube (Hey You! Don't Watch That! Watch This! – Эй! Туда не ходи! Сюда ходи!). Она никоим значимым образом не взаимодействует с остальной частью расширения, это просто конечная точка процесса (см. рисунок 4).

Рисунок 4. Переадресация
Переадресация

Объединение всех компонентов

Теперь у вас есть отличное расширение, но как его протестировать? Для начала загрузите неупакованные файлы расширения. Это называется загрузкой распакованного расширения, и ею можно управлять со страницы управления расширениями (см. раздел Ресурсы) (или же щелкнуть правой кнопкой мыши на любом установленном расширении и выбрать Управление расширениями).

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

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


Публикация упакованного расширения

На странице управления расширениями рядом с кнопкой загрузки распакованного расширения есть кнопка Упаковка расширений (см. рисунок 5). Эта кнопка запускает процесс упаковки расширения с целью его последующего распространения. Chrome запросит каталог с распакованным расширением и при необходимости ― файл секретного ключа. Ниже я вернусь к этому файлу.

Рисунок 5. Страница управления расширениями
Страница управления расширениями Chrome

В первый раз при упаковке расширения Chrome сгенерирует два файла: .crx и .pem. Файл .crx ― это упакованное расширение, готовое к распространению. Файл .pem ― вышеупомянутый секретный ключ. Chrome сообщит, что этот файл нужно надежно сохранить — если вы захотите упаковать обновление своего расширения, то вам понадобится этот файл секретного ключа. Без него Chrome будет рассматривать обновление как совершенно новое расширение.

Упаковав расширение, его можно распространять любым способом — по электронной почте, через свой Web-сайт, посредством программы установки, на флэш-накопителе и т.п. Оборотная сторона самостоятельного распространения ― вам придется управлять и процессом обновления.

Чтобы расширение для Chrome проверяло наличие обновлений, добавьте в файл манифеста строку, указывающую, где искать обновления (см. Листинг 7).

Листинг 7. Проверка обновлений
{
  "name": "GawkBlocker",
  "version": "1.7",
  "update_url": "http://yourawesomedomain.com/ext/updates.xml",
  ...
}

Затем нужно разместить XML-файл, соответствующий формату, приведенному в разделе Autoupdating документации. Это не сложно, но все же это дополнительная работа. И это означает отсутствие всякого присутствия в интернет-магазине Chrome.


Помещение расширения в интернет-магазин Chrome

Процесс помещения расширения в интернет-магазин Chrome технически менее сложен, чем самостоятельное распространение расширения, но все же придется кое-что сделать.

Во-первых, нужно зарегистрироваться в интернет-магазине в качестве разработчика. Для этого нужна учетная запись Google. Перейдите на панель разработчика (Developer Dashboard) и зарегистрируйтесь в качестве разработчика. Это будет стоить $5.00, и заплатить нужно с помощью кошелька Google (Google Wallet). Если учетная запись Google уже есть и активно используется, с панелью разработчика можно начинать работать сразу. Если это новая учетная запись или она использовалась редко, может потребоваться время на ее проверку.

Зарегистрировавшись как разработчик, вернитесь в каталог со своим распакованным расширением и заархивируйте все файлы расширения — HTML, CSS, JavaScript и любые графические файлы. Файлы .crx и .pem в архив не включайте. Интернет-магазин Chrome создаст файл .crx из вашего архива и подпишет его с помощью файла секретного ключа .pem.

При наличии учетной записи и zip-файла достаточно нажать большую синюю кнопку Add new item (Добавить новый продукт) на панели разработчика, и расширение будет загружено (см. рисунок 6).

Рисунок 6. Интернет-магазин Chrome
Интернет-магазин Chrome

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


Как работают обновления

Как только расширение окажется в магазине, внесите пару небольших изменений и загрузите обновление в магазин, чтобы понять, как это работает. Типичная ошибка ― забывают обновить номер версии в файле манифеста. После загрузки обновления нажмите кнопку Update extensions now (Обновить расширения) на странице управления расширениями, чтобы принудительного обновить его. Расширения Chrome проверяют наличие обновлений каждые несколько часов, так что пользователи очень скоро получат новую версию.


Найденные ответы

Теперь посмотрим, какими оказались ответы на наши вопросы.

Насколько трудно внедриться в пользовательский интерфейс браузера? Оказывается, довольно легко. Достаточно указать browser_action в файле манифеста и добавить значок.

Как сохранить данные между сеансами браузера? В Chrome разработчик получает доступ к постоянному хранилищу localStorage. Это значительно облегчает сохранение данных между сеансами браузера.

Как разные части расширения взаимодействуют друг с другом? Все страницы сообщаются с фоновой страницей через chrome.extension.getBackgroundPage(), а API передачи сообщений позволяет разным компонентам расширения при необходимости общаться друг с другом.

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


Заключение

Написав простое расширение для Chrome, вы вскоре почувствуете потребность пойти дальше. Можно получить доступ к разнообразным API chrome.*, и это только начало. Усвоив основы, принимайтесь за работу и посмотрите, как далеко вы сможете зайти в освоении Chrome.


Загрузка

ОписаниеИмяРазмер
Исходный код для статьиGawkBlocker.zip60 KБ

Ресурсы

Научиться

Получить продукты и технологии

  • Используйте версию Google Chrome из Developer Channel, чтобы получить новейшие инструменты разработки.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Web-архитектура, XML
ArticleID=861328
ArticleTitle=Создание своих собственных расширений для браузера: Часть 1. Расширение возможностей Chrome
publish-date=03132013