2012-07-02 87 views
2

Chrome擴展中發生了一些奇怪的事情。預加載頁面消息的內容腳本背景失敗

內容腳本:

console.log('content'); 

chrome.extension.onRequest.addListener(function(request, sender, sendResponse){ 
    console.log('request received'); 
    sendResponse(); 
}); 

chrome.extension.sendRequest(JSON.stringify({'msg': 'page_loaded'})); 

它只是監聽擴展消息和加載頁面時,將消息發送到後臺。

背景腳本:

console.log('bg'); 

chrome.extension.onRequest.addListener(function(request, sender, sendResponse){ 
    sendResponse(); 
    chrome.tabs.sendRequest(
     sender.tab.id, 
     JSON.stringify({'msg': 'page_loaded_bg_receive'}), 
     function(){ 
      console.log('sendRequest page_loaded_bg_receive callback'); 
     }); 
}); 

它監聽消息,並把消息發送到發送方標籤。

它似乎正在工作,至少在大多數情況下在頁面日誌中出現'請求收到'。

在用戶點擊「輸入」之前,輸入Chrome的URL有時會加載輸入的地址。這是一個奇怪的現象:網頁加載,內容腳本運行時,將消息發送到後臺,但是當後臺發送消息回來 - 它無法與後臺日誌消息:

Port error: Could not establish connection. Receiving end does not exist. miscellaneous_bindings:184 chromeHidden.Port.dispatchOnDisconnect miscellaneous_bindings:184

這是Chrome錯誤?如何將消息發送到預加載標籤?

這是人工最小樣本來重現此類行爲。我需要在處理消息後多次調用'chrome.tabs.sendRequest',因此調用'sendResponse'不是解決方案。

+0

當這種奇怪的行爲出現時,tab具有'index'屬性等於'-1'。回調正在調用,所以實際上我可以調用'chrome.tabs.sendRequest'直到成功。但這似乎很奇怪。 – ZzDmitry

+0

那麼,最新的解決方案?自昨天起我一直在嘗試這樣做,並一直在收到錯誤。當我在彈出窗口中使用sendRequest時,我也遇到了這個錯誤。 – 2012-07-02 13:32:25

+0

你有任何衝突的擴展? PS。您不必使用'JSON.stringify'和'JSON.parse',Chrome會自動(de)通過通道序列化請求。 –

回答

3

解決方案基於文章https://developers.google.com/chrome/whitepapers/pagevisibility。如果document.webkitVisibilityState不是'hidden'或'prerender',我在其他地方聽'webkitvisibilitychange'並等待document.webkitVisibilityState不是'hidden'或'prerender',我運行內容腳本代碼。我認爲檢查'prerender'就足夠了,但是當我打開一個新的空標籤頁時,它會加載document.webkitVisibilityState ='hidden'的頁面,並且此頁面也沒有收到後臺消息。

function isDocumentReady() { 
    return document.webkitVisibilityState != "hidden" && document.webkitVisibilityState != "prerender"; 
} 

if (isDocumentReady()) 
    main(); 
else { 

    function onVisibilityChange() { 
    if (!isDocumentReady()) 
     return; 
    document.removeEventListener(
     "webkitvisibilitychange", 
     onVisibilityChange, 
     false); 
    main(); 
    } 

    document.addEventListener(
    "webkitvisibilitychange", 
    onVisibilityChange, 
    false); 

}