我正在使用一些需要作为页面运行的代码,如果它作为Chrome Extension运行,我希望能够做更多的事情。我正在使用的是:
<script>
if (chrome && chrome.extension) {
// extension stuff
}
</script>
这似乎很不错capability detection。使用用户代理字符串会给我带来麻烦,因为无论上下文(网页与扩展名)如何都是一样的。
问题:是否还有其他更可靠的技术可用于检测Chrome扩展程序中是否有一段代码正在运行?
更新:我想知道是否可以将某些内容放入我的manifest.json
文件中,然后我可以回读。请注意,我正在处理的扩展不是一直运行的持久性事物,它是一个在单个窗口或浏览器选项卡中运行的内容应用程序,无需与其他窗口或选项卡或其他任何内容交互
答案 0 :(得分:23)
这里有很多复杂的答案,而您可以通过检查chrome.runtime.id
的存在和非空虚来轻松检测您是否在Chrome扩展程序中运行:
if (window.chrome && chrome.runtime && chrome.runtime.id) {
// Code running in a Chrome extension (content script, background page, etc.)
}
答案 1 :(得分:4)
务实地说这是一个很好的方法。从理论上讲(不确定这是否相关,例如可能提供漏洞),它可以非常容易地被欺骗。我想这取决于你的背景是多么相关。
这是一个稍微强烈的想法:
if (chrome &&
chrome.windows &&
chrome.windows.get &&
typeof chrome.windows.get === 'function' &&
chrome.windows.get.toString() === 'function get() { [native code] }')
这个想法和你的想法一样,虽然它稍微强一点,因为AFAIK有一个对象是一个函数并且它的toString()
值具有该值是不可能的,因为它不是有效的语法,所以即使试图欺骗它除非您更改了本机代码(这需要完全不同级别的黑客),否则该值将无效。
不要随便记住,检查这样的事情是否需要权限,但我希望这个想法很明确。
<强>更新强>
我刚刚意识到,通过别名现有函数,可以欺骗“本机代码”语法理念。 E.g。
var FakeFn = Object.create;
FakeFn.toString(); // "function create() { [native code] }"
但是可以通过仔细选择我们使用的函数来处理,因为名称出现在字符串中。 get
可能过于常见,但如果我们采用仅在Chrome扩展中实现的模糊函数名称(如captureVisibleTab
chrome.tabs.captureVisibleTab
),它仍然是一个非常便携的解决方案,因为基本检查代码可以被其他本地用户代码欺骗,事先已知浏览器没有实现具有此名称的任何本机函数,因此它在所有浏览器中仍然是安全的并且具有所有用户代码。
<强>更新强>
正如@Mathew指出的那样,这个想法是可以实现的(虽然看似只是恶意)。我认为我可以通过与Function.prototype.toString
进行比较来修补问题,但认为即使可以通过对原始toString
方法进行别名并创建一个新的方法来愚弄,因为某些函数会返回假字符串,而其他函数会返回原始字符串。
总之,我的想法比原版略强,因为它几乎可以排除所有无意碰撞的机会(略高于OP的想法),但当然我无法防范恶意攻击可能是。
答案 2 :(得分:2)
我知道这已经过时了,但我想我会提供另一种选择。您可以将另一个javascript文件添加到chrome扩展,因此它包含两个.js文件。 manifest.json会有:
"js": ["additionalscript.js", "yourscript.js"]
additionalscript.js可以简单地声明一个变量var isextension = true
。 yourscript.js可以查看typeof isextension != 'undefined'
。
但也许是一个更有趣的例子,它可以宣告
var adminpassword='letmein'
现在yourscript.js在扩展程序中运行时只能访问adminpassword。
(如果插件位于可能受到攻击的计算机上,您当然不会在脚本文件中嵌入密码)
答案 3 :(得分:2)
我需要类似的东西。
但我并不需要关心试图欺骗代码的网站。
const SCRIPT_TYPE = (() => {
if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) {
return 'BACKGROUND';
} else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) {
return 'POPUP';
} else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) {
return 'WEB';
} else {
return 'CONTENT';
}
})();
上面应该检测4个场景
答案 4 :(得分:1)
我注意到在Chrome中,无法删除chrome对象,即全局窗口对象的属性。如果是用户定义属性删除操作成功。所以你可以用这种方式测试:
var isRunningInExtension = (!(delete window.chrome) && chrome.extension) ?
true : false;
更新: 上面的行并不能保证代码在chrome扩展中运行。每个人都可以使用“扩展”属性创建一个名为“chrome”的对象,然后冻结/密封该对象 - 这样做就足以通过检查,并且您的代码在chrome扩展中运行的结果不正确。
确保您在扩展程序中运行代码,您必须在运行任何javascript之前测试全局chrome对象 - 这样您就可以保证在测试之前不会创建假的chrome对象。
一种可能的解决方案是使用iframe - 在我下面的示例中,我使用iframe的sandbox属性来指示iframe不执行任何脚本(甚至脚本标记中包含的脚本) - 这样我就可以确保没有脚本能够修改全局window.chrome对象。
(function() {
var isChromeExtension = (function () {
var contentWindow,
iframe = document.createElement("iframe"),
isChromeExtension;
// test for sandbox support. It is supported in most recent version of Chrome
if ("sandbox" in iframe) {
try {
iframe.sandbox = "allow-same-origin";
iframe.src=location.href;
iframe.style="display: none";
document.body.appendChild(iframe);
contentWindow = iframe.contentWindow;
isChromeExtension = !!(contentWindow.chrome && contentWindow.chrome.extension);
document.body.removeChild(iframe);
} catch(e) {}
}
return isChromeExtension;
}());
}());
结果可能是:
答案 5 :(得分:1)
Chrome不提供任何直接API来检查在扩展程序弹出窗口或Chrome页面视图中运行的应用程序的运行状态。但是,一个间接技巧可以工作,我们可以匹配扩展主体分辨率等于或小于CSS中指定的(在这种情况下,扩展弹出窗口将打开)或大于(在这种情况下,网页视图将是打开)。
答案 6 :(得分:0)
要检测Chrome应用和扩展程序,请使用:
chrome.app.getDetails()