Chrome extension: inserting a javascript tag and calling a function
I have a chrome extension that uses a content script in order开发者_运维问答 to dynamically insert a script tag referencing an external javascript file. The code I use is:
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);
The external Javascript contains the following code:
function lfunc(){
alert('RUNNING loaded function');
}
alert('LAST LINE of script');
When I load a page in a tab the "LAST LINE of script" message appears, showing that the script tag is correctly inserted in the DOM.
My extension also has a button (i.e., a browser_action). Now, I would like this button to call lfunc() defined above whenever it is clicked. Unfortunately, my code simply doesn't work.
I use the following code in the background.html page to process the onClick event of my button:
<script>
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null,
{code: "try {lfunc()} catch (e) {alert(e);}"});
}); // it should call lfunc()
</script>
The permissions in the manifest.json file are:
"permissions": [
"tabs", "http://*/*", "https://*/*" ]
Instead of getting the "RUNNING loaded function" message I get the error message "ReferenceError: lfunc is not defined".
What am I doing wrong?
You can execute the external JS file (by injecting it into the DOM (document
in the extension)). The external JS file also has access to the local DOM.
Not possible is communciation between those two:
- User-added Javascript (so non-native) can't be accessed by the extension:
The extension's JS doesn't have access to the page'sjQuery
object, but it does have access to itsdocument.body
. - The user-added Javascript (the page's JS or your added external JS) doesn't have access to the extension:
From the page, you can't access chrome API's, like bookmarks, tabs, browser action etc.
This is done very much intentionally for security reasons.
What I was talking about (sendRequest
and onRequest
) is communication between 'content script' and extension script/background pages. In your case irrelevant =) Sorry.
answers
> I cannot call specific functions within the external JS file from the extension because of the lack of communication capabilities between the two
That's right.
> 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
That's right. The ext JS can contain immediate actions and timers etc, like a normally loaded JS (in the webpage itself) would.
> The code launching granularity from the extension is at external JS level, not at JS function level
What do you mean by JS function level
? The extension JS?
PS
chrome.tabs.executeScript
is not quite as cool as you'd think. Basically what it does is execute a script in the page's context (like content_scripts
). It has, however, the same limits as content_scripts
: it can reach the DOM and native JS functionality, bot not user added JS. An example:
// Inside a `background_page`:
chrome.tabs.executeScript(null, {
"code": "document.body.removeChild(document.body.firstChild);"
});
This works, because only access to the page's (always existing) DOM is required. The following won't work (assuming jQuery was included in the webpage itself):
// Still inside a `background_page`:
chrome.tabs.executeScript(null, {
"code": "jQuery('input').remove();"
});
This won't work, because jQuery
is a foreign, non-native, user-added JS object that's inaccessible to the extension (both background_page
and content_scripts
).
I don't really understand the reason for this last limitation, but it's all about sandboxing and security in Chrome =) Which is a good thing I guess...
BTW
I think the solution to your problem is quite simple... You can make the browser_action
inject external JS into the page's DOM. That's enough, right? The external JS contains logic AND the actual function call. Better solution all around, because the external JS is only loaded when the browser_action
(button) is pushed/triggered. One very slight downside: a very short delay (= downloading the external JS after pushing the browser_action
).
Might I suggest again: put all your extension JS into the extension. This will allow offline functionality and never require a(nother) connection to a third party server.
Replace alert('It doesn't work');
with alert(e);
This should give you a better idea of what the error is. Please post the error.
i needed to invoke a function that was inside one of the pages scripts...
location = 'javascript:callToTheFunction(param,param,..)' did it.
i'm talking from a content
精彩评论