Success using Chrome content script extensions with uncompiled code?

273 views
Skip to first unread message

Andrew Mattie

unread,
Dec 12, 2012, 2:36:48 AM12/12/12
to closure-lib...@googlegroups.com
Has anyone had any success with using uncompiled Closure Library -based content scripts in a Chrome extension? I spent the better part of today trying to get it working to no avail.

The problem I found has to do with the way Closure loads dependencies via goog.require. Since the goog.writeScriptTag_ method uses document.write, and since the content scripts are loaded after the document is finished, an alternative is needed. That alternative might normally involve implementing window.CLOSURE_IMPORT_SCRIPT with something that creates script tags and appends them to document.body or whatever, but that doesn't work because the goog.global (this / window) object exposed when base.js is evaluated isn't the same as the initial global obj since it's loaded on the chrome-extensions: scheme.

I tried all sorts of ideas involving background script loading and message passing, overriding CLOSURE_NO_DEPS, and other ideas. There's a ton of detail I'm initially leaving out here for brevity sake.

Has anyone been able to make this work? Any public examples?

David Levin

unread,
Dec 12, 2012, 3:04:38 AM12/12/12
to closure-lib...@googlegroups.com
Wouldn't document.write also have the problem that the content scripts run in an "isolated world" so any scripts injected in this manner wouldn't be accessible to the content script?

dave

PS With respect to using closure in a Chrome extension, you should probably override goog.json.parse (e.g. goog.json.parse = window.JSON.parse) because goog.json.parse uses eval which doesn't work with manifest v2.




Andrew Mattie

unread,
Dec 12, 2012, 2:33:04 PM12/12/12
to closure-lib...@googlegroups.com
Yeah, there are a few issues. I spent some more time this morning on it and am giving up trying to run uncompiled code. Bummer.

In order for this to work properly, I'm convinced Chrome needs to add an API that allows either the content script or background script to inject new scripts into the running content script's environment. I don't believe there's any other way to accomplish that goal since scripts appended to the page from the chrome-extension: protocol run in an altogether different environment than any content scripts and the background page that doesn't have access to the content script's environment.

I had hopes that chrome.tabs.executeScript could fix the problem, but this bug <http://code.google.com/p/chromium/issues/detail?id=30756> seems to prevent that. I can't even use message passing since I can't set up CLOSURE_IMPORT_SCRIPT in the environment that base.js is evaluated in. I very well could be missing something, but I don't see any workaround at this time.

Thanks for the tip on goog.json and eval. I had been wondering about such compatibility issues like that. Makes sense.

Andrew

David Levin

unread,
Dec 12, 2012, 3:05:54 PM12/12/12
to closure-lib...@googlegroups.com
fwiw, I don't work on google closure. I'm simply a user of it in an extension.

There is a Google group for extension development questions that may be able to help you more: https://groups.google.com/a/chromium.org/forum/?fromgroups#!aboutgroup/chromium-extensions (It even suggests using Stack Overflow -- see the link).

dave

mesteiral

unread,
Dec 13, 2012, 11:42:36 AM12/13/12
to closure-lib...@googlegroups.com
goog.json.parse and other functions requiring eval() can be made to work in chrome extensions without modification (in content scripts or otherwise) with manifest v2 by tweaking the content security policy:

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

This is how I debug content scripts (refreshing on page reload) in conjuction with Plovr, albeit admittedly not uncompiled. I use SIMPLE_OPTIMIZATIONS, so apart from this manifest.json tweaking my advice won't help.


For information's sake: Message-passing is used to ask the background script to load the script pretty-printed and compiled with simple optimizations via XMLHttpRequest, and pass it back to the content script, which then eval()s it in the context it's naturally assigned. I based my solution off Michael Bolin's chrome-extension-template[1], which uses short-lived messages (I use chrome.extension.onMessage rather than chrome.extension.onRequest).

Reply all
Reply to author
Forward
0 new messages