Меню сайта
Наш опрос
Оцените мой сайт
Всего ответов: 5
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » 2014 » Июль » 22 » Пишем расширение для Google Chrome
15:15
Пишем расширение для Google Chrome

Как и любой современный web обозреватель, Google Chrome поддерживает расширения. В этой статье я покажу общий подход к написанию extension`ов, после чего Вы без труда напишете свой собственный плагин.Пример, который я буду показывать, будет называться GoogleMark и его назначением будет метка результатов поиска в google,как показано на скриншоте ниже.Дабы не утомлять тех, кому достаточно прочесть документацию, приведу сразу на неё ссылку. Там Вы найдёте краткий обзор и руководство по быстрому старту. Но, хочу предостеречь читателя о том, что этих вводных данных не достаточно для комфортной работы. Информация о необходимых мелочах раскидана по всей документации. В этой статье я постараюсь дать ссылки на самые важные части документации.Итак, расширения для Google Chrome пишутся на JavaScript. Все файлы расширения должны лежать в одном каталоге. Я буду называть этот каталог каталогом расширения.Для начала я приведу скрипт, который будет раскрашивать страничку результатов поиска google. В нём совсем немного специфичного для расширения кода, по большей части -- это простой JavaScript, который Вы используете при обработке любых web-страниц.googleMarker = { preparePage: function() { var links = document.getElementsByClassName("l"); var count = links.length; for(var i = 0; i < count; ++i) { links[i].removeAttribute("onmousedown"); } }, markUrl: function(url, color) { var block = googleMarker.findMarkingBlockByUrl(url); googleMarker.markBlock(block, color); googleMarker.saveMarker(block, color); }, restoreUrlMark: function(url, color) { googleMarker.markBlock(googleMarker.findMarkingBlockByUrl(url), color); }, findMarkingBlockByUrl: function(url) { var listItems = document.getElementsByClassName("l"); var itemsCount = listItems.length; for(var i = 0; i < itemsCount; ++i) { var item = listItems[i]; if(item.href == 'undefined') { return null; } if(element.className == 'r') { return element; } return googleMarker.findMarkingBlockByNestedElement(element.parentNode); }, markBlock: function(block, color) { if(block == 'undefined') { return; } var image = googleMarker.getImage(color); if(image green": url = chrome.extension.getURL("green.png"); break; case "yellow": url = chrome.extension.getURL("yellow.png"); break; case "red": url = chrome.extension.getURL("red.png"); break; } if(url l")[0]; var url = link.href; chrome.extension.sendRequest( { color: color, url: url } ); }}На случай, если Google поменяет разметку страницы результатов, я приведу HTML одного из блока результатов, которые выдаются сейчас.<div > <h3 > <a href="http://brainstream-dev.blogspot.com/2012/03/c-visual-studio-11.html" > <em>Ещё один блог о программировании</em>: Асинхронное <b>...</b></a> </h3> <div > <div > <div ></div> </div> </div> <div > <div > <cite>brainstream-dev.<b>blogspot</b>.com/2012/03/c-visual-studio-11.html</cite> <span > <a href="http://webcache.googleusercontent.com/search?q=cache:wtBn88UhcVYJ:brainstream-dev.blogspot.com/2012/03/c-visual-studio-11.html+&amp;cd=2&amp;hl=ru&amp;ct=clnk&amp;gl=ru" ','','','2','AFQjCNHoJc76l2Yol_mH3A94wFMHV1Z5AA','t0iOo1MA-N91FmlNaAEdNQ','0CBMQIDAB',null,event)" > Сохраненная&nbsp;копия </a> </span> <button title="Рекомендовать эту страницу" > </button> </div> <div > Вы уже поставили +1 этой странице.&nbsp; <a href="#" >Отменить</a> </div> <span > <span >4 мар 2012 – </span> <em>Ещё один блог о программировании</em>. Все статьи этого блога могут быть использованы в соответствии с лицензией GNU FDL.<br> </span> </div></div>Добавлять картинки я буду слева от ссылки в блоке "h3" с классом "l". Теперь разберём скрипт чуть подробнее.Функция preparePage нужна для того, чтобы убрать все обработчики "onmousedown" из ссылок, иначе ссылка изменится чудесным образом и скрипт её уже никогда не узнает.markUrl и restoreUrlMark делают одно и то же, за исключением того, что markUrl сохраняет метку (об этом чуть позже).Функция getImage получает картинки из расширения. Об этом тоже чуть позже.Все остальные функции являются вспомогательными и просто работают с DOM документа. Сохраним файл со скриптом в каталог расширения под названием googleMarker.js.Итак, я надеюсь, что с тем, как метки будут появляться на страничке, мы разобрались и я перейду непосредственно к теме статьи. МанифестЛюбое расширение Google Chrome должно содержать файл манифеста, определяющий структуру и права Вашего расширения. Манифест для нашего примера будет следующим:{ "name": "GoogleMark", "version": "1.0", "manifest_version": 2, "description": "Marks google search results", "content_scripts": [ { "matches": [ "*://*.google.com/*", "*://*.google.ru/*" ], "js": [ "googleMarker.js" ], "css": [ "googleMarker.css" ] } ], "background": { "page": "background.html" }, "permissions": [ "tabs", "webNavigation", "contextMenus", "*://*.google.com/*", "*://*.google.ru/*" ], "icons": { "16": "menu-icon-16x16.png" }, "web_accessible_resources": [ "green.png", "yellow.png", "red.png" ]}Как видно, манифест представляет собой JSON объект. Файл манифеста сохраняется в корневой каталог расширения и должен иметь имя "manifest.json". Разберём структуру объекта примера.Поля "name", "version", "manifest_version" и "description" понятны без объяснений.Ваше расширение может встраивать в страницы собственные JavaScript`ы и каскадные таблицы стилей. Всё это описывается в поле "content_scripts", которое представляет собой массив объектов с указанием списка файла JavaScript`ов и файлов CSS. Кроме указания файлов, можно указывать шаблоны URL тех сайтов, в которые данный контент должен быть встроен. Спецификацию шаблонов можно найти в документации.Каждое расширение может иметь свою теневую страницу. Эта страница загружается при запуске дополнения и может не иметь никакой разметки, кроме подключения JavaScript`ов. Теневая страница указывается в поле "background".Вы можете явно задать HTML страницу в параметре "page" или, если Вам не нужна страница, то она может быть сгенерирована автоматически, если Вы укажете список скриптов в параметре "scripts".Права, которыми обладает расширение вообще и теневая страница в частности, перечисляются в поле "permissions". В это поле вносятся шаблоны URL, к которым есть доступ у скриптов и список разрешённых модулей API.В поле "icons" перечислены иконки расширения разных размеров. В частности, иконка 16x16 будет использоваться в меню (см. скриншот в начале статьи).В списке "web_accessible_resources" перечисляются те ресурсы дополнения, которые могут быть доступны из страницы браузера. В частности, те скрипты, которые определены в поле "content_scripts" могут получить только те ресурсы, которые здесь перечислены. Функция getImage, в скрипте, приведённом в начале статьи, загружает файлы "green.png", "yellow.png" и "red.png" используя функцию chrome.extension.getURL для получения URL на эти ресурсы. URL ресурсов дополнения выглядит так:chrome-extension://[ID пакета дополнения]/[путь]Полную спецификацию манифеста можно найти в документации. Теневая страницаНепосредственно в теневой странице запрещено исполнение JavaScript политикой безопасности, поэтому код HTML страницы будет представлять из себя только подключение скриптовых файлов и структур HTML для хранения отмеченных страниц. Естественно, что такая организация сохранения высосана из пальца только для того, чтобы продемонстрировать работу с теневой страницей. Вот её разметка.<html> <head> <script src="jquery-1.7.2.min.js"></script> <script src="background.js"></script> </head> <body> <ul ></ul> <ul ></ul> <ul ></ul> </body></html>Как видно, на теневой странице мы можем использовать любые скрипты, в частности, я подключил jQuery. Контекстное менюДля работы с контекстным меню в Google Chrome API служет модуль contextMenus. Для его работы нужно добавить строку "contextMenus" в поле "permissions" манифеста. Добавим в файл background.js функцию для создания меню. Внимание, большинство API функций Google Chrome являются асинхронными и возвращают управление сразу после вызова. Для обработки результатов все асинхронные вызовы опционально принимают функцию обратного вызова.function createMenu() { var urls = [ "*://*.google.com/*", "*://*.google.ru/*" ]; var root = chrome.contextMenus.create({ title: "Mark as", contexts: [ "link" ], documentUrlPatterns: urls }); chrome.contextMenus.create({ title: "Green", contexts: [ "link" ], parentId: root, documentUrlPatterns: urls, onclick: function(info, tab) { chrome.tabs.executeScript(tab.id, { code: "googleMarker.markUrl('" + info.linkUrl + "', 'green')" }); } }); chrome.contextMenus.create({ title: "Yellow", contexts: [ "link" ], parentId: root, documentUrlPatterns: urls, onclick: function(info, tab) { chrome.tabs.executeScript(tab.id, { code: "googleMarker.markUrl('" + info.linkUrl + "', 'yellow')" }); } }); chrome.contextMenus.create({ title: "Red", contexts: [ "link" ], parentId: root, documentUrlPatterns: urls, onclick: function(info, tab) { chrome.tabs.executeScript(tab.id, { code: "googleMarker.markUrl('" + info.linkUrl + "', 'red')" }); } });}createMenu();Всё элементарно. Вызывая функцию chrome.contextMenus.create и передавая в неё детальное описание, мы получаем новый пункт меню. Полное описание объекта, описывающего пункт меню можно посмотреть в документации к функции, а я опишу лишь самые основные.В параметре documentUrlPatterns перечисляются шаблоны URL адресов, на которых пункт меню будет появляться.В списке contexts перечисляются типы элементов, при правом щелчке на которые, будет появляться данный пункт меню. Доступные варианты такие: "all", "page", "frame", "selection", "link", "editable", "image", "video", "audio".Параметр parentId является дескриптором родительского пункта меню. Каждый вызов функции chrome.contextMenus.create возвращает такой дескриптор.Наиболее интересным, для нас, является поле onclick. Сюда помещается обработчик выбора пункта меню. ВкладкиВ функцию обратного вызова onclick элемента меню, помимо информации об элементе, для которого было вызвано контекстное меню, передаётся информация о вкладке, в которой отображается документ с указанным элементом.Одной из самых полезных функций модуля tabs (не забудьте указать значение "tabs" в поле "permissions", в манифесте) является функция chrome.tabs.executeScript. Как ясно из названия, она позволяет выполнить скрипт в документе, который находится во вкладке, идентификатор которой передаётся первым параметром. Вторым параметром передаётся объект, содержащий код скрипта или имя файла со скриптом. Работу этой функции и демонстрируют обработчики onclick пунктов меню. ЗапросыДля синхронизации работы встраиваемых скриптов с теневой страницей Google Chrome API предоставляют возможность скриптам обмениваться информацией посредством запросов. Напомню, как выглядит функция сохранения метки в файле googleMarker.js saveMarker: function(block, color) { var link = block.getElementsByClassName("l")[0]; var url = link.href; chrome.extension.sendRequest( { color: color, url: url } );}В этой функции отсылается запрос с объектом, описывающим маркер для сохранения. Вообще говоря, Вы можете передавать любой объект в качестве запроса в функцию chrome.extension.sendRequest. Кроме того, этой функции можно передать идентификатор дополнения и функцию прослушки ответов.Для работы с функциями из модуля extension не требуется никаких указаний в манифесте.Чтобы наше расширение смогло реагировать на запросы, следует подписаться на их прослушивание. В нашем случае это будет выгладить так:chrome.extension.onRequest.addListener( function(request, sender, sendResponse) { var $list = $("#" + request.color); if($list.lengh <li>").append(request.url)); });Параметры функции обработки события chrome.extension.onRequest довольно очевидны; это запрос, отправитель запроса (идентификаторы вкладки и дополнения) и функция отправки ответа.В нашем случае, мы, воспользовавшись jQuery, добавляем в теневую страницу новый элемент списка. События навигацииGoogle Chrome API предоставляют возможность отслеживать события навигации с помощью модуля webNavigation. Для его использования следует добавить в Ваши "permissions" элемент "webNavigation" в файле манифеста. Модуль предоставляет несколько полезных событий и функций, я же продемонстрирую использование события chrome.webNavigation.onDOMContentLoaded, наступающего, как и следует из названия, после загрузки дерева элементов документа. Мы воспользуемся этим событием для подготовки страницы (удаления атрибута onmousedown) и восстановления сохранённых меток. chrome.webNavigation.onDOMContentLoaded.addListener( function(details) { if(details.frameId googleMarker.preparePage()" } ); var colors = ["green", "yellow", "red"]; for(var i = 0; i < colors.length; ++i) { var $urls = $("#" + colors[i] + " li"); if($urls.length googleMarker.restoreUrlMark('" + this.innerText + "', '" + colors[i] + "')" } ); }); } });В функцию обработки события приходит объект, содержащий идентификатор вкладки, идентификатор фрейма, URL и время окончания загрузки дерева. Идентификатор фрейма равен нулю, если дерево было построено в корневом документе вкладки, иначе -- это уникальный (в пределах вкладки) идентификатор фрейма HTML страницы. Всё остальное из фрагмента кода, приведённого чуть выше, нам уже знакомо. ЗавершениеПоследнее, что нам осталось сделать -- это добавить файлы googleMarker.css, menu-icon-16x16.png, green.png, yellow.png и red.png для отображения всех необходимых элементов..r img { margin-right: 15px;}Теперь плагин готов к установке. Для этого переходим в Google Chrome в меню -> Tools -> Extesions и ставим галку на Developer mode. Нажимаем Load unpacked extension и выбираем каталог с расширением.Теперь мы можем протестировать новое расширение и отладить его. Все встраиваемые скрипты доступны из стандартного инструментария (F12), а чтобы отладить скрипты теневой страницы достаточно нажать на соответствующую ссылку в менеджере дополнений. Иконка и popupИтак, убедившись, что всё работает, мы хотим добавить немного интерактивности в виде иконки расширения и всплывающего окна с кнопкой для очистки всех маркеров.Для этого добавляем файл иконки (icon.png) и два файла для представления popup окна: popup.html и popup.js. Заносим новые сведения в файл манифеста, добавляя поле browser_action{ "name": "GoogleMark", "version": "1.0", "manifest_version": 2, "description": "Marks google search results", "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" }, "content_scripts": [ { "matches": [ "*://*.google.com/*", "*://*.google.ru/*" ], "js": [ "googleMarker.js" ], "css": [ "googleMarker.css" ] } ], "background": { "page": "background.html" }, "permissions": [ "tabs", "webNavigation", "contextMenus", "*://*.google.com/*", "*://*.google.ru/*" ], "icons": { "16": "menu-icon-16x16.png" }, "web_accessible_resources": [ "green.png", "yellow.png", "red.png" ]}Разметка popup.html очень проста <html> <body> <button >Clear markers</button> <script src="popup.js" ></script> </body></html>Здесь только кнопка и подключение скрипта. Выполнение inline скриптов снова отключено по соображениям безопасности.В файле popup.js мы подписываемся на нажатие кнопки и делаем запрос к фоновой странице.var button = document.getElementById("clear-btn");button.addEventListener("click", function() { chrome.extension.sendRequest( { action: "clear" } );});Так как у нас появляется второе событие, то вводим поле action в запрос. По этой причине дописываем значение "save" в запросе на сохранение маркера (файл googleMarker.js) saveMarker: function(block, color) { var link = block.getElementsByClassName("l")[0]; var url = link.href; chrome.extension.sendRequest( { action: "save", color: color, url: url } );}Осталось немного поправить обработчик запросов: chrome.extension.onRequest.addListener( function(request, sender, sendResponse) { switch(request.action) { case "save": var $list = $("#" + request.color); if($list.lengh <li>").append(request.url)); break; case "clear": $("ul").empty(); break; } });Всё готово! Жмём кнопку Reload в менеджере расширений и у нас появляется значок в верхнем правом углу браузера. Теперь Вы можете упаковать ваше расширение в файл *.crx нажав кнопку Pack extestion в менеджере расширений или залить его в Chrome Web Store.Скачать исходный код примера можно здесь.


Быстрое изготовление входных дверей на заказ возможно в магазине www.torea.ru.
Просмотров: 620 | Добавил: admin | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Форма входа
Календарь
«  Июль 2014  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей