2014-10-07 132 views
3

我正在构建一个通过websockets与nodejs服务器进行通信的扩展。关键是要跟踪内容的浏览历史记录。这一切似乎工作,但偶尔(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,但这并没有帮助。

像youtube/wikipedia这样的页面似乎永远不会工作,而Facebook /谷歌的作品。

编辑:sendContent回调确实会触发100%的时间,只是传递给它的数据是未定义的。

编辑:这里是清单文件

{ 
    "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 2014-10-07 18:18:36

+0

试过了。有没有区别:( – Ignas 2014-10-07 18:59:02

+0

Hm。在'sendMessage'回调中检查'chrome.runtime.lastError'的值我有一个预感你的内容脚本只是在需要的时候没有。 – Xan 2014-10-07 19:00:42

回答

6

首先,你的理解是sendContent执行的100%的时间是错误的。

正如评论中所建立的那样,sendMessage回调也会在出现错误时执行;而这个错误是,在你的情况,"Receiving end does not exist"


的错误就在于你的内容脚本的舱单申报。 A match pattern"*://*/"只有匹配httphttps 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 2014-10-09 13:38:23

+0

很高兴帮助;我不太确定这是否值得额外奖励,但如果你这样做,我只是“付出代价”来解决其他问题。 – Xan 2014-10-09 14:08:12

+0

你确实为我节省了大量的时间。答案是准确的,我的情况,我相信它会帮助别人在未来:) – Ignas 2014-10-09 14:13:24