我想制作一个Chrome扩展程序,在window
中提供一个新对象。当在加载了扩展名的浏览器中查看网页时,我希望通过Javascript提供window.mything
。 window.mything
对象将具有我将在扩展中定义的一些函数,并且当在启用了扩展名的浏览器中查看页面时,这些函数应该可以从console.log
或任何Javascript文件调用。
我能够使用Content Script成功将Javascript文件注入页面:
var s = document.createElement("script");
s.src = chrome.extension.getURL("mything.js");
document.getElementsByTagName("head")[0].appendChild(s);
mything.js看起来像这样:
window.mything = {thing: true};
console.log(window);
每当页面加载时,我都会看到整个window
对象,因为我希望它在控制台中。但是,我无法从控制台与window.mything
对象进行交互。似乎注入的脚本没有真正修改全局window
对象。
如何从Chrome扩展程序修改全局window
对象?
答案 0 :(得分:37)
你不能,不能直接。来自content scripts documentation:
但是,内容脚本有一些限制。他们不能:
- 使用chrome。* API(chrome.extension的部分除外)
- 使用其扩展程序页面定义的变量或函数
- 使用由网页或其他内容脚本定义的变量或函数
(强调补充)
内容脚本看到的window
对象与页面看到的window
对象不同。
但是,您可以使用window.postMessage
方法通过DOM传递消息。您的网页和内容脚本都会收听消息事件,当您从其中一个地方拨打window.postMessage
时,另一个会收到该信息。 “内容脚本”文档页面上有一个example of this。
编辑:
您可以通过从内容脚本中注入脚本来向页面添加一些方法。但是,它仍然无法与扩展程序的其余部分进行通信,而不使用postMessage
之类的内容,但您至少可以在页面中添加一些内容window
var elt = document.createElement("script");
elt.innerHTML = "window.foo = {bar:function(){/*whatever*/}};"
document.head.appendChild(elt);
答案 1 :(得分:7)
我一直在玩这个。我发现通过将javascript包装到window.location = call中,我可以与浏览器的window对象进行交互。
var myInjectedJs = "window.foo='This exists in the \'real\' window object';"
window.location = "javascript:" + myInjectedJs;
var myInjectedJs2 = "window.bar='So does this.';"
window.location = "javascript:" + myInjectedJs2;
它可以工作,但仅适用于设置的window.location的最后一个实例。如果访问文档的窗口对象,它将具有变量“bar”而不是“foo”
答案 2 :(得分:2)
经过数小时的尝试,并遇到了诸如CORS之类的安全问题,我找到了在Chrome和Firefox上编辑window
对象的方法。您需要为每种策略使用不同的策略:
content_scripts
。script
附加到页面上并使其内联运行自定义代码。像这样:;(function() {
function script() {
// your main code here
window.foo = 'bar'
}
function inject(fn) {
const script = document.createElement('script')
script.text = `(${fn.toString()})();`
document.documentElement.appendChild(script)
}
inject(script)
})()
在Firefox上,由于出现Content-Security-Policy
错误,上述解决方案无法正常工作。但是,至少在目前,以下变通办法目前正在起作用:
content_scripts
,例如inject.js
和script.js
inject
脚本将获取script.js
文件的完整绝对URL 并加载它:;(function() {
const b = typeof browser !== 'undefined' ? browser : chrome
const script = document.createElement('script')
script.src = b.runtime.getURL('script.js')
document.documentElement.appendChild(script)
})()
script.js
将包含您的主要代码:;(function() {
// your main code here
window.foo = 'bar'
})()
答案 3 :(得分:1)
内容脚本可以调用window
方法,然后可以使用这些方法来改变window
对象。这比<script>
代码注入更容易,即使尚未解析<head>
和<body>
(例如使用run_at: document_start
时),也会有效。
// In Content Script
window.addEventListener('load', loadEvent => {
let window = loadEvent.currentTarget;
window.document.title='You changed me!';
});
答案 4 :(得分:1)
Chrome扩展程序content_script
在其自己的上下文中运行,该窗口与窗口分开。您可以将脚本注入页面,因此它在与页面窗口相同的上下文中运行,如下所示:Chrome extension - retrieving global variable from webpage
我能够通过向页面的DOM添加script.js
来调用窗口对象上的方法并修改窗口属性:
var s = document.createElement('script');
s.src = chrome.extension.getURL('script.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
s.remove();
};
并在该注入的脚本文件中创建自定义事件侦听器:
document.addEventListener('_my_custom_event', function(e) {
// do whatever you'd like! Like access the window obj
window.myData = e.detail.my_event_data;
})
并在content_script中调度该事件:
var foo = 'bar'
document.dispatchEvent(new CustomEvent('_save_OG_Editor', {
'detail': {
'my_event_data': foo
}
}))
反之亦然;发送script.js
中的事件并在您的扩展程序的content_script中监听它们(如上面的链接所示)。
请务必在扩展程序的文件中添加注入的脚本,并将脚本文件的路径添加到manifest within "web_accessible_resources"
,否则您将收到错误。
希望能帮助某人\(•◡•)/
答案 5 :(得分:1)
正如其他人指出的那样,上下文脚本不会在与页面相同的上下文中运行,因此,要访问正确的window
,您需要将代码注入页面。
这是我的看法:
function runEmbedded() {
// Put here whatever your script needs to do. For example:
window.foo = "bar";
}
function embed(fn) {
const script = document.createElement("script");
script.text = `(${fn.toString()})();`;
document.documentElement.appendChild(script);
}
embed(runEmbedded);
清洁且易于使用。无论您需要在页面上下文中运行什么内容,都可以将其放在runEmbedded()
中(您可以根据自己的喜好将其命名)。 embed()
函数负责打包函数并将其发送到页面中运行。
答案 6 :(得分:0)
感谢这里的其他答案,这是我正在使用的:
((source)=>{
const script = document.createElement("script");
script.text = `(${source.toString()})();`;
document.documentElement.appendChild(script);
})(function (){
// Your code here
// ...
})
效果很好,没问题。