Revision: 4478
Author:   jasvir
Date:     Fri May 20 13:58:12 2011
Log:      Use caja.js api to render the playground
http://codereview.appspot.com/4383048

Removes extraneous ES53 setup in the playground in favor of caja.js
* ensure es53-taming files get copied now that they're called opt rather than minified
* remove valija/cajita js files
* add the caja.js api
* remove taming.js
* fix up policy.js to use the new api
* rewire alert to use GWT alert rather than the browser native alert

[email protected]

http://code.google.com/p/google-caja/source/detail?r=4478

Deleted:
 /trunk/src/com/google/caja/demos/playground/taming.js
Modified:
 /trunk/src/com/google/caja/demos/playground/Playground.html
 /trunk/src/com/google/caja/demos/playground/client/policy.js
 /trunk/src/com/google/caja/demos/playground/client/ui/PlaygroundView.java

=======================================
--- /trunk/src/com/google/caja/demos/playground/taming.js Fri Mar 25 11:05:27 2011
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2009 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview
- * Tamed apis that are exposed to Caja playground.
- *
- * @author Jasvir Nagra ([email protected])
- * @requires document, window
- * @requires swfobject
- * @requires ___, attachDocumentStub, cajita
- * @provides caja___, tamings___
- */
-var tamings___ = tamings___ || [];
-var onReadyCallbacks___ = onReadyCallbacks___ || [];
-var caja___ = (function () {
-  var myPath = '';
-  var cajaDomSuffix = 'g___';
-  var grantAdditionalPowers = function(tamings___, ___, imports) {
-    for (var tamer = 0; tamer < tamings___.length; ++tamer) {
-      tamings___[tamer].call(___.USELESS, ___, imports);
-    }
-  }
-
-  var uriPolicy = {
-      rewrite: function (uri, uriEffect, loaderType, hints) {
-        if (!/^https?:/i.test(uri)) { return void 0; }
-        if (uriEffect === html4.ueffects.NEW_DOCUMENT ||
-            (uriEffect === html4.ueffects.SAME_DOCUMENT &&
-             loaderType === html4.ltypes.SANDBOXED)) {
-          return uri;
-        }
-        return null;
-      }
-  };
-
-  var id = "cajoled-output" + '-' + cajaDomSuffix;
-  function configureHTML(parent, html) {
-    var gadgetRoot = document.createElement('div');
-    gadgetRoot.id = id;
-    gadgetRoot.className = id;
-    gadgetRoot.innerHTML = html;
-    parent.appendChild(gadgetRoot);
-  }
-
-  function enableCajita(parent, policy, html, js) {
-    configureHTML(parent, html);
-    var gadgetRoot = document.getElementById(id);
-    var imports = ___.copy(___.sharedImports);
-    imports.outers = imports;
-    attachDocumentStub('-' + id, uriPolicy, imports, gadgetRoot);
-    imports.htmlEmitter___ = new HtmlEmitter(gadgetRoot, imports.document);
-    imports.$v = valijaMaker.CALL___(imports.outers);
-    ___.setLogFunc(function(x) { caja___.logFunc(x); })
-    ___.getNewModuleHandler().setImports(imports);
-    eval(policy);
-    grantAdditionalPowers(tamings___, ___, imports);
-    eval(js);
-  }
-
-  var cachedImports;
-  function reset() {
-    cachedImports = undefined;
-  }
-
-  function enableES53(parent, policy, html, js, callback, cache) {
-    configureHTML(parent, html);
-
-    var hiddenDiv = document.getElementById("es53frames");
-    var currentFrame = document.createElement('iframe');
-    currentFrame.src = myPath +
-      "es53.html?rnd=" + Math.floor(Math.random() * 10000);
-    currentFrame.id = "es53frame";
-
-    onReadyCallbacks___.push(function(api, childFrame) {
-        var result;
-        if (cache) {
-          if (!cachedImports) {
-            cachedImports = api.configureImports(
- document.getElementById(id), uriPolicy, policy, grantAdditionalPowers);
-          }
-          result = api.run(cachedImports, {js : js});
-        } else {
- result = api.initJS(document.getElementById(id), uriPolicy, policy,
-              {js : js}, grantAdditionalPowers);
-        }
-        if ('function' == typeof callback) {
-          callback(result);
-        }
-    });
-    hiddenDiv.appendChild(currentFrame);
-  }
-
-  function tearDownES53() {
-    try {
-      document.body.removeChild(document.getElementById("es53frame"));
-    } catch (e) {
-      // failure is an option
-    }
-  }
-
-  function setPath(path) {
-    myPath = path;
-  }
-
-  function enable(es53, parent, policy, html, js, callback, cache) {
-    tearDownES53();
-    if (es53) {
-      enableES53(parent, policy, html, js, callback, cache);
-    } else {
-      enableCajita(parent, policy, html, js, callback, cache);
-    }
-  }
-
-  function onReady(api, frameElement) {
-    var callback;
-    for (callback = 0; callback < onReadyCallbacks___.length; callback++) {
-      onReadyCallbacks___[callback](api, frameElement);
-    }
-    onReadyCallbacks___ = [];
-  }
-
-  return {
-    reset: reset,
-    enable: enable,
-    onReady: onReady,
-    setPath: setPath,
-    logFunc: function noOp() {}
-  }
-})();
=======================================
--- /trunk/src/com/google/caja/demos/playground/Playground.html Wed Mar 16 15:02:01 2011 +++ /trunk/src/com/google/caja/demos/playground/Playground.html Fri May 20 13:58:12 2011
@@ -31,25 +31,13 @@
     <link href="prettify.css" type="text/css" rel="stylesheet" />
   </head>
   <body>
+    <script type="text/javascript" src="caja.js"></script>
<!-- Load scripts in body so that document.body is available in IE 6 -->
-    <script type="text/javascript" src="json_sans_eval.js"></script>
-    <script type="text/javascript" src="cajita.js"></script>
-    <script type="text/javascript" src="cajita-debugmode.js"></script>
-    <script type="text/javascript" src="unicode.js"></script>
-    <script type="text/javascript" src="css-defs.js"></script>
     <script type="text/javascript" src="html4-defs.js"></script>
-    <script type="text/javascript" src="html-sanitizer.js"></script>
-    <script type="text/javascript" src="html-emitter.js"></script>
-    <script type="text/javascript" src="setup-valija.js"></script>
-    <script type="text/javascript" src="bridal.js"></script>
-    <script type="text/javascript" src="cssparser.js"></script>
-    <script type="text/javascript" src="domita.js"></script>
     <script type="text/javascript" src="prettify.js"></script>
     <script type="text/javascript" src="lang-css.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js";></script>
     <script type="text/javascript" src="testbed.js"></script>
-    <script type="text/javascript" src="taming.js"></script>
-    <script type="text/javascript" src="valija.out.js"></script>
     <script type="text/javascript" src="js/codemirror.js"></script>
<script type="text/javascript" src="playground/playground.nocache.js"></script>

=======================================
--- /trunk/src/com/google/caja/demos/playground/client/policy.js Sun Jan 16 11:33:18 2011 +++ /trunk/src/com/google/caja/demos/playground/client/policy.js Fri May 20 13:58:12 2011
@@ -1,220 +1,20 @@
 // Playground policy
-//  - exposes flash
-//  - exposes alert
-tamings___ = [];
-/**
- * Simple flash taming
- *   - exposes a taming of the swfobject API
- *   - ensures version of flash > 9 (defaults to v10)
- *   - adds parameters to limit network and prevent script access
- */
-
-tamings___.push(function tameSimpleFlash(___, imports) {
-  if (!parent.___) {
-    imports.outers.swfobject = {
- embedSWF: function() { console.log("Flash is not supported on ES3"); }
-    };
-    ___.grantRead(imports.outers, 'swfobject');
-    ___.grantFunc(imports.outers.swfobject, 'embedSWF');
-
-    return;
-  }
-  // Get a frame with no Caja in it.
-  var ifr = document.createElement('iframe');
-  document.body.appendChild(ifr);
-  var O = ifr.contentWindow.Object;
-  var A = ifr.contentWindow.Array;
-  document.body.removeChild(ifr);
-
-  ___.flash = {
-    /**
-     * Converts cajoled objects to objects with no special properties.
-     * Enumerable guest properties must not be recursive.
-     */
-    untame: function untame(obj) {
-        var result, i;
-        var t = typeof obj;
-        if (t === 'object') {
-          if (Array.isArray(obj)) {
-            result = new A();
-          } else {
-            result = new O();
-          }
-          var keys = ___.allEnumKeys(obj), len = keys.length;
-          for (i = 0; i < len; ++i) {
-            result[keys[i]] = untame(obj[keys[i]]);
-          }
-        } else {
-          result = obj;
-        }
-        return result;
-      },
-
-    /**
-     * Converts a valija object (since the host page is valija)
- * generated by flash (so everything's writable/enumerable/configurable)
-     * into an ES5/3 object.
-     */
-    tame: function tame(obj) {
-        var result, i;
-        var t = typeof obj;
-        if (t === 'object') {
-          if (Array.isArray(obj)) {
-            result = [];
-          } else {
-            result = {};
-          }
-          for (i in obj) {
-            if (/__$/.test(i)) { continue; }
-            var value = tame(obj[i]);
-            if (typeof i === 'number' || ('' + (+i)) === i) {
-              result[i] = value;
-            } else {
-              result.DefineOwnProperty___(i, {
-                  value: value,
-                  writable: true,
-                  configurable: true,
-                  enumerable:true
-                });
-            }
-          }
-        } else {
-          result = obj;
-        }
-        return result;
-      },
-
-    cajaContextTable: []
-  };
-
-  // Modify the host page wunderbar
-  parent.___.flash = {
-      onLoaderInit: function(context) {
-          // ___.log('onLoaderInit:' + context)
-        },
-      onLoaderError: function(context) {
-          // ___.log('onLoaderError: ' + context);
-        },
-      onAddCallback: function(context, fnName) {
-          // ___.log('onAddCallback: ' + context + ', ' + fnName);
-          // Mark the function as callable.
-          ___.flash.cajaContextTable[context][fnName+'_m___'] = 1;
-        },
-      onCall: function(context, fnName, args) {
-          // _.log('onCall: ' + context + ', ' + fnName + ', ' + args);
-          var fn = imports[fnName];
-          if (___.isFunction(fn)) {
-            var tameargs = ___.flash.tame(args);
-            var result = fn.f___(___.USELESS, tameargs);
-            result = ___.flash.untame(result);
-            return result;
-          }
-          return void 0;
-        },
-      onNavigateToURL: function(context, url) {
-          // ___.log('onNavigateToURL: ' + context + ', ' + url);
-        }
-    };
-
-  imports.outers.swfobject = {};
-  imports.outers.swfobject.embedSWF = function(swfUrl, id, width, height,
-      version, expressInstall, flashvars, params, attributes, cb) {
-    var cajaContext = ___.flash.cajaContextTable.length;
-    var tameSwfUrl = 'flashbridge.swf' +
-        '?__CAJA_cajaContext=' + cajaContext +
-        '&__CAJA_src=' + swfUrl;
-    ___.flash.cajaContextTable[cajaContext] = {};
-    var tameId = imports.outers.document.getElementById(id).node___.id;
-    var tameWidth = +width;
-    var tameHeight = +height;
-    // Default to 10.0 if unspecified or specified < 9
-    // else use whatever version >9 the user suggests
-    var tameVersion = version || "10.0";
-    if (!/^9|([1-9][0-9])\./.test(tameVersion)) {
-      tameVersion = "10.0";
-    }
-    var tameExpressInstall = false;
-    var tameAttr = null;
-    var tameParams = {allowScriptAccess: 'always', allowNetworking: 'all'};
-
-    var result = swfobject.embedSWF(
-        tameSwfUrl,
-        tameId,
-        tameWidth,
-        tameHeight,
-        tameVersion,
-        tameExpressInstall,
-        flashvars,
-        tameParams,
-        tameAttr,
-        ___.isFunction(cb) ?
-            function(e) {
-              /**
-               * Properties of this event object are:
- * success, Boolean to indicate whether the embedding of a SWF
-               *    was success or not
- * id, String indicating the ID used in swfobject.registerObject
-               * ref, HTML object element reference (returns undefined when
-               *    success=false)
-               **/
-              var ref = ___.flash.cajaContextTable[cajaContext] = e.ref;
-              e = {
-                  success: e.success,
-                  id: e.id,
-                  ref:{
-                      // ref is an object on which you can only invoke
-                      // methods.
-                      m___: function (methodName, args) {
-                          var feralargs = ___.flash.untame(args);
-                          if (ref[methodName+'_m___']) {
-                            return ___.flash.tame(
-                                ref[methodName].apply(ref, feralargs));
-                          }
-                          return void 0;
-                        }
-                    }
-                };
-              ___.grantRead(e, 'success');
-              ___.grantRead(e, 'id');
-              ___.grantRead(e, 'ref');
-              return cb.f___(___.USELESS, [e]);
-            } :
-            null);
-  };
-  ___.grantRead(imports.outers, 'swfobject');
-  ___.grantFunc(imports.outers.swfobject, 'embedSWF');
-});
-
-/**
- * Throttled alert taming
- *   - exposes a taming of the alert function
- *   - ensures that after 10 alerts the user has the option of redirecting
- *     remaining calls to alert to cajita.log instead
- */
-tamings___.push(function tameAlert(___, imports) {
-  imports.outers.alert = (function() {
-    var remainingAlerts = 10;
-    function tameAlert(msg) {
-      if (remainingAlerts > 0) {
-        remainingAlerts--;
-        alert("Untrusted gadget says: " + msg);
-      } else if (remainingAlerts == 0) {
-        remainingAlerts = confirm("Ignore remaining alerts?") ? -1 : 10;
+(function() {
+  var tamings___ = [];
+  window.___ = {};
+
+  /**
+   * Expose a "recordResult" function expected by sunspider benchmarks
+   */
+  tamings___.push(function tameRecordResult(frameGroup, imports) {
+    function recordResult(number) {
+      if (!!console && !!console.log) {
+        console.log("Time taken: " + number);
       }
     };
-    return tameAlert;
-  })();
-  ___.grantFunc(imports.outers, 'alert');
-});
-
-/**
- * Expose a "record" function used by sunspider benchmarks
- */
-tamings___.push(function tameRecord(___, imports) {
-  imports.outers.recordResult = function recordResult(number) {
-    if (!!console && !!console.log) {
-      console.log("Time taken: " + number);
-    }
-  };
-  ___.grantFunc(imports.outers, 'recordResult');
-});
+    frameGroup.markFunction(recordResult);
+    imports.parent = frameGroup.tame({ recordResult: recordResult });
+  });
+
+  return tamings___;
+})();
=======================================
--- /trunk/src/com/google/caja/demos/playground/client/ui/PlaygroundView.java Wed May 18 10:18:54 2011 +++ /trunk/src/com/google/caja/demos/playground/client/ui/PlaygroundView.java Fri May 20 13:58:12 2011
@@ -20,22 +20,24 @@
 import com.google.caja.demos.playground.client.Playground;
 import com.google.caja.demos.playground.client.PlaygroundResource;
 import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.ScriptElement;
+import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.FocusEvent;
 import com.google.gwt.event.dom.client.FocusHandler;
 import com.google.gwt.event.logical.shared.SelectionEvent;
 import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.DialogBox;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
 import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
 import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.TextArea;
 import com.google.gwt.user.client.ui.TreeItem;

 /**
@@ -233,13 +235,6 @@
   }
   */

-  private native void setupNativeRuntimeMessageBridge() /*-{
-    var that = this;
-    $wnd.caja___.logFunc = function logFunc (msg) {
- [email protected]::addRuntimeMessage(Ljava/lang/String;)(msg);
-    };
-  }-*/;
-
   private native void setupNativeSelectLineBridge() /*-{
     var that = this;
     $wnd.selectLine = function (uri, start, sOffset, end, eOffset) {
@@ -250,7 +245,6 @@
   }-*/;

   private void initEditor() {
-    setupNativeRuntimeMessageBridge();
     setupNativeSelectLineBridge();
     selectTab(Tabs.SOURCE);
   }
@@ -335,26 +329,18 @@
       playgroundUI.cajoledSource.setText("There were cajoling errors");
       return;
     }
-    playgroundUI.cajoledSource.setHTML(prettyPrint(html) +
-      "&lt;script&gt;" + prettyPrint(js) + "&lt;/script&gt;");
+    playgroundUI.cajoledSource.setHTML(prettyPrint(html, "html") +
+      "&lt;script&gt;" + prettyPrint(js, "lang-js") + "&lt;/script&gt;");
   }

   public void setLoading(boolean isLoading) {
     playgroundUI.loadingLabel.setVisible(isLoading);
   }

-  private native String prettyPrint(String result) /*-{
-    return $wnd.prettyPrintOne($wnd.indentAndWrapCode(result));
+  private native String prettyPrint(String result, String lang) /*-{
+    return $wnd.prettyPrintOne($wnd.indentAndWrapCode(result), lang);
   }-*/;

-  private ScriptElement scriptOf(String text) {
-    Element el = DOM.createElement("script");
-    ScriptElement script = ScriptElement.as(el);
-    script.setType("text/javascript");
-    script.setInnerText(text);
-    return script;
-  }
-
   public void setRenderedResult(String policy, String html, String js) {
     if (html == null && js == null) {
       playgroundUI.renderResult.setText("There were cajoling errors");
@@ -368,28 +354,95 @@
     setRenderedResultBridge(true /* es53 */,
         playgroundUI.renderPanel.getElement(),
         policy, html != null ? html : "", js != null ? js : "");
-
-    playgroundUI.renderResult.setText(getRenderResult());
+  }
+
+  private void setRenderedResult(String result) {
+    playgroundUI.renderResult.setText(result);
   }

+  private void alert(String msg) {
+    final DialogBox alertBox = new DialogBox();
+    alertBox.setGlassEnabled(true);
+    alertBox.setText("Cajoled gadget says");
+    DockLayoutPanel dock = new DockLayoutPanel(Unit.PX);
+    dock.add(new ScrollPanel(new Label(msg)));
+    dock.addSouth(new Button("Ok", new ClickHandler() {
+      @Override
+      public void onClick(ClickEvent arg0) {
+        alertBox.hide();
+      }
+    }), 20);
+    dock.setSize("200px", "200px");
+    alertBox.add(dock);
+    alertBox.center();
+    alertBox.show();
+  }
+
   private native void setRenderedResultBridge(boolean es53,
       Element div, String policy, String html, String js) /*-{
-    $wnd.caja___.enable(es53, div, policy, html, js);
+    var that = this;
+    $wnd.caja.configure({
+      cajaServer: 'http://localhost:8080/',
+    }, function (frameGroup) {
+      var extraImports = {};
+      try {
+        var tamings___ = eval(policy);
+      } catch (e) {
+ [email protected]::addRuntimeMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)
+            (e, "evaluating policy");
+      }
+      for (var i=0; i < tamings___.length; i++) {
+        try {
+          tamings___[i].call(undefined, frameGroup, extraImports);
+        } catch (e) {
+ [email protected]::addRuntimeMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)
+              (e, "evaluating " + i + "th policy function");
+        }
+      }
+
+      extraImports.onerror = frameGroup.tame(frameGroup.markFunction(
+        function (message, source, lineNum) {
+ [email protected]::addRuntimeMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)
+              (message, source, lineNum);
+        }));
+      extraImports.alert = frameGroup.tame(frameGroup.markFunction(
+        function (message) {
+ [email protected]::alert(Ljava/lang/String;)
+              (message);
+        }));
+
+      frameGroup.makeES5Frame(div, {
+          rewrite: function (uri, uriEffect, loaderType, hints) {
+            if (!/^https?:/i.test(uri)) { return void 0; }
+            if (uriEffect === $wnd.html4.ueffects.NEW_DOCUMENT ||
+                (uriEffect === $wnd.html4.ueffects.SAME_DOCUMENT &&
+                 loaderType === $wnd.html4.ltypes.SANDBOXED)) {
+              return uri;
+            }
+            return null;
+          }
+        }, function (frame) {
+        frame.contentCajoled('http://localhost:8080/',
+           js, html).run(extraImports, function (result) {
+ [email protected]::setRenderedResult(Ljava/lang/String;)
+                (result)
+           });
+      });
+    });
   }-*/;

-  private native String getRenderResult() /*-{
-    return "" + $wnd.___.getNewModuleHandler().getLastValue();
-  }-*/;
-
   public void addCompileMessage(String item) {
     // Rendered using HTMLSnippetProducer serverside
     HTML i = new HTML(item);
     playgroundUI.compileMessages.add(i);
   }

-  public void addRuntimeMessage(String item) {
+ public void addRuntimeMessage(String message, String source, String lineNum) {
     // Unsafe as HTML
-    Label i = new Label(item);
+    Label i = new Label(
+        "Uncaught script error: '" + message +
+        "' in source: '" + source +
+        "' at line: " + lineNum + "\n");
     playgroundUI.runtimeMessages.add(i);
   }

Reply via email to