2014-10-07 96 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