Задать вопрос
@netW0rm

Как организовать бмен сообщениями между chrome extensions и web page?

Есть расширение для хрома, с ним нужно общаться с любых страниц интернета по типу: запрос(от страницы) - ответ(от расширения)

Sending messages from web pages не подходит, т.к. в манифесте нужно указать домен. Требуется обмениваться сообщениями с разных доменов, которые сразу в манифест не пропишешь.
"externally_connectable": {
  "matches": ["*://*.example.com/*"]
}


пробовал посылать обычный хттп запрос, перехватывать его в расширении и делать редирект на data URL в котором был ответ с сообщением:
// background.js
const extensionId = 'abcdefg...'
const message = 'xyz'
chrome.webRequest.onBeforeRequest.addListener(details => {
  if (details.url === `http://${extensionId}/`) {
    return {
      redirectUrl: 'data:,' + message
    }
  }
}, { urls: ["<all_urls>"] }, ["blocking"])

// webpage.js
const extensionId = 'abcdefg...'
fetch('http://'+extensionId)
  .then(r => r.text())
  .then(message => {
    console.log(message)
  })

но браузер выдает ошибку
Redirects to data: URL are allowed only when mode is "no-cors".

если включить no-cors fetch не сможет отдать тело ответа и возвратит status == 0

Есть какие-нибудь идеи, коллеги?
  • Вопрос задан
  • 605 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@netW0rm Автор вопроса
Получилось)
Схема такая:
//manifect.json
{
    "name": "test",
    "description": "test",
    "version": "0.1",
    "permissions": [
        "management",
        "<all_urls>"
    ],
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_end"
    }],
    "background": {
        "scripts": ["background.js"]
    },
    "manifest_version": 2
}


//content.js
const script = document.createElement('script')
script.textContent = `${sendMessageToExtension}`
document.documentElement.appendChild(script)

document.addEventListener('pageMessage', ev => {
    chrome.runtime.sendMessage(ev.detail, sendResponse)
})

function sendResponse(response) {
    const event = new CustomEvent(response._id, { detail: response })
    document.dispatchEvent(event)
}

function sendMessageToExtension(extensionId, message) {
    return new Promise((resolve, reject) => {
        const _id = Math.random().toString()

        const event = new CustomEvent('pageMessage', {
            detail: {
                _id,
                message,
                extensionId
            }
        })

        const responseHandler = (event) => {
            resolve(event.detail.message)
            document.removeEventListener(_id, responseHandler)
        }

        document.addEventListener(_id, responseHandler)

        document.dispatchEvent(event)
    })
}


//background.js
chrome.management.getSelf(extension => {
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        if (request.extensionId !== extension.id) return

        // наше сообщение
        const message = request.message
        // готовим ответ
        const response = { result: message.value * 2 }

        sendResponse(Object.assign({}, request, { message: response }))
    })
})


теперь на каждой странице появляется функция sendMessageToExtension
// web page
main()
async function main() {
  const extensionId = 'adifgidpakahghppcfdelejcfgnpdenj'
  const response = await sendMessageToExtension(extensionId, { value: 5 })
  console.log(response.result) // 10
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы