chrome.tabs.sendMessage
Подскажите пожалуйста, как мне отправить сообщение из 2го в 1й скрипт?
Смотрел вот тут описание, но без примера я ничего не понимаю... Есть 2 скрипта, 1й(background.js) висит в приложении постоянно, 2й(maps.js) подключается только к определённым страницам. В background.js chrome.runtime.onMessage.addListener // Отлов сообщений ( function(request, sender, sendResponse) { switch(request.id) // Это типа идентификатор сообщений { case 2: // GET запрос { GetHttpRequest(request.href, {rid: request.rid}) break } } } ) Это дополнительная информация из background.js function GetHttpRequest(href, arg) // Запрос { var xhr = new XMLHttpRequest() xhr.withCredentials = true xhr.onreadystatechange = function(e) { e.data = arg ProcessRequestChange.apply(this, arguments) } xhr.open('GET', href, true) xhr.send(null) } function ProcessRequestChange(e) // Обработчик запроса { var xhr = this if(xhr.readyState != 4) return if(xhr.status == 200) { var html = xhr.responseText switch(e.data.rid) // Это типа идентификатор запроса { case 3: // Покопаться в ответе на 'http://www.site.ru/bla-bla.php' { // Некий код который записывает необходимую информацию в str убрал для экономии var str = 'ответ' // Пусть будет это ответом chrome.tabs.query // Вроде это какое - то событие открытия(или получения) вкладок? ( {active: true, currentWindow: true}, // Х.з function(tabs) { chrome.tabs.sendMessage // Это то, что отправляет ответное сообщение ( tabs[0].id, // Х.з, наверное идентификатор вкладки, куда отправить? {greeting: "hello"}, // Это я так понял и есть ответ? function(response) // А это вообще не нужно вроде... { console.log(response.farewell); } ) } ) break } } } } В maps.js: chrome.runtime.sendMessage // Отправить сообщение в background.js ( {id: 2, href: 'http://www.site.ru/bla-bla.php', rid: 3}, // Сделать запрос на адрес function(response) // Функция ответа не может быть вызвана, т.к. ответ не отправляется из background.js { document.querySelector('#fades').style.display = 'inline' document.querySelector('#guild').style.display = 'inline' document.querySelector('#mercenary').innerHTML = 'jhg' } ) Так вот, вся проблема заключается в том, что в background.js сначала нужно послать запрос, получить ответ, покопаться в ответе, и только потом отправить ответ на сообщение в maps.js. |
*!* - GetHttpRequest(request.href, {rid: request.rid}) */!* + GetHttpRequest(request.href, {rid: request.rid, response: sendResponse}); *!* - chrome.tabs.query // Вроде это какое - то событие открытия(или получения) вкладок? ( {active: true, currentWindow: true}, // Х.з function(tabs) { chrome.tabs.sendMessage // Это то, что отправляет ответное сообщение ( tabs[0].id, // Х.з, наверное идентификатор вкладки, куда отправить? {greeting: "hello"}, // Это я так понял и есть ответ? function(response) // А это вообще не нужно вроде... { console.log(response.farewell); } ) } ) */!* + e.data.response(str); |
Не получается получить текст ответа.
Сделал так, только передал строку с идентификатором: В background.js в обработчике запроса: e.data.response({value: str}) В maps.js: chrome.runtime.sendMessage ( {id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3}, function(response) { alert('ответ пришел\n' + response.value) } ) Что - то ругается: Цитата:
|
chrome.runtime.onMessage.addListener // Отлов сообщений ( function(request, sender, sendResponse) { switch(request.id) // Это типа идентификатор сообщений { case 2: // GET запрос { GetHttpRequest(request.href, {rid: request.rid, response: sendResponse}) break } } *!*return true;*/!* } ) Цитата:
|
Спасибо ))
Всё работает. |
Блин, только что всё работало, и вдруг стало выдавать ошибку в background.js (e.data.response({value: str})):
Цитата:
background.js: function GetHttpRequest(href, arg) { var xhr = new XMLHttpRequest() xhr.withCredentials = true xhr.onreadystatechange = function(e) { e.data = arg ProcessRequestChange.apply(this, arguments) } xhr.open('GET', href, true) xhr.send(null) } function ProcessRequestChange(e) { var xhr = this if(xhr.readyState != 4) return if(xhr.status == 200) { var html = xhr.responseText switch(e.data.rid) { /*-------*/ case 3: // Гильдия наёмников { if(html.indexOf('возвращайся с победой') > -1 || (html.indexOf('у нас нет сейчас заданий') > -1 && html.indexOf('Вы получаете') < 0)) break var s = html.indexOf('align=left rowspan=2>') + 21 var e = html.indexOf('</td>', s) var str = html.substring(s, e) e.data.response({value: str}) break } /*-------*/ case 0: break // Без обработки } } } chrome.runtime.onMessage.addListener ( function(request, sender, sendResponse) { switch(request.id) { /*-------*/ case 6: // Гн { GetHttpRequest(request.href, {rid: request.rid, response: sendResponse}) return true break } /*-------*/ } return false } ) maps.js: chrome.runtime.sendMessage ( {id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3}, function(response) { //alert('ответ пришел\n' + response.value) document.querySelector('#fades').style.display = 'inline' document.querySelector('#guild').style.display = 'inline' document.querySelector('#mercenary').innerHTML = response.value } ) |
А вот так всё работает:
//var s = html.indexOf('align=left rowspan=2>') + 21 //var e = html.indexOf('</td>', s) var str = 'errfsdf'//html.substring(s, e) |
Вот эта строчка:
var e = html.indexOf('</td>', s)тут вы переназначаете переменную "e", соответственно "e.data" уже ничего не содержит.) |
От блин, невнимательность, спасибо ))
|
Вложений: 1
Блин, задолбала уже эта ошибка:
Цитата:
Просто я сделал одну фигню всплывающим окном(вставил часть другой страницы), через localStorage убрал лишние запросы на сайт... Вложение 3343 Вот это всё равно вызывается: chrome.runtime.sendMessage ( {id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3}, function(response) { alert('ответ') document.querySelector('#fades').style.display = 'inline' document.querySelector('#guild').style.display = 'inline' document.querySelector('#mercenary').innerHTML = response.value } ) А это обработчик(ну или прослушиватель, как его там правильно) этого сообщения. Тут всё нормально с return'ами break'ами? Просто я не привык к этой дикости в свитче... chrome.runtime.onMessage.addListener ( function(request, sender, sendResponse) { switch(request.id) { case 4: // Получить значение localStorage { var sid = request.sid sendResponse({sid: sid, value: localStorage[sid]}) break } case 6: // Обработчик { var l = localStorage['mercenary_guild'] if(l != undefined && l > parseInt(+ new Date() / 1000)) break alert('запрос') GetHttpRequest(request.href, {rid: request.rid, response: sendResponse}) return true break } } return false } ) Когда срабатывает это условие: if(l != undefined && l > parseInt(+ new Date() / 1000)) break Появляется ошибка. Я понял, что нет параметра value в ответе(он вообще пустой). Не понятно какого хрена он вообще приходит, ведь там нет sendResponse()... Если всё так и должно работать, можно хотя бы как - то проверить, что ответ пустой? |
Цитата:
проверить на тип undefined лучше typeof L === "undefined"или !!(L) еще лучше проверять на конкретный тип typeof L === "number" второе условие вообще безобразно - чем вам так объект Date не понравился, что вы его на 1000 делите? )) если по-вашему, то if ( !(typeof === "undefined") && L > Math.round(Date.now()/1000) ) |
Цитата:
не назначайте ее, если не надо или function(){} укажите |
Цитата:
maps.js каким образом подключается к страницам? |
Цитата:
Цитата:
|
это eventPage.js (по-вашему background)
list = ['google.ru','mail.ru','yandex.ru']; //chrome.webNavigation.onDOMContentLoaded.addListener(onNavigate); chrome.webNavigation.onCompleted.addListener(onNavigate); function onNavigate(details){ var len = list.length; var tabID = details.id; var tabUrl = details.url.replace(/^https?\:\/\/(www\.)?/, ''); for (var i=0; i < len; i++){ if( tabUrl.startsWith(list[i]) ){ if (details.frameId != 0) break; /*иначе, например, bing "съедает" две загрузки, те msg будет показан 2*/ var siteName = list[i]; var msg = list[i]; chrome.tabs.insertCSS(tabID, {file:"css/content_style.css"}); chrome.tabs.executeScript(tabID, {file: "js/content_script.js"}); tabConnect({msg_:msg, name_:siteName}); }; }; function tabConnect(msg) { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { var port = chrome.tabs.connect(tabs[0].id); port.postMessage(msg); port.onMessage.addListener(function getResp(response){ if(response.close_){ sessionStorage.setItem(response.name_, 3); }; }); }); }; а это в том самом скрипте, который вживляется в указанные в массиве сайты нексолькими строками выше, так называемый content_script.js var siteName; var portName; var div = document.createElement('div'); chrome.runtime.onConnect.addListener(function(port) { portName = port; port.onMessage.addListener(function(msg) { if(msg.msg_) showMessage(msg.msg_); if(msg.name_) siteName = msg.name_; }); }); function showMessage(msg){ div.className = "injection"; div.innerHTML = '<p class="inj_message">' + msg + '</p>'; div.addEventListener('click', clickHandler); document.body.appendChild(div); }; function clickHandler(){ document.body.removeChild(div); portName.postMessage({name_:siteName, close_:true}); }; я, конечно, свой код покрамсал и поэтому могут быть ошибки, но суть такова: сообщение - ответ. если надо длительное общение поддерживать, то лучше создавать именованный канал и не забывать его закрывать, а то скрипты так и будут висеть. |
Цитата:
Цитата:
Math.round(Date.now()/1000) Я уже поменял, просто писал это до того как посмотрел другую тему. Цитата:
Вешается на "невидимую" вкладку. Он нужен, т.к. приложение - бот для онлайн игры. Он работает даже когда нет открытых вкладок с самой игрой. maps.js подключается в манифесте через указанный адрес. Цитата:
Просто мало того, что там всё по английски(гугл перевод конченный), так ещё терминами непонятными сыпят. Ничего не понятно, я не могу ничего там найти, из того, что мне нужно... Спасибо, понял теперь в чём дело. )) Цитата:
Ну и в принципе мне обычного хватит вполне. Т.к. страницы открываются/закрываются... Суть вот в чём, открываю страницу сайта("карта", к ней и подгружается maps.js), получаю 3 ячейки из фонового скрипта(background.js) с настройками. Далее несколько проверок(есть ли задания гильдии наёмников, они либо висят доступные либо сданы и нужно подождать минут 20 до следующего) - запрос на другую страницу(самой гильдии, там пишут доступно или нет и сколько ждать), проверка, вывод посередине страницы части страницы из запроса. Вот я сейчас на этапе "оптимизации" этого не единственного функционала приложения. На странице карты можно узнать взято или нет задание, а остальное только запросом. Чтобы не делать каждый раз запрос(при обновлении карты, а она постоянно в работе), я создал ячейку в памяти и храню в ней время когда будет доступно задание(1й запрос всё - таки делается, чтобы узнать это время). Ну и вот, только на клиентской стороне всё считается... |
Во, всё заработало:
chrome.runtime.onMessage.addListener ( function(request, sender, sendResponse) { switch(request.id) { case 4: // Получить значение localStorage { var sid = request.sid sendResponse({sid: sid, value: localStorage[sid]}) return false break } case 6: // Гн { var l = localStorage['mercenary_guild'] if(l != undefined && l > Math.round(Date.now() / 1000)) break alert('запрос') GetHttpRequest(request.href, {rid: request.rid, response: sendResponse}) break } } return true } ) |
А если нужно несколько раз вернуть ответ(асинхронно), то никак не получится?
Т.е. я 1 раз посылаю сообщение в другой скрипт, а тот что - то там делает, и отправляет ответы, при необходимости... Цитата:
Долгоживущее соединение не поможет? |
Артист, таким образом - да.
Для более сложного "постоянного" общения есть connect. |
Спасибо )
|
Вроде понял, нашел где по русски объясняют...
Так нужно отправлять сообщения из background.js в maps.js chrome.tabs.query // Запрос браузеру на получение id всех вкладок ( {url: "http://www.site.ru/*"}, // Параметры(фильтры) function(tabs) // Функция вызывающаяся после получения { var l if((l = tabs.length) != 0) return // Если нет подходящих вкладок var i = -1 while(++i < l) chrome.tabs.sendMessage(tabs[l].id, {greeting: "hello"}) // Отправка сообщения вкладкам } ) В maps.js должна быть функция chrome.runtime.onMessage.addListener. Я хочу сделать на какой вкладке был запрос, туда и слать ответные сообщения. Т.е. я из maps.js отправляю один запрос в background.js, и уже в этом запросе передаю нужный ид вкладки. В background.js уже будет отослано этой вкладке несколько "ответов". Как получить id текущей вкладки? |
Нашел:
chrome.tabs.getSelected ( null, function(tab) { console.log(tab) } ) Оказалось, что из контент скрипта нет доступа к апи хрома. Уродство. |
Часовой пояс GMT +3, время: 15:48. |