2015-10-22 2 views
3

Я пытаюсь написать расширение Chrome с некоторой базовой связью между сценарием контента и фоновой страницей.Сообщения внутри расширения Chrome в ClojureScript

В JavaScript я бы зарегистрировать слушателей в обоих содержание и фоновых страниц, например, в качестве фона страницы:

chrome.browserAction.onClicked.addListener(function(tab) { 
    // Send a message to the active tab 
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 
    var activeTab = tabs[0]; 
    chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"}); 
    }); 
}); 

(взяты из this tutorial).

Другой пример, который работает в Javascript:

// content.js 
chrome.runtime.sendMessage({screenShot: true}, function(response) { 
    console.log("response: " + response); 
}); 

// background.js 
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) { 
    alert('message received!'); 
    console.log("request: " + request); 
    if (request.screenShot) { 
     // do something 
    } 
}); 

Как я могу перевести вышеприведенный код ClojureScript?

Моя первая попытка состояла в том, чтобы создать проект на основе шаблона lein-chrome-extension и использовать Khroma's runtime/connect методы, основанные на ядре-асинхронном режиме. Но я не получаю надлежащую связь между сценами content.cljs и background.cljs. В content.cljs я есть:

(defn init [] 
    (go 
    (let [bg (runtime/connect)] 
     (console/log "content script test") 
     (while true 
     (>! bg :lol-i-am-a-content-script) 
     (console/log "Background said: " (<! bg)))))) 

и background.cljs:

(defn on-connect-listener [] 
    (console/log "on-connect-listener") 
    (go-loop 
    [channel (runtime/on-connect)] 
    (let [content (<! channel)] 
     (console/log "Content script said: " (<! content)) 
     (>! content :fml-i-am-the-background-script) 
     (recur channel)))) 

(defn инициализации [] (на Connect-слушателя))

В консоли Chrome я получаю только «Фон сказал : fml-i-am-the-background-script ", поэтому только сообщения, отправленные фоном на страницу содержимого, но не наоборот (я бы ожидал" Content script сказал: lol-i-am-a-content-script " также).

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

Спасибо!

+1

Можете ли вы показать какие-либо попытки и как они потерпят неудачу? – Xan

+0

@Xan - расширен мой первоначальный вопрос. Благодаря! – siphiuel

ответ

3

Две недели назад я начал работу над расширением chrome в ClojureScript. Я начал использовать Khroma, и у меня не возникло проблем с использованием их библиотеки для достижения двусторонней связи между моей фоновой страницей и сценарием контента (или на моей странице фоновой страницы и всплывающей подсказки). Поэтому я могу подтвердить, что библиотека работает. К сожалению, я не вижу никакой очевидной ошибки в примерах кода здесь.

В качестве побочного примечания: Мне не нравилось, как Khorma «злоупотребляла» каналами code.async для реализации дуплексной связи. Khroma дает вам канальный объект при подключении. Поместив сообщение на него, вы отправите сообщение и, взяв сообщение от него, вы ждете, чтобы получить сообщение. Легко? Но на самом деле это не основной контракт с каналом core.async. Обычно в режиме ввода и приема core.async работает на в той же очереди, и это может быть сделано кем угодно (производитель или потребитель). Хрома фактически превратил его в «канал», в котором две очереди. Один для отправки и один для получения. Если вы поместите что-то на канал, вы не сможете его вернуть (например). Для меня это сначала сбивало с толку. И я думаю, что это вас смущает, а, код, как это трудно читать:

(let [content (<! channel)] 
     (console/log "Content script said: " (<! content)) 
     (>! content :fml-i-am-the-background-script)) 

Проблема в >! который никогда не блокирует (в случае ввода Хрома в случае отправки, и это неблокирующий вызов функции и не имеет никакого отношения к каналу). Но <! может «блокировать», если на канале нет сообщений.

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

Библиотека называется Chromex, и я только что выпустил простой пример проект расширения Chrome вместе с некоторой документацией: https://github.com/binaryage/chromex-sample

Код для фона страницы выглядит следующим образом: https://github.com/binaryage/chromex-sample#background-page

Обратите внимание, что я также обернуть runtime.Port как core.async-подобный канал, но я не претендую на двустороннюю связь. Вы можете только взять! из канала для получения сообщения (обертка канала реализует только протокол core-async/ReadPort). Чтобы отправить сообщение, вы должны использовать отдельный метод протокола post-message!.

+2

Благодарим вас за ответ. Я работаю над вашими примерами. – siphiuel

Смежные вопросы