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) +
- "<script>" + prettyPrint(js) + "</script>");
+ playgroundUI.cajoledSource.setHTML(prettyPrint(html, "html") +
+ "<script>" + prettyPrint(js, "lang-js") + "</script>");
}
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);
}