Like I wrote recently I am contracted at a German ISP at the moment to build a new Portal where one can put several different widgets on his or her personal web page. Similar to igoogle. My customer also wants to provide the possibility of own widgets to external developers, so to avoid security issues we will need to sandbox each of those widgets, but like we all know that can be a serious problem when it comes to the “evil unleashed monster” javascript. So in order to leash it inside a sandbox on a secure chain we came across google caja.
Caja is a project started by google a few years ago to provide a way to safely embed third party DHTML code on your own web page, as well as rich communication interfaces between the embedding page and the embedded applications. Normally to embed third party code one would use iframes, but with the capability of javascript to communicate between frames this can be a serious security breach.
At this point google caja provides you with a neat solution. First of all you will not need any iframes to embed third party code on your web page safely, the java based cajoler will provide you with html and javascript that is sand-boxed and secure to embed once it is cajoled. Don’t get me wrong, Java will only be needed to compile possibly hazardous code once, into the cajoled secure code one can use on his website. After that it is all done by the javascript libraries provided by the caja project.
But let me show you how the magic works.
First of all you will need to install some software:
- JDK 6
- The subversion version manager
- The Apache Ant build system.
- The JUnit testing framework. Just drop junit.jar</tt> in the $ANT_HOME/lib directory you set up for Ant.
Then create some folders for your caja project, for this I assume you will use Linux or Mac OS:
mkdir caja cd caja mkdir svn-changes cd svn-changes mkdir pristine cd pristine
After you have done this you will need to check out caja from the SVN – Repository:
svn checkout http://google-caja.googlecode.com/svn/trunk/ google-caj
Following the wiki of the caja project I assumed simply running “ant demos” on the console would provide me with some working demos. To make a long story of yelling and cursing short, no it didn`t. After long sessions of trail and error and a post on the discussion board where Jasvir Nagra pointed me in the right direction I found out why.
First of all several sources of the projects wiki as well as the sources compiled by ant will show you that you have to integrate the valija js the following way:
<script src="valija.co.js" type="text/javascript"></script>
;
What´s the problem with that ? There is simply no valija.co.js anywhere in the whole project !! But there is a “valija.out.js”. Simply use that file name and one of your setup problems will be gone. Yes right, one, there are several more traps I will show you.
Next thing you will notice, running firebug, is that cajoling source ,either via applet or via war (generated via ant playground), will not work but return a 500 Internal Server error.
Though I am a huge fan of software running out of the box I assumed that running either “ant playground” or “ant demos” ( / “ant testbed” for testbed only) would provide me with a running demo to play with. It didn´t. The reason why I found out after I had setup jetty Java server in debug mode, like Jasvir suggested. The log then showed me that some nu.validator.* library was missing in my jar file that was compiled by ant. Because I had been looking through all the project files and folders at my days of yelling and cursing I new where to find it. This Lib with all the needed classes is stored in “$cajaSourceFolder/third-party/java/htmlparser/src”. So there is a simply solution for that, simply copy the “nu” – folder to “$cajaSourceFolder/src” and run “ant testbed” or “ant playground” again.
Tada,… problem solved. Either you will get a working testbed by now or a working playground war.
To play at the playground I would suggest that you use jetty. The use of the server to my mind is quite easy. Simply download the src here, unpack it, switch to the folder and run:
$cajaSourceFolder: ant playground $jettyHomeDir/webapps:ln -s $cajaHomeDir/ant-war caja-playground cd .. $jettyHomeDir: java -jar start.jar etc/jetty-logging.xml etc/jetty.xml
By now you will have jetty running on port 8080 at localhost and caja-playground can be found at:
http://localhost:8080/caja-playground
But we don´t only want to play do we ?
So after playing around a little bit with either the playground or the testbed application I assume you would like to use what you have produced with either of those in a simple host page. Ten years of doing this job by now I thought the wiki might provide me with a simple solution for a host page that would be working right away. Hhmmm sorry nope. Wrong again. It does not.
Don`t get me wrong there is an example. It simply does not work with the code that you can download at the projects page. Simple as that. But this could not keep me from setting up one simple example, by braking down the playgrounds web page to the minimum needed to get it running.
Same procedure as every year Ms Sofia ? Same procedure as every year James. If nothing helps reverse engineering does it each and every time.
The nice guy I am I will save you some time and give you a step by step of what is needed to get the cajoled code running in a simple as can be host page.
First thing you will need to get the cajoled code running will be this inside the body tag of your page:
<!-- Load all needed scripts --> <script src="cajita.js" type="text/javascript"></script> <script src="unicode.js" type="text/javascript"></script> <script src="css-defs.js" type="text/javascript"></script> <script src="html4-defs.js" type="text/javascript"></script> <script src="html-sanitizer.js" type="text/javascript"></script> <script src="html-emitter.js" type="text/javascript"></script> <script src="setup-valija.js" type="text/javascript"></script> <script src="bridal.js" type="text/javascript"></script> <script src="domita.js" type="text/javascript"></script> <script src="valija.out.js" type="text/javascript"></script>
The next step will be to provide a method that will assign the containers for your cajoled widget:
<script type="text/javascript"> var imports = ___.copy(___.sharedImports); var gadgetRoot = ""; imports.outers = imports; function setGadgetContainer(containerId){ gadgetRoot = document.getElementById(containerId); imports.htmlEmitter___ = new HtmlEmitter(gadgetRoot); attachDocumentStub('-g___', { rewrite: function(){ return null; } }, imports, gadgetRoot); imports.$v = valijaMaker.CALL___(imports.outers); ___.getNewModuleHandler().setImports(imports); } </script>
This code simply initiates the base for caja and assigns a container for the widget. But lets go on with the html you will need for your page:
<div id="cajoled-output" class="g___"> {Here goes the html output of the cajoler}</div> <!-- Load widget 1 --> <script type="text/javascript">setGadgetContainer("cajoled-output");</script> <!-- The Cajoled javascript output put in an external file --> <script src="widgets/widget1.vo.js" type="text/javascript"></script>
You might have recognized the ” class=’g___’ ” that is also mentioned in the js method. This is nescessary for the html code rendered dynamicly by the caja libary to assign the content to the container.
This is it. If you followed the instructions you should have a working google caja playground, demo, webservice and jetty server by now as well as a working basic stand alone page witch will run you cajoled code.