2011-05-09 87 views
3

我有一個Chrome擴展,它使用內容腳本以便動態插入引用an external javascript file的腳本標記。我使用的代碼是:Chrome擴展程序:插入JavaScript標記並調用函數

var html_doc = document.getElementsByTagName('head')[0]; 
var _js = document.createElement('script'); 
_js.setAttribute('type', 'text/javascript'); 
_js.setAttribute('id', 'chr_js'); 
_js.setAttribute('src', 'http://unixpapa.com/js/dyna1.js'); 
if(!document.getElementById('chr_js')) 
html_doc.appendChild(_js); 

的外部JavaScript包含以下代碼:

function lfunc(){ 
    alert('RUNNING loaded function'); 
} 
alert('LAST LINE of script'); 

當我打開一個頁面的選項卡中的「腳本最後一行」消息出現,表明腳本標記正確插入到DOM中。

我的擴展也有一個按鈕(即browser_action)。現在,我希望這個按鈕在被點擊時調用上面定義的lfunc()。不幸的是,我的代碼根本不起作用

我用下面的代碼background.html頁面來處理我的按鈕的onClick事件:

<script> 
chrome.browserAction.onClicked.addListener(function(tab) { 
    chrome.tabs.executeScript(null, 
    {code: "try {lfunc()} catch (e) {alert(e);}"}); 
    }); // it should call lfunc() 
</script> 

的manifest.json文件的權限是:

"permissions": [ 
"tabs", "http://*/*", "https://*/*" ] 

而不是獲取「RUNNING加載函數」消息我得到錯誤消息「ReferenceError: lfunc未定義爲「。

我在做什麼錯?

+0

外部腳本和內容腳本是完全不同的(私人談話! )範圍。他們不能使用彼此的代碼。然而,他們爲此發明了一些東西:[sendRequest](http://code.google.com/chrome/extensions/extension.html#method-sendRequest)和[onRequest](http://code.google .com/chrome/extensions/extension.html#event-onRequest)但是**爲什麼**你要加載外部腳本? – Rudie 2011-05-10 13:03:37

+0

如果你將lfunc安裝到窗口的全局作用域中並執行它,那麼可能會發生什麼......我要試試這個=) – Rudie 2011-05-10 13:16:28

+0

嗯,我無法讓它工作。內容腳本和背景頁面可以交談,但似乎他們都無法訪問文檔窗口中的用戶內容。(他們可以訪問DOM和標準JS,但不能訪問用戶添加的功能,如外部腳本)。 – Rudie 2011-05-10 13:55:45

回答

9

您可以執行外部JS文件(通過將其注入到DOM中(擴展名爲document))。外部JS文件也可以訪問本地DOM。

不可能是這兩個之間communciation:

  • 用戶添加的Javascript(所以非原生)不能由擴展訪問:
    擴展的JS沒有訪問該頁面的jQuery對象,但它有權訪問其document.body
  • 用戶添加的Javascript(頁面的JS或添加的外部JS)無權訪問擴展程序:
    從頁面中,您無法訪問Chrome API,如書籤,選項卡,瀏覽器操作等。

出於安全原因,這是非常有意地完成的。

我在說什麼(sendRequestonRequest)是'內容腳本'和擴展腳本/後臺頁面之間的通信。在你的情況下不相關=)對不起。

回答

> I cannot call specific functions within the external JS file from the extension because of the lack of communication capabilities between the two

這是正確的。

> All I can do is make my extension inject the external JS file into the DOM. This will execute whatever is there to be executed in the external JS file

沒錯。 ext JS可以包含即時動作和定時器等,就像一個正常加載的JS(在網頁本身)會。

> The code launching granularity from the extension is at external JS level, not at JS function level

你是什麼意思?JS function level?擴展JS?

PS
chrome.tabs.executeScript並不像你想象的一樣酷。基本上它是在頁面的上下文中執行腳本(如content_scripts)。但是,它具有與content_scripts相同的限制:它可以達到DOM和原生JS功能,bot不會向用戶添加JS。舉個例子:

// Inside a `background_page`: 
chrome.tabs.executeScript(null, { 
    "code": "document.body.removeChild(document.body.firstChild);" 
}); 

這樣做是可行的,因爲只需要訪問頁面(總是存在的)DOM。下面是不行的(假設的jQuery被列入網頁本身):

// Still inside a `background_page`: 
chrome.tabs.executeScript(null, { 
    "code": "jQuery('input').remove();" 
}); 

這是行不通的,因爲jQuery是外來的,非本地的,用戶添加的JS對象,是無法進入到擴展(background_pagecontent_scripts)。
我真的不理解這最後一個限制的原因,但它是所有關於在Chrome =)這是我猜的好事沙盒和安全...

BTW
我認爲解決你的問題很簡單...你可以讓browser_action將外部JS插入到頁面的DOM中。這就夠了,對吧?外部JS包含邏輯AND實際函數調用。更好的解決方案,因爲外部JS只在browser_action(按鈕)被按下/觸發時加載。一個非常輕微的缺點:非常短暫的延遲(=推動browser_action後下載外部JS)。

可能我再次建議:將所有的擴展JS放入擴展中。這將允許脫機功能,並且永遠不需要連接到第三方服務器。

+0

謝謝Rudie!如果我正確地理解了你,我不能從擴展中調用外部JS文件中的特定函數,因爲兩者之間缺乏通信能力。我所能做的就是讓我的擴展將外部JS文件注入到DOM中。這將執行任何有待在外部JS文件中執行的內容。從擴展的代碼啓動粒度是在外部JS級別,而不是在JS功能級別。是這樣嗎? – Mike 2011-05-11 21:13:28

+0

回答您的評論在我的答案和一點關於'chrome.tabs.executeScript' – Rudie 2011-05-11 21:28:57

+0

感謝您的示例和您的建議。現在我所處理的問題對我來說很清楚。我認爲這個問題回答了。 – Mike 2011-05-12 17:16:14

1

更換alert('It doesn't work');alert(e);

這應該給你的錯誤是什麼更好的主意。請發佈錯誤。

+0

我插入了警報(e)並重新編輯了我的問題,並提供了一些可能對您有用的信息。我得到的錯誤是「_ReferenceError:lfunc未定義_」。如果我將外部Javascript的內容轉儲到文件** myContentScript.js **中,並將其作爲內容腳本添加到_manifest.json_中,那麼整個過程就行得通!但是這對我來說還不夠**,因爲我希望能夠使用外部JavaScript託管在服務器中,而不是在擴展包中......所以問題仍然存在,爲什麼不這行得通? – Mike 2011-05-10 13:00:43

1

我需要調用,這是內部的網頁腳本中的一個函數...

location = 'javascript:callToTheFunction(param,param,..)' did it. 

我現在是內容