在Chrome包应用中评估

时间:2012-08-10 07:20:32

标签: javascript google-chrome google-chrome-extension eval google-chrome-app

我想创建一个包app chrome扩展,以允许用户编写和执行javascript代码(如javascript控制台)。

我想使用eval()函数来执行JS代码。

经典的javascript eval函数在从chrome扩展程序调用时会抛出错误:

  

未捕获错误:从此上下文不允许的字符串生成代码

要在Chrome扩展程序中使用eval,人们需要使用sandbox,但是当我在清单中编写沙箱时,我会收到此错误:

  

尝试安装此扩展程序时出现警告:   指定的包类型(主题,应用等)不允许使用“sandbox”。

更新

根据this issue,包应用不支持沙盒,所以我有两个问题:

  1. 我可以使用其他方法代替eval()吗?

  2. 是否可以在没有沙箱的情况下使用eval? (我想可能不是出于安全原因?)

6 个答案:

答案 0 :(得分:30)

<强>更新

自2013年1月以来,Chrome现在允许unsafe-eval内容安全策略(CSP)指令,该指令允许在沙箱外执行eval

  

可以通过添加 eval() 来放宽针对setTimeout(String)及其亲属的政策,例如setInterval(String)new Function(String)'unsafe-eval'你的政策

为您的扩展程序清单添加适当的CSP,例如:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

bug you refer to现已标记为fixed,自Chrome 22以来就已包含在其中。

在引入'unsafe-eval'之前,没有办法让manifest_version: 2扩展名的CSP允许执行任意文本作为代码。 At the time,Google明确表示没有办法删除此限制(在沙盒之外):

  

内联JavaScript以及危险的字符串到JavaScript方法(如eval)将不会被执行......没有机制可以放宽对执行内联JavaScript的限制。特别是,设置包含unsafe-inline的脚本策略将不起作用。这是故意的。

如上所述,现在可以放宽此限制。

答案 1 :(得分:6)

我想你在谈论新的打包应用程序(清单版本2),对吧?

Sandboxes绝对可以在新的打包应用中使用。上周我刚刚上传了a sample,它正是这样做的:一个窗口向一个隐藏的沙盒iframe发送一条消息,iframe编译一个把手模板(这里它可以使用eval代替)并将编译后的HTML返回到托管页面,这显示了结果。

您还可以查看this other sample,它完全符合您的要求。

所以,直接回答你的问题:

1)否,因为CSP的限制。评估Chrome打包应用中动态JavaScript的唯一方法是沙盒iframe。如果这不是您应用的选项,您还可以发送和评估服务器中的JavaScript内容,并仅将结果返回给用户(尽管这会破坏Chrome打包应用的离线功能)

2)不,你只能在沙盒iframe中使用eval()。

答案 2 :(得分:1)

你可以试试......

function evalMe(code){
    var script = document.createElement('script');
    script.innerText = code;
    document.querySelector('head').appendChild(script);
}

这应该创造相同的效果,除非他们也禁用它,但据我所知,这很好。当然,如果脚本errors你不会听到它,除非你把string包裹到eval,例如

function myHandler(err){
    // handle errors.   
}

function evalMe(code){
    var script = document.createElement('script');
    var wrapper = '(function(){ try{ @@ }catch(err){ myHandler(err); } })()';
    // Make sure the string has an ending semicolon
    code = code[code.length-1] === ';' ? code : code + ';';

    script.innerText = wrapper.replace('@@', code);
    document.querySelector('head').appendChild(script);
}

或者你可以使用官方机制

http://developer.chrome.com/beta/extensions/tabs.html#method-executeScript

但是,这需要您在app页面和背景页面之间使用background page并使用message passing

更新工作方法

您可以使用iframe和eval编码base64创建dataURI类似方法,该方法可处理扩展程序页与<iframe>之间的邮件传递。您可以获取code on github的工作副本。要使用简单克隆或下载存储库,并在chrome扩展管理器中将“客户端”dir安装为未打包的扩展程序。驱动插件的代码位于app.js

使用iframeEval进行测试,错误通知有点小问题,但是嘿,eval有效。

@appsillers为了让您的插件在没有任何其他代码的情况下正常运行,您可以使用代码中的eval方法覆盖扩展程序window上的iframeEval方法。

答案 3 :(得分:1)

在我开始使用Angular.js Chrome应用程序后,我得到了同样的错误。作者没有提到Angular.js,但是如果有其他人遇到这个问题,你需要在你的网页上添加一个额外的指令,例如。

<html ng-app ng-csp>
...

这使角度处于CSP安全模式 https://docs.angularjs.org/api/ng/directive/ngCsp

答案 4 :(得分:1)

您可以使用:$ scope。来自angular的$ eval()。

答案 5 :(得分:-1)

以下是不起作用的示例,因为所有带代码的字符串都会在Chrome打包应用中被拒绝:

//To run some code from a string without `eval` just do this:
var code = new Function(yourCodeString);
code();