Задача:
Создать расширение для браузера Chrome, которое сможет в любой из открытых табов внедрить необходимый контент и небольшой управляющий модуль для него, и если этот контент внедрен в несколько разных табов, то управляющие модули должны иметь возможность между собой общаться.
Доступные инструменты:
Content Scripts, Background Pages, Message Passing
Алгоритм решения:
Создать общий управляющий модуль который будет создавать модули потомки и управлять ими, наладить с каждым из них механизм обратной связи.
Абстрактный пример:
Общий управляющий модуль (ОУМ), создал 3 потомка (П1, П2, П3), каждый из которых работает в отдельной вкладке. Пользователь произвел действие с П1, П1 используя механизм обратной связи отправил сообщение об этом ОУМу, ОУМ совершил необходимые действия и оповестил П2, П3 о произошедших изменениях.
Конкретный пример:
Пользователь решил в 3 табах использовать расширение, которое меняет бекграунд, в одной из них он решил что его не устраивает новый зеленый фон и он хочет что бы новый фон был светло серым. Он нажимает кнопку которая внедрилась в страницу при открытии, фон страницы меняется на серый, то же самое происходит в остальных 2 табах.
Реализация:
Создаем Background Page которая создается раз и навсегда на время жизни расширения, в нем будем держать общий управляющий модуль (ОУМ).
Когда пользователь входит на страницу и хочет использовать на ней возможности расширения, он нажимает на кнопку расширения, запуская тем самым основной функционал, который внедряет в контент выбранного таба небольшой командный модуль (КМ) (фронтенд html и бекенд javascript), также расширение производит необходимые действия c этим контентом.
main.js
chrome.tabs.executeScript(null, {file: "content_script.js"}); // внедряем командный модуль // совершаем какие то действия с контентом
Как только модуль внедрился он посылает сообщение ОУМу.
content_script.js
chrome.extension.sendMessage({cmd: "tab_add"}, function(response) {}); // отправляем сообщение ОУМу chrome.extension.onMessage.addListener(ext_msg_listener); // создаем слушатель команд от ОУМ function ext_msg_listener () { var cmd = arguments[0].cmd; ... }
ОУМ берет из сообщения идентификатор таба и кладет его в список табов для оповещения.
background.js
chrome.extension.onMessage.addListener( function(request, sender, send_response) { if (request.cmd == "tab_add") { // добавляем в список для оповещения идентификатор таба = sender.tab.id } ... } )
При совершении пользователем действий с КМ, КМ отсылает сообщение ОУМу.
content_script.js
chrome.extension.sendMessage({cmd: "some_msg_from_km"}, function(response) {})
ОУМ, если это необходимо оповещает КМы из списка.
background.js
chrome.extension.onMessage.addListener( function(request, sender, send_response) { ... if (request.cmd == "some_msg_from_km") { // каждому tab_id из списка отсылаем сообщение chrome.tabs.sendMessage(tab_id, {cmd: 'some_command_from_oum', bar: 'buz'}, null) } ... } )
КМ слушает сообщения и услышав необходимую команду от ОУМа выполняет действия.
content_script.js
function ext_msg_listener () { ... if (cmd=="some_command_from_oum") { // делаем что необходимо } }
Когда КМ закрывается пользователем, перед закрытием он оповещает ОУМ.
content_script.js
chrome.extension.onMessage.removeListener(ext_msg_listener); chrome.extension.sendMessage({cmd: "tab_remove"}, function(response) {}); // сообщаем ОУМу о закрытии КМ
Соответственно из списка идентификатор таба убирается.
background.js
chrome.extension.onMessage.addListener( function(request, sender, send_response) { ... if (request.cmd == "tab_remove") { // убираем из списка оповещения идентификатор таба = sender.tab.id } } )
Немного обо мне:
Пишу фронтенды на html+js или objective-c, бекэнды на php или руби (sinatra). Люблю делать интерактивные приложения для IOS, особенно игры. В одно время надо было написать приложение с использованием OpenGL ES 2.0, но все тогда сидели на 1.1, пришлось писать свой, увлекательное было занятие, если есть конкретные вопросы по OpenGL ES 2.0 — задавайте, отвечу.
PS:
Небольшое замечание для тех, кому режет глаз смешение русского текста и иностранных названий. Я придерживаюсь позиции, что если писать название в оригинале, то будет проще искать информацию в первоисточниках.
Можно также было не отправлять сообщения каждый раз, а открыть одно постоянное соединение между КМ и ОУМ.
Если что то требует более обширного объяснение — задавайте вопросы, дополню.
ссылка на оригинал статьи http://habrahabr.ru/post/159145/
Добавить комментарий