Пользователь
0,0
рейтинг
20 ноября 2009 в 14:06

Разработка → Создание расширения для Google Chrome

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

Для работы с расширениями вам понадобится переключить канал обновлений на Dev или Beta.

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

Расширение будет содержать страницу настроек (options), на которой можно будет выбрать язык интерфейса (русский, английский) и выбрать размер картинки (маленький, большой).



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

{
 "name": "Hubble pictures extension", // Название расширения
 "version": "1.0", // Номер версии
 "description": "Hubble pictures extension", // Описание расширения

 "permissions": [
  "tabs", // Разрешить расширению работать с вкладками
  "http://hubblesite.org/*" // Разрешить расширению обращаться к указанному адресу
 ],

 "browser_action": { // Элементы браузера
  "default_title": "Hubble", // Название кнопки
  "default_icon": "images/icon.png", // Иконка для кнопки
  "popup": "popup.html" // Всплывающее окно
 },

 "options_page": "options.html" // Страница настроек
}


* This source code was highlighted with Source Code Highlighter.

Подробное описание файла manifest.json вы можете получить здесь

Настройки


Создадим страницу настроек — options.html. Приводить полный код страницы я не буду, только интересные, на мой взгляд моменты, а именно сохранение, извлечение настроек и локализация.

Сохранять настройки можно в объекте localStorage, который, по сути, представляет из себя ассоциативный массив, хранящий пары «название», «значение». Например, для сохранения состояния радиокнопки «Размер картинки — Маленький», используется код:

localStorage["previewSmall"] = document.getElementById("previewSmall").checked;

Для восстановления состояния:

document.getElementById("previewSmall").checked = (localStorage["previewSmall"] == "true") ? true : false;

В своем проекте я обернул обращение к localStorage в функцию readProperty чтобы избавится от лишних проверок и получить возможность получения значения по умолчанию:

function readProperty(property, defValue)
{
  if(localStorage[property] == null)
  {
    return defValue;
  }

  return localStorage[property];
}

// Пример вызова
document.getElementById("previewSmall").checked = readProperty("previewSmall", true);


* This source code was highlighted with Source Code Highlighter.

Локализация


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

Идея простая — есть ряд элементов, которые нужно перевести. У них есть идентификаторы. Создается ассоциативный массив или объект, в котором идентификатору элемента соответствует локализованный текст. Функция, которая занимается локализацией «пробегает» по массиву, по идентификатору находит контрол и устанавливает ему текст.

Создадим файл с названием элементов и указанием языка. Язык «регистрируется», путем добавления элемента в выпадающий список «Язык». Например русский язык добавляет в список элемент с текстом «Russian» и значением «ru_RU».

Файл \locale\ru_RU\options.js

RegisterLang();

lang_ru_RU =
{
  lngLanguage: "Язык", // Пара - идентификатор (id) элемента, текст

  lngPreviewSize: "Размер картинки",
  lngPreviewSmall: "Маленький",
  lngPreviewBig: "Большой",
  
  lngSave: "Сохранить",
  lngExit: "Выход"
}

function RegisterLang()
{
  var ctrl = document.getElementById("language");

  ctrl.add(createOption("Russian", "ru_RU"));
}


* This source code was highlighted with Source Code Highlighter.


Этот скрипт добавляется на страницу настроек (options.html)

<script type="text/javascript" src="locale/ru_RU/options.js"></script>

На странице, все локализуемые элементы должны иметь соответствующие идентификаторы, например:

<span id="lngPreviewSmall">Small</span>

Локализацией занимается функция localize

function getSelectedLanguage()
{
  var lang = getSelectedValue("language"); // Возвращает значение выбранного элемента в выпадающем списке "Language"
  return eval("lang_" + lang);
}

function localize()
{
  var lang = getSelectedLanguage();

  // Перебираем все элементы объекта lang_ru_RU
  for(var ctrlId in lang)
  {
    var value = lang[ctrlId];

    // Получить элемент с id
    var ctrl = document.getElementById(ctrlId);

    // Не найден, продолжаем перебор
    if(ctrl == null)
    {
      continue;
    }

    // Найден, определить тип и присвоить значение
    if(ctrl.tagName == "SPAN")
    {
      ctrl.innerText = value;
    }
    else if(ctrl.tagName == "INPUT")
    {
      ctrl.value = value;
    }
  }
}


* This source code was highlighted with Source Code Highlighter.

Теперь, если нам необходимо добавить новый язык, например английский, мы просто создаем папку \locale\en_US, в ней создаем скрипт options.js

RegisterLang();

lang_en_US =
{
  lngLanguage: "Language",
  
  ...

  lngExit: "Exit"
}

function RegisterLang()
{
  var ctrl = document.getElementById("language");

  if(ctrl != null)
  {
    ctrl.add(createOption("English", "en_US"));
  }
}


* This source code was highlighted with Source Code Highlighter.

И добавляем скрипт на страницу

<script type="text/javascript" src="locale/en_US/options.js"></script>

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


Внутри файла popup.html простая разметка, в которой предусмотрено место для загружаемой картинки, кнопки управления и индикатор процесса загрузки.

<ul class="menu">
  <li><img src="images/options.png" onclick="showOptions();"/></li>
  <li><img src="images/update.png" onclick="getPicture();"/></li>
  <li><img src="images/close.png" onclick="closePopup();"/></li>
</ul>

<div id="loader">
  <img src="images/loader.gif" />
</div>

<div id="image" style="display: none;">
  <a href="#" id="hrefPlace" onclick="return openImage();"><img id="imgPlace"/></a>
</div>


* This source code was highlighted with Source Code Highlighter.

В общем ничего интересного. Все интересно вынесено в файл popup.js.

Данный скрипт, используя XMLHttpRequest загружает страницу hubblesite.org/gallery/wallpaper, находит ссылки на изображения, выбирает случайное и отображает в popup-е.

xhr = new XMLHttpRequest();

xhr.onreadystatechange = function() {
if (xhr.readyState == 4)
{
  if (xhr.responseText)
  {
    var xmlDoc = xhr.responseText;

    var imgs = xmlDoc.match(/http:\/\/imgsrc.hubblesite.org\/hu\/db\/images\/hs-[0-9]{4}-[0-9]{2}-[a-z]/g);
    var hrefs = xmlDoc.match(/gallery\/wallpaper\/pr[0-9]{4,}[a-z]/g);

    if (imgs.length > 0)
    {
      var randIdx = Math.floor(Math.random() * imgs.length);

      var imgSize = "-wallpaper_thumb.jpg";

      // Какую картинку показываем?
      if(readProperty("previewBig", "false") == "true")
      {
        imgSize = "-640_wallpaper.jpg";
      }

      showImage("http://hubblesite.org/" + hrefs[randIdx], imgs[randIdx] + imgSize);
    }
  }
}

xhr.open("GET", "http://hubblesite.org/gallery/wallpaper/", true);
xhr.send(null);

function showImage(url, imgSrc)
{
  var imgPlace = document.getElementById("imgPlace");
  imgPlace.setAttribute("src", imgSrc);

  var hrefPlace = document.getElementById("hrefPlace");
  hrefPlace.setAttribute("href", url);

  displayLoader(false);
}


* This source code was highlighted with Source Code Highlighter.

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


Расширение создано, теперь необходимо загрузить его в Chrome. Запускаем Chrome, нажимаем кнопку Настройка и управление , выбираем пункт меню Extensions.



На открывшейся вкладке нажимаем Load Extension..., указываем путь к папке и, если все сделано правильно, видим новую кнопку на панели инструментов.



А в списке расширений видим наше расширение.



Теперь упакуем наше расширение, для того, чтобы его можно было выложить на какой-нибудь ресурс и любой пользователь мог бы скачать и установить его в пару кликов. Для этого, на той же закладке Installed Extensions нажимаем кнопку Pack Extension..., указываем путь к папке, содержащей файлы расширения, поле Private key file в первый раз оставляем пустым.



Нажимаем OK, видим сообщение о том, что расширение упаковано.

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

Архив с исходниками расширения

Практически вся информация, необходимая для разработки расширений сосредоточена на странице Google Chrome Extensions: Developer Documentation. Если этого покажется мало, то всегда можно взять готовое расширение, изменить расширение с crx на zip, распаковать и посмотреть как это сделано «у них».

Так же источником информации, так сказать, из первых рук, может стать список изменений при выходе новых версий Google Chrome.
Дмитрий Рыжков @Terror
карма
223,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (28)

  • +1
    спасибо! взял на заметку
  • +1
    В закладки, однозначно!
    Спасибо за труды, как раз нечто подобное и искал неделю назад :)
  • +5
    судя по всему писать расширения под хром очень просто, этот факт не может не радовать

    • 0
      Еще радует то, что практически в каждом новом релизе они добавляют новые фичи для расширений.
  • +2
    По-моему всё проще: берёшь расширение из примеров, разбираешь, изучаешь, собираешь из него своё, попутно почитывая документацию.
    • 0
      Я так и начинал :)
      Кстати, а под лису начинал учить с хабраголика :)
  • 0
    В бете же еще нет поддержи расширений?

    Кстати, кто сможет написать хабрааддон к хрому?
    • 0
      На сайте с документацией сказано «you need to subscribe to the Dev or Beta channel», значит все-таки поддерживает.

      Про какой хабрааддон идет речь?
      • 0
        сказано, но вот все расширения на www.chromeextensions.org/ имеют статус developer builds.

        вот про такой аддон речь — habrahabr.ru/blogs/firefox/64790/
        • 0
          Что-то мне подсказывает, что надо для начала автору того расширения к Firefox предложить это сделать. Наверняка часть кода можно просто перетащить без изменений.
  • +1
    Очень полезная статья.

    Таким образом можно сделать checker почты или еще что-то подобное.

    Хотелось бы еще иметь представление о работе расширений со страницами, загруженными в браузере.
    Например, под FF есть расширение Evernote, которое помещает выделенный текст на странице в личный блокнот
    • 0
      Для этого используются Content scripts
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Я так понимаю, у аякса тут нет никаких ограничений? это очень радует. наверно на выходных попробую написать кое-какой extension, которого мне очень нехватает
    • 0
      В расширениях можно так же jQuery и другие библиотеки использовать
      • 0
        Я как-то пробовал использовать любимый мутулс, но уже давно, так там выборка с помощю $$() не работала… Надеюсь уже работает. На выходных попробую.
  • 0
    Приложили бы своё расширение для тестов
    • +1
      Забыл разместить ссылку, исправился. В конце статьи ссылка на архив.
      • 0
        И да, забыл финал написать, как делать запакованные екстеншен

        Закрываем хром и

        C:\Users\%username%\AppData\Local\Google\Chrome\Application>chrome.exe --pack-extension=c:\HubblePics

        В итоге *.pem не теряем, а *.crx дарим людям
        • 0
          Нет, не забыл, в конце статьи есть информация об упаковке расширения.
        • 0
          вы пишите экстеншны к хрому? есть работка
  • +1
    Приятно, что настолько же просто, как и для фокса.
    С ужасом вспоминаю создание расширений для ИЕ
    • 0
      Согласен, дрожь берет. Но с другой стороны плагины IE имеют более низкоуровневый доступ, за который приходится платить сложностью кода.
      • 0
        да само расширение, особенно на С#.NET, создать несложно. А вот заставить его выглядеть нормально и воспринимать XP-стили у меня до сих пор не вышло. И это при том, что писал и на С#.NET, и на С++.NET, и на С++ голом, и на Delphi.
        • 0
          Писать не сложно, код он и есть код, но «порог входа» туда высокий. Готовых, рабочих примеров, в свое время, я даже на MSDN не нашел.
          • 0
            фактически, да. Я тоже. Приходилось ломиться сквозь чащу
  • 0
    Всё-таки XML более человечен для таких целей, чем JSON…
    Я имею в виду манифест и локализацию.
  • 0
    Не забудьте добавить в скрипт полезную функцию — автообновление

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