chrome 扩展无法使用内容脚本和其他方式从谷歌加载外部 javascript
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9886833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
chrome extension unable to load external javascript from google using content scripts and other ways
提问by Jayapal Chandran
I am writing a chrome extension which will enable transliteration for specific textboxes in facebook.
我正在编写一个 chrome 扩展程序,它将为 facebook 中的特定文本框启用音译。
I have used the script tab to load https://www.google.com/jsapiin background.html
我已经使用脚本选项卡在 background.html 中加载https://www.google.com/jsapi
here is the code i have used in a content script i tried to load using ajax and the generic way.
这是我在尝试使用 ajax 和通用方式加载的内容脚本中使用的代码。
when i checked it said google undefined.
当我检查它时说谷歌未定义。
/*
$.ajax({
url: "https://www.google.com/jsapi",
dataType: "script",
});
*/
var script = document.createElement("script");
script.setAttribute('type','text/javascript');
script.setAttribute('src','https://www.google.com/jsapi?'+(new Date()).getTime());
document.body.appendChild(script);
$(document).ready(function()
{
alert(google)
if(window.location.href.indexOf('facebook.com'))
yes_it_is_facebook();
})
function yes_it_is_facebook()
{
// document.getElementsByName('xhpc_message_text')[0].id = 'facebook_tamil_writer_textarea';
// alert(document.getElementsByName('xhpc_message').length)
google.load("elements", "1", { packages: "transliteration" });
google.setOnLoadCallback(onLoad);
}
function onLoad()
{
var options = {
sourceLanguage:
google.elements.transliteration.LanguageCode.ENGLISH,
destinationLanguage:
[google.elements.transliteration.LanguageCode.HINDI],
shortcutKey: 'ctrl+g',
transliterationEnabled: true
};
var control = new google.elements.transliteration.TransliterationControl(options);
control.makeTransliteratable(['facebook_tamil_writer_textarea']);
}
and i have https://www.google.com/jsapiin manifest.json content script array.
我在 manifest.json 内容脚本数组中有https://www.google.com/jsapi。
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-1.7.2.min.js", "js/myscript.js", "https://www.google.com/jsapi"]
}
],
it showed an error
它显示了一个错误
Could not load javascript https://www.google.com/jsapifor content script
无法为内容脚本加载 javascript https://www.google.com/jsapi
here is my manifest.json
这是我的 manifest.json
{
"name": "Facebook Tamil Writer",
"version": "1.0",
"description": "Facebook Tamil Writer",
"browser_action": {
"default_icon": "images/stick-man1.gif",
"popup":"popup.html"
},
"background_page": "background.html",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-1.7.2.min.js", "js/myscript.js", "https://www.google.com/jsapi"]
}
],
"permissions": [
"http://*/*",
"https://*/*",
"contextMenus",
"tabs"
]
}
in that i have added https://www.google.com/jsapifor your understanding and i have tested removing that also.
因为我已经添加了https://www.google.com/jsapi以供您理解,并且我也测试了删除它。
so how do i load that javascript into a document context . that is when ever a web page is loaded... here i specifically loading for facebook. still i have to correct the indexof condition because it is not giving the proper result but that is not the problem to this context of my question.
那么我如何将该 javascript 加载到文档上下文中。那是当网页被加载时...在这里我专门为 facebook 加载。我仍然必须纠正 indexof 条件,因为它没有给出正确的结果,但这不是我问题的上下文的问题。
so please suggest me.
所以请建议我。
回答by Juzer Ali
I don't seem to find any documentation regarding this but I think you cannot mention an http://
path in content_scripts
option. A possible work around could be this:
我似乎没有找到任何关于此的文档,但我认为您不能提及选项中的http://
路径content_scripts
。一个可能的解决方法可能是这样的:
$('head').append("<script type='text/javascript' src='http://google.com/jsapi'>");
Or loading it via ajax request as you have commented out in your code.
或者通过 ajax 请求加载它,正如您在代码中注释掉的那样。
Secondly google.com/jsapi
will have to be loaded before you can use it in your script. In your manifest you are loading your script first and then google.com/jsapi
.
其次,google.com/jsapi
必须先加载,然后才能在脚本中使用它。在您的清单中,您首先加载脚本,然后加载google.com/jsapi
.
A friendly advice:jQuery by default disallows caching by appending timestamp at the end of url. Since the script you are trying to load is not likely to change in short durations you can pass cache: false
as an option for saving load time. Check out this pagefor more info.
Better yet you can bundle the script with your package so that there is no ajax request associated with your extension, that will add to the speed of your extension.
一个友好的建议:默认情况下,jQuery 通过在 url 末尾附加时间戳来禁止缓存。由于您尝试加载的脚本不太可能在短时间内更改,因此您可以将其cache: false
作为节省加载时间的选项传递。查看此页面了解更多信息。更好的是,您可以将脚本与您的包捆绑在一起,以便没有与您的扩展相关联的 ajax 请求,这将增加您的扩展的速度。
回答by Rob W
One of the biggest issues with google.load
is that it cannot properly load resources afterthe page has fully loaded, because the API uses document.write
to inject scripts/styles. To fix the issue, two methods have to be patched:
最大的问题之一google.load
是页面完全加载后无法正确加载资源,因为 API用于document.write
注入脚本/样式。要解决此问题,必须修补两种方法:
(function(g) {
var loader_d = g.loader.d,
setOnLoadCallback = g.setOnLoadCallback;
// Force not to use document.write when the document is loaded
g.loader.d = g.loader.writeLoadTag = function(a, b) {
loader_d(a, b, document.readyState === 'complete');
};
// Executes functions directly when page has loaded
g.setOnLoadCallback = function(a_listener, b) {
if (b || document.readyState !== 'complete') {
setOnLoadCallback(a_listener, b);
} else {
// When the API is not loaded yet, a TypeError with google.
// will be thrown. Not a ReferenceError, because google.* is defined
// Retry max *c* times.
var c = 5;
b = function() {
try {
a_listener();
} catch (e) {
if (e instanceof TypeError && (''+e).indexOf('google.')!=-1) {
if (c--) setTimeout(b, 2000);
}
}
};
b();
}
};
})(google);
Now, problem 2: Content Scripts run in an isolatedenvironment: any properties of the global namespace, window
, are not accessible. So, any injected APIs are notvisible to your Content Script.
现在,问题 2:内容脚本在隔离环境中运行:window
无法访问全局命名空间 的任何属性。因此,您的内容脚本看不到任何注入的 API 。
To fix this, see the following Stack Overflow answer: Building a Chrome Extension.
要解决此问题,请参阅以下 Stack Overflow 答案:构建 Chrome 扩展程序。
回答by Jerinaw
This might help with understanding Chrome's security policies
这可能有助于了解 Chrome 的安全政策
In there is says that if you attach a script tag to the page (not the popup or content script) it loads in the context of the page not your extension. And script from the extension can not talk to scripts of the page. If you look at the page script's you'll see it there but not under your extension scripts.
据说如果您将脚本标签附加到页面(不是弹出窗口或内容脚本),它会在页面的上下文中加载,而不是您的扩展程序。扩展程序中的脚本无法与页面的脚本对话。如果您查看页面脚本,您会在那里看到它,但不会在您的扩展脚本下看到。
I discovered this while trying to inject the Google API script.
我在尝试注入 Google API 脚本时发现了这一点。
script = document.createElement('script');
script.src = "https://apis.google.com/js/client.js?onload=init";
(document.head||document.documentElement).appendChild(script);
The init function is defined in my content script. But the Goolge API script is loaded as a page script. So if I do this
init 函数在我的内容脚本中定义。但是Goolge API 脚本是作为页面脚本加载的。所以如果我这样做
var script = document.createElement('script');
script.innerText = "function init(){ alert('hi'); }";
(document.head||document.documentElement).appendChild(script);
script = document.createElement('script');
script.src = "https://apis.google.com/js/client.js?onload=init";
(document.head||document.documentElement).appendChild(script);
The injected init function is called and I see the alert 'hi'. Not sure if this helps but I figured I'd make a note of it for anyone else struggling with loading the Google apis. I'll update this answer if I figure out a way to actually get it loaded.
注入的 init 函数被调用,我看到警报“嗨”。不确定这是否有帮助,但我想我会为其他在加载 Google api 方面苦苦挣扎的人记下它。如果我想出一种方法来实际加载它,我会更新这个答案。