2014-10-07 5 views
3

Я создаю расширение chrome, которое связывается с сервером nodejs через websockets. Суть его в том, чтобы отслеживать историю просмотров с содержанием. Кажется, что все работает, но иногда (в 30% случаев) обратный вызов функции, переданной в onMessage.addListener, срабатывает неправильно. Позвольте мне показать вам код:Обратный вызов обратной связи возвращает значение нечасто - Расширение Chrome

background.js

var socket = io('http://localhost:3000/'); 

var tabLoad = function (tab) { 
    socket.emit('page load', tab); 
}; 

var tabUpdate = function (tabid, changeinfo, tab) { 
    var url = tab.url; 
    if (url !== undefined && changeinfo.status == "complete") { 
     tab.user_agent = navigator.userAgent; 
     tab.description = ''; 
     tab.content = ''; 

     socket.emit('insert', tab); 
    } 
}; 

socket.on('inserted', function(page){ 
    socket.emit('event', 'Requesting page content\n'); 
    //page = {tab: page, id: docs._id}; 
    chrome.tabs.sendMessage(page.tab_id, {requested: "content", page: page}, function(data) { 
     socket.emit('content', data); 
    }); 

}); 

try { 
    chrome.tabs.onCreated.addListener(tabLoad); 
    chrome.tabs.onUpdated.addListener(tabUpdate); 
} catch(e) { 
    alert('Error in background.js: ' + e.message); 
} 

содержание сценария - public.js

var messageHandler = function(request, sender, sendContent) { 
    if (request.requested == "content") { 
     var html = document.getElementsByTagName('html')[0].innerHTML; 
     var data = { 
      content: html, 
      page: request.page 
     }; 
     sendContent(data); 
     return true; 
    } 
}; 

chrome.extension.onMessage.addListener(messageHandler); 

Проблема заключается в том, что данные в sendContent иногда не определено, а иногда все в порядке. Любые идеи отладки этого или того, что я делаю неправильно?

Я попытался заменить document.getElementsByTagName('html')[0].innerHTML строкой 'test', но это не помогло.

Страницы, подобные youtube/wikipedia, похоже, никогда не работают, в то время как facebook/google работает.

Редактировать: Обратный вызов sendContent срабатывает в течение 100% времени, когда данные, переданные ему, не определены.

Edit: Вот файл манифеста

{ 
    "manifest_version": 2, 

    "name": "Socket test", 
    "description": "sockets are cool", 
    "version": "1.0", 

    "permissions": [ 
     "http://st-api.localhost/", 
     "http://localhost:3000/", 
     "tabs", 
     "background", 
     "history", 
     "idle", 
     "notifications" 
    ], 
    "content_scripts": [{ 
     "matches": ["*://*/"], 
     "js": ["public/public.js"] 
     //"run_at": "document_start" 
    }], 
    //"browser_action": { 
    // "default_icon": "logo.png", 
    // "default_popup": "index.html" 
    //}, 
    "background": { 
     //"page" : "background.html", 
     "scripts": ["socket-io.js", "background.js"], 
     "persistent": true 
    } 
} 
+0

Попробуйте удалить 'return true;', в этом случае он вам не нужен. – Xan

+0

Пробовал, что. Разница не изменилась :( – Ignas

+0

Hm. Проверьте значение 'chrome.runtime.lastError' в обратном вызове' sendMessage'. У меня есть подозрение, что ваш скрипт контента просто отсутствует, когда это необходимо. – Xan

ответ

6

Во-первых, ваше понимание, что sendContent исполняется 100% времени, является неправильным.

Как указано в комментариях, обратный вызов sendMessage также выполняется, когда произошла ошибка; и эта ошибка, в вашем случае, "Receiving end does not exist"


Ошибка заключается в манифесте декларации скрипта содержимого. A match pattern"*://*/" будет только соответствует страницам верхнего уровня на http и https URI. То есть http://example.com/ будет соответствовать, а http://example.com/test - нет.

Самое легкое исправление "*://*/*", но я бы рекомендовал универсальный шаблон соответствия "<all_urls>".


С учетом этого исправления в коде все еще есть несколько улучшений.

  • Заменить chrome.extension.onMessage (который не рекомендуется) и использовать chrome.runtime.onMessage
  • Изменить sendMessage часть, чтобы быть более устойчивыми, путем проверки chrome.runtime.lastError. Несмотря на широкое разрешение, Chrome по-прежнему не будет вводить какие-либо скрипты содержимого на некоторые страницы (например, chrome:// страниц, Интернет-магазин Chrome)
  • Убедитесь, что вы используете "run_at" : "document_start" в своем скрипте контента, чтобы убедиться, что onUpdated с "complete" не уволен перед вашим скрипт готов.
+0

Удивительный, он работает! Я дам вам 100 репутации в качестве награды за то, что вы не торопитесь! Ура! – Ignas

+0

Рад, что это помогло; Я не уверен, что он достоин дополнительной щедрости, но если вы это сделаете, я просто «заплачу» за другие ответы. – Xan

+0

Ты спас мне огромное количество времени. Ответ точно для моей ситуации, и я уверен, что это поможет кому-то еще в будущем :) – Ignas

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