实际上,这是一个不错的方法。从理论上讲(不确定是否相关,例如可能会提供漏洞),它很容易被欺骗。我想这取决于您的上下文环境,这个问题有多么重要。
这里有一个稍微更强的想法:
if (chrome &&
chrome.windows &&
chrome.windows.get &&
typeof chrome.windows.get === 'function' &&
chrome.windows.get.toString() === 'function get() { [native code] }')
这个想法和你的一样,尽管稍微强一些,因为据我所知,使一个对象成为函数并让它的
toString()
值具有该值是不可能的,因为它不是有效的语法,因此即使尝试欺骗该值,除非修改本机代码(这需要不同级别的黑客),否则不起作用。
我不确定像这样检查东西是否需要权限,但我希望思路是清楚的。
更新
我刚意识到“本机代码”语法的想法可以被欺骗,方法是给现有函数取一个别名。例如:
var FakeFn = Object.create;
FakeFn.toString(); // "function create() { [native code] }"
但这可以通过仔细选择我们使用的函数来解决,因为名称出现在字符串中。 get 可能太常见了,但如果我们选择一个不常用的函数名称(例如 chrome.tabs.captureVisibleTab 的 captureVisibleTab),它仅在 Chrome 扩展中实现,那么它仍然是一个非常可移植的解决方案,因为与基本检查不同,代码可以被其他本地用户代码欺骗,预先知道浏览器没有实现任何具有此名称的本机函数,因此在所有浏览器和所有用户代码中仍然安全。
更新
正如 @Mathew 指出的那样,这个想法是可以被愚弄的(尽管似乎只会恶意)。我以为我可以通过比较 Function.prototype.toString 来修补这个问题,但发现即使是那样也可以通过给原始 toString 方法取别名并创建一个新的方法,在某些函数中返回错误的字符串,在其他函数中返回原始字符串,来欺骗它。
总之,我的想法比原来的想法稍微强一些,因为它几乎排除了所有意外碰撞的可能性(比 OP 的想法稍微多一点),但肯定不能防御恶意攻击,就像我最初认为的那样。