17

If I use underscore.js's _.template() from inside a Google Chrome extension I get the following error in the console:

Uncaught Error: Code generation from strings disallowed for this context

Is there any way to get past this error?

user3335966
  • 2,673
  • 4
  • 30
  • 33
djmccormick
  • 463
  • 4
  • 11

6 Answers6

7

Many thanks to the Chromium list contributor who pointed out that to create a Function object in the way underscore is doing it requires the manifest.json option for content_security_policy to include 'unsafe-eval'.

As an example, your manifest.json could be

{
  "manifest_version": 2,
  ...
  "content_security_policy": "script-src 'self' 'unsafe-eval'",
  ...
}

and then the underscore behavior would work because this policy allows it. For more information on the format see the Chrome documentation on this option here.

Chris Hunt
  • 3,840
  • 3
  • 30
  • 46
djmccormick
  • 463
  • 4
  • 11
  • 1
    Link is dead and I don't know how to add 'unsafe-eval', chromium keeps rejecting everything I try. Can you add an example to your answer? Thanks. – Jorge Vargas Apr 13 '12 at 06:29
  • 2
    Here's an example of adding unsafe-eval to the manifest.json: https://github.com/djmccormick/linkswapp-chrome/blob/master/manifest.json – djmccormick Apr 13 '12 at 13:54
  • 3
    Thanks man! I also found out that on chrome extensions v2 unsafe-eval currently doesn't work. There's a discussion going on about accepting unsafe-eval or keeping it disabled here (current status of issue is wontfix): http://code.google.com/p/chromium/issues/detail?id=107538 – Jorge Vargas Apr 24 '12 at 16:22
  • *Could not load extension from '/home/Envs/todolist'. Invalid value for 'content_security_policy'.* I have been getting the above error. – user993563 Jun 22 '12 at 13:07
  • I've created a super basic example of how this is done: https://github.com/djmccormick/content-security-policy-test – djmccormick Jun 22 '12 at 17:00
  • This will not work for manifest version 2. See @AndrewBrown's answer. – djmccormick Jul 13 '12 at 20:01
5

Unfortunately I don't think you can use underscore.js's _.template() from within a chrome extension...at least with the new manifest.json version 2. The same holds true for trying to use the jQuery Template plugin.

From the Google Chrome Extension's Content Security Policy page:

There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes unsafe-inline will have no effect. This is intentional.

I am going to look at other templating engines that will hopefully not use the new Function object.

Andrew Brown
  • 176
  • 3
  • 8
  • The inline script restriction only applies to JS that appears inside of an HTML page (i.e. 'inline' JS). You can get around the specific thing you're quoting above by putting JS that was previously inline into its own .js file and loading it via a script tag or through some other mechanism. To say it another way, the thing you're quoting doesn't seem to apply to the unsafe eval problem, specifically. – jefflunt Feb 20 '14 at 15:04
4

I use Underscore.js because I want Backbone.js for my Chrome extension, I just changed the Template engine to Mustache ~ if you have the same reason, you can also use Underscore.js for Backbone, just do not use _.template() function.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
wang
  • 41
  • 1
0

Manifest v2 limitations, as said above, forbid to use Eval, new Function, and inline scripts - even when playing with the Content Security Policy: there's no way to relax this security policy in v2 extensions.

Most template libraries use, at some point or another, evals. One solution is to rewrite your extensions so that all logic resides in a javascript, and nothing in a template; a solution such as google jstemplate should in this case be usable.

There's, though, the option to do Eval and new Function inside a sandboxed iframe, for instance with the following lines in the manifest:

"sandbox": {
    "pages": [
      "page1.html",
      "directory/page2.html"
    ]
},

A sandboxed page will not have access to extension or app APIs, or direct access to non-sandboxed pages (it may communicate with them via postMessage()). You can further restrict the sandbox rights with a specific CSP

There's now a full example from the Google Chrome team on the github eval in iframe on how to circumvent the problem by communicating with a sandboxed iframe, as well as a short analytics tutorial

Hopefully some library will show up using this mechanism to provide full compatibility with standard templates usage, though I'd advise removing as much logic from the templates as possible for performance reasons...

Thanks to Google, there's a lot of extension rewriting in the lineup :(

Stefano
  • 18,083
  • 13
  • 64
  • 79
0

Google just released a new document discussing the solution for this problem ?

http://code.google.com/chrome/extensions/trunk/sandboxingEval.html

Shai Reznik - HiRez.io
  • 8,748
  • 2
  • 33
  • 33
0

You can write your own template mini-engine using jQuery's $('<element .../>') construction.

The clean way:

function myElement(text) {
  var d = $('<div class="abc"/>');
  d.text(text);
  return d;
}

myElement('my text').appendTo(domParent);

The dirty way:

var yourTemplate = '<div>${somevar}</div>';

function instTemplate(tmpl, text) {
  return $(tmpl.replace(/\$\{somevar\}/g, text));
}

instTemplate(yourTemplate, 'your text').appendTo(domParent);

E.g. it's pretty quick to rewrite simple jquery.tmpl templates using the dirty method, if you know that the replacement data is not harmful, etc.

youurayy
  • 1,635
  • 1
  • 18
  • 11