Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not make GWT application work as Chrome packaged app, probably due to CSP

Keep getting CSP errors: "Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'"

The problem is probably due to HTML files generated by GWT which contain inline JS.

UPD: Changing to manifest version 1 helped, but this is a temporary workaroud, as Chrome 21 complains that it will no longer be supported.

UPD2: <add-linker name="xsiframe" /> does not help either

like image 671
Alexey Timanovsky Avatar asked Aug 25 '12 15:08

Alexey Timanovsky


3 Answers

GWT 2.5.1 has finally fixed this problem. The release notes documenting this are here:

https://developers.google.com/web-toolkit/release-notes#Release_Notes_2_5_1

and they state that:

"Apps built with DirectInstallLinker should work in a page where inline scripts are forbidden (e.g. a Chrome extension)"

This means that it is now possible to use DirectInstallLinker to link your Chrome packaged app in a manner that satisfies the new security requirements of manifest version 2 regarding inline scripts. That is, by using DirectInstallLinker to link your app with GWT 2.5.1 selected as your GWT version, GWT will not place any script elements inline in its generated Javascript, and thus the new manifest version 2 requirement that there be no inline scripts will not be violated.

I have found that SingleScriptLinker also seems to work for my own app; however, Issue 7685 warns against using the SingleScriptLinker because "This generates a $doc.write line which is forbidden in packaged apps." I am using DirectInstallLinker myself.

Here is the Javadoc for DirectInstallLinker:

http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/core/linker/DirectInstallLinker.html

To use this linker, you can include the following in your *.gwt.xml file:

<define-linker name="dil" class="com.google.gwt.core.linker.DirectInstallLinker"/>
<add-linker name="dil" />

(dil can be replaced by anything you choose, so long as there are no dashes or other illegal characters).

You will need to select GWT 2.5.1 as your version of GWT. If you're using an older version of GWT in an out-of-date version of Eclipse such as Ganymede (as I was), you'll have to upgrade to at least Helios and then import your project to your new Eclipse environment. The archive URLs for the Google Plugin for Eclipse that can be used for the latest three Eclipse versions can be found here:

https://developers.google.com/eclipse/docs/download

With the above in place, you should be able to set

"manifest_version": 2

in your manifest.json file and not experience any errors due to GWT-generated inline Javascript. This should allow your Chrome Web app to be acceptable to the Chrome Web Store (which now requires manifest version 2 for any new apps or for updates to present apps), so long as there are no other issues.

like image 186
Carl Avatar answered Oct 11 '22 01:10

Carl


EDIT: new GWT bug reported: http://code.google.com/p/google-web-toolkit/issues/detail?id=7685, see also http://gwt-code-reviews.appspot.com/1838803/ which is related to this bug

In other words, it looks like, when fixed, you'll simply have to use the DirectInstallLinker (<add-linker name='direct_install'/>).

In the mean time, IIUC, you'd have to extend DirectInstallLinker and:

  • override getJsInstallLocation to return a copy a installLocaltionIframe.js without the $wnd part
  • override getModulePrefix to prepend var $wnd = $wnd || window.parent; to what's generated by super.getModulePrefix

I don't know CSP enough to give a complete answer, but the xsiframe linker is "customizable": create a class that extends com.google.gwt.core.linker.CrossSiteIframeLinker and overrides the appropriate methods, then use with a <define-linker> and <add-linker> in your *.gwt.xml.

For instance, getJsInstallLocation defaults to com/google/gwt/core/ext/linker/impl/installLocationIframe.js but there's a com/google/gwt/core/ext/linker/impl/installLocationMainWindows.js alternate implementation.

Similarly (and probably more importantly), getJsInstallScript defaults to com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js but there's also a com/google/gwt/core/ext/linker/impl/installScriptDirect.js alternate implementation.

See http://code.google.com/p/google-web-toolkit/source/browse/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java#204, http://code.google.com/p/google-web-toolkit/source/browse/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/ and http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/core/Core.gwt.xml

like image 39
Thomas Broyer Avatar answered Oct 11 '22 03:10

Thomas Broyer


Thanks to Thomas Broyer's advice. I created this GWT Linker. Now my GWT application runs perfectly as an Chrome Application (Tested on Chrome 32 and GWT 2.5.1).

public class CSPCompatibleLinker extends DirectInstallLinker {

@Override
protected String getJsInstallLocation(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/installLocationMainWindow.js";
} 

}

Dont forget to declare the Linker into your*.gwt.xml file:

<define-linker name="csp" class="com.sfeir.linker.CSPCompatibleLinker"/>
<add-linker name="csp" />
like image 37
Mohamed Abdennebi Avatar answered Oct 11 '22 01:10

Mohamed Abdennebi