Author: doll
Date: Fri Jan 11 18:08:32 2008
New Revision: 611350

URL: http://svn.apache.org/viewvc?rev=611350&view=rev
Log:
Improved more of the opensocial - caja integration code. Gadgets cajoled with 
the latest caja server should now work with the excpetion of 2 bugs on their 
side. 
This change includes html sanitization as well as a proper definition of 
emitHtml.



Added:
    incubator/shindig/trunk/features/caja/html-sanitizer.js
Modified:
    incubator/shindig/trunk/features/caja/feature.xml
    incubator/shindig/trunk/features/opensocial-reference/container.js

Modified: incubator/shindig/trunk/features/caja/feature.xml
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/caja/feature.xml?rev=611350&r1=611349&r2=611350&view=diff
==============================================================================
--- incubator/shindig/trunk/features/caja/feature.xml (original)
+++ incubator/shindig/trunk/features/caja/feature.xml Fri Jan 11 18:08:32 2008
@@ -23,6 +23,7 @@
   <name>caja</name>
   <gadget>
     <script src="caja.js"></script>
+    <script src="html-sanitizer.js"></script>
     <!--Be default permissive.js should not be included.
         Including this file turns off all caja security rules. -->
     <!--<script src="permissive.js"></script>-->

Added: incubator/shindig/trunk/features/caja/html-sanitizer.js
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/caja/html-sanitizer.js?rev=611350&view=auto
==============================================================================
--- incubator/shindig/trunk/features/caja/html-sanitizer.js (added)
+++ incubator/shindig/trunk/features/caja/html-sanitizer.js Fri Jan 11 18:08:32 
2008
@@ -0,0 +1,420 @@
+// Copyright (C) 2006 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.
+
+// [EMAIL PROTECTED]
+
+/**
+ * Strips unsafe tags and attributes from html.
+ * @param {String} html to sanitize
+ * @param {Function} opt_urlXform : String -> String -- a transform to apply to
+ *   url attribute values.
+ * @param {Function} opt_nmTokenXform : String -> String -- a transform to 
apply
+ *   to name attribute values.
+ * @return {String} html
+ */
+var html_sanitize = (function () {
+
+  // hide all the whitelists and other state so they can't be interfered with
+
+  /** token definitions. */
+  var TOK_ENTITY = /^&(?:\#[0-9]+|\#x[0-9a-f]+|\w+);/i;
+  var TOK_COMMENT = /^<!--[\s\S]*?-->/;
+  var TOK_TAG_BEGIN = /^<\/?[a-z][a-z0-9]*/i;
+  var TOK_TAG_END = /^\/?>/;
+  var TOK_ATTRIB = /^\w+(\s*=\s*(?:\"[^\"]*\"|\'[^\']*\'|[^>\"\'\s]*))?/;
+  var TOK_SPACE = /^\s+/;
+  var TOK_OTHER = /^[^&<]+/;
+  var TOK_CRUFT = /^[<&]/;
+  var TOK_IGNORABLE_CRUFT = /^[^\w\s>]+/;
+
+  /** the token definitions used when we are outside a tag. */
+  var TOKS_NOTTAG = [
+      TOK_ENTITY,
+      TOK_COMMENT,
+      TOK_TAG_BEGIN,
+      TOK_OTHER,
+      TOK_CRUFT
+  ];
+  /** token definitions used inside a tag. */
+  var TOKS_INTAG = [
+      TOK_SPACE,
+      TOK_ATTRIB,
+      TOK_TAG_END,
+      TOK_IGNORABLE_CRUFT
+  ];
+
+  /**
+   * split html into tokens using the regexps above.
+   * This also does some normalization of tokens, escaping specials that don't
+   * appear to be part of a larger token.
+   */
+  var lex = function (html) {
+    var tokens = [];
+    var inTag = false; // 0 outside tag, 1 inside tag
+    while (html) {
+      var m = null;
+      var tok = null;
+      if (!inTag) {
+        for (var i = 0; i < TOKS_NOTTAG.length; ++i) {
+          m = html.match(TOKS_NOTTAG[i]);
+          if (m) {
+            tok = TOKS_NOTTAG[i];
+            break;
+          }
+        }
+        if (tok === TOK_TAG_BEGIN) { inTag = true; }
+      } else {
+        for (var i = 0; i < TOKS_INTAG.length; ++i) {
+          m = html.match(TOKS_INTAG[i]);
+          if (m) {
+            tok = TOKS_INTAG[i];
+            break;
+          }
+        }
+        if (tok === TOK_TAG_END) { inTag = false; }
+      }
+      var tokstr = m[0];
+      html = html.substring(tokstr.length);
+      if (tok === TOK_CRUFT) {
+        tokstr = tokstr == '<' ? '&lt;' : '&amp;';
+      } else if (tok === TOK_OTHER) {
+        tokstr = tokstr.replace(/>/g, '&gt;');
+      } else if (tok == TOK_SPACE) {
+        tokstr = ' ';
+      } else if (tok === TOK_ATTRIB) {
+        tokstr = tokstr.replace(/^(\w+)\s*=\s*/, '$1=');
+      }
+      if (tok !== TOK_IGNORABLE_CRUFT && tok != TOK_COMMENT) {
+        tokens.push(tokstr, tok);
+      }
+    }
+    return tokens;
+  };
+
+  // whitelists of elements and attributes
+
+  /** element flags. */
+  var OPTIONAL_ENDTAG = 1,
+          BREAKS_FLOW = 2,
+                EMPTY = 4,
+               UNSAFE = 8;
+
+  /** attribute flags */
+  var SCRIPT_TYPE = 1,
+       STYLE_TYPE = 2,
+     NMTOKEN_TYPE = 4,
+         URI_TYPE = 8;
+
+  /**
+   * All the HTML4 elements.
+   * U - unsafe, E - empty, B - breaks flow, O - optional endtag
+   */
+  var ELEMENTS = {
+    A          : 0,
+    ABBR       : 0,
+    ACRONYM    : 0,
+    ADDRESS    : 0,
+    APPLET     : UNSAFE,
+    AREA       : EMPTY,
+    B          : 0,
+    BASE       : UNSAFE|EMPTY,
+    BASEFONT   : UNSAFE|EMPTY,
+    BDO        : 0,
+    BIG        : 0,
+    BLOCKQUOTE : BREAKS_FLOW,
+    BODY       : UNSAFE|OPTIONAL_ENDTAG,
+    BR         : EMPTY|BREAKS_FLOW,
+    BUTTON     : 0,
+    CAPTION    : 0,
+    CENTER     : BREAKS_FLOW,
+    CITE       : 0,
+    CODE       : 0,
+    COL        : EMPTY,
+    COLGROUP   : OPTIONAL_ENDTAG,
+    DD         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    DEL        : 0,
+    DFN        : 0,
+    DIR        : BREAKS_FLOW,
+    DIV        : BREAKS_FLOW,
+    DL         : BREAKS_FLOW,
+    DT         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    EM         : 0,
+    FIELDSET   : 0,
+    FONT       : 0,
+    FORM       : BREAKS_FLOW,
+    FRAME      : UNSAFE|EMPTY,
+    FRAMESET   : UNSAFE,
+    H1         : BREAKS_FLOW,
+    H2         : BREAKS_FLOW,
+    H3         : BREAKS_FLOW,
+    H4         : BREAKS_FLOW,
+    H5         : BREAKS_FLOW,
+    H6         : BREAKS_FLOW,
+    HEAD       : UNSAFE|OPTIONAL_ENDTAG|BREAKS_FLOW,
+    HR         : EMPTY|BREAKS_FLOW,
+    HTML       : UNSAFE|OPTIONAL_ENDTAG|BREAKS_FLOW,
+    I          : 0,
+    IFRAME     : UNSAFE,
+    IMG        : EMPTY,
+    INPUT      : EMPTY,
+    INS        : 0,
+    ISINDEX    : UNSAFE|EMPTY|BREAKS_FLOW,
+    KBD        : 0,
+    LABEL      : 0,
+    LEGEND     : 0,
+    LI         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    LINK       : UNSAFE|EMPTY,
+    MAP        : 0,
+    MENU       : BREAKS_FLOW,
+    META       : UNSAFE|EMPTY,
+    NOFRAMES   : UNSAFE|BREAKS_FLOW,
+    NOSCRIPT   : UNSAFE,
+    OBJECT     : UNSAFE,
+    OL         : BREAKS_FLOW,
+    OPTGROUP   : 0,
+    OPTION     : OPTIONAL_ENDTAG,
+    P          : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    PARAM      : UNSAFE|EMPTY,
+    PRE        : BREAKS_FLOW,
+    Q          : 0,
+    S          : 0,
+    SAMP       : 0,
+    SCRIPT     : UNSAFE,
+    SELECT     : 0,
+    SMALL      : 0,
+    SPAN       : 0,
+    STRIKE     : 0,
+    STRONG     : 0,
+    STYLE      : UNSAFE,
+    SUB        : 0,
+    SUP        : 0,
+    TABLE      : BREAKS_FLOW,
+    TBODY      : OPTIONAL_ENDTAG,
+    TD         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    TEXTAREA   : 0,
+    TFOOT      : OPTIONAL_ENDTAG,
+    TH         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    THEAD      : OPTIONAL_ENDTAG,
+    TITLE      : UNSAFE|BREAKS_FLOW,
+    TR         : OPTIONAL_ENDTAG|BREAKS_FLOW,
+    TT         : 0,
+    U          : 0,
+    UL         : BREAKS_FLOW,
+    VAR        : 0
+  };
+
+  /**
+   * All the HTML4 attributes
+   */
+  var ATTRIBS = {
+    ABBR            : 0,
+    ACCEPT          : 0,
+    'ACCEPT-CHARSET': 0,
+    ACCESSKEY       : 0,
+    ACTION          : URI_TYPE,
+    ALIGN           : 0,
+    ALINK           : 0,
+    ALT             : 0,
+    ARCHIVE         : URI_TYPE,
+    AXIS            : 0,
+    BACKGROUND      : URI_TYPE,
+    BGCOLOR         : 0,
+    BORDER          : 0,
+    CELLPADDING     : 0,
+    CELLSPACING     : 0,
+    CHAR            : 0,
+    CHAROFF         : 0,
+    CHARSET         : 0,
+    CHECKED         : 0,
+    CITE            : URI_TYPE,
+    CLASS           : NMTOKEN_TYPE,
+    CLASSID         : URI_TYPE,
+    CLEAR           : 0,
+    CODE            : 0,
+    CODEBASE        : URI_TYPE,
+    CODETYPE        : 0,
+    COLOR           : 0,
+    COLS            : 0,
+    COLSPAN         : 0,
+    COMPACT         : 0,
+    CONTENT         : 0,
+    COORDS          : 0,
+    DATA            : URI_TYPE,
+    DATETIME        : 0,
+    DECLARE         : 0,
+    DEFER           : 0,
+    DIR             : 0,
+    DISABLED        : 0,
+    ENCTYPE         : 0,
+    FACE            : 0,
+    FOR             : NMTOKEN_TYPE,
+    FRAME           : 0,
+    FRAMEBORDER     : 0,
+    HEADERS         : 0,
+    HEIGHT          : 0,
+    HREF            : URI_TYPE,
+    HREFLANG        : 0,
+    HSPACE          : 0,
+    'HTTP-EQUIV'    : 0,
+    ID              : NMTOKEN_TYPE,
+    ISMAP           : 0,
+    LABEL           : 0,
+    LANG            : 0,
+    LANGUAGE        : 0,
+    LINK            : 0,
+    LONGDESC        : URI_TYPE,
+    MARGINHEIGHT    : 0,
+    MARGINWIDTH     : 0,
+    MAXLENGTH       : 0,
+    MEDIA           : 0,
+    METHOD          : 0,
+    MULTIPLE        : 0,
+    NAME            : NMTOKEN_TYPE,  // but not really for inputs
+    NOHREF          : 0,
+    NORESIZE        : 0,
+    NOSHADE         : 0,
+    NOWRAP          : 0,
+    OBJECT          : 0,
+    ONBLUR          : SCRIPT_TYPE,
+    ONCHANGE        : SCRIPT_TYPE,
+    ONCLICK         : SCRIPT_TYPE,
+    ONDBLCLICK      : SCRIPT_TYPE,
+    ONFOCUS         : SCRIPT_TYPE,
+    ONKEYDOWN       : SCRIPT_TYPE,
+    ONKEYPRESS      : SCRIPT_TYPE,
+    ONKEYUP         : SCRIPT_TYPE,
+    ONLOAD          : SCRIPT_TYPE,
+    ONMOUSEDOWN     : SCRIPT_TYPE,
+    ONMOUSEMOVE     : SCRIPT_TYPE,
+    ONMOUSEOUT      : SCRIPT_TYPE,
+    ONMOUSEOVER     : SCRIPT_TYPE,
+    ONMOUSEUP       : SCRIPT_TYPE,
+    ONRESET         : SCRIPT_TYPE,
+    ONSELECT        : SCRIPT_TYPE,
+    ONSUBMIT        : SCRIPT_TYPE,
+    ONUNLOAD        : SCRIPT_TYPE,
+    PROFILE         : URI_TYPE,
+    PROMPT          : 0,
+    READONLY        : 0,
+    REL             : 0,
+    REV             : 0,
+    ROWS            : 0,
+    ROWSPAN         : 0,
+    RULES           : 0,
+    SCHEME          : 0,
+    SCOPE           : 0,
+    SCROLLING       : 0,
+    SELECTED        : 0,
+    SHAPE           : 0,
+    SIZE            : 0,
+    SPAN            : 0,
+    SRC             : URI_TYPE,
+    STANDBY         : 0,
+    START           : 0,
+    STYLE           : STYLE_TYPE,
+    SUMMARY         : 0,
+    TABINDEX        : 0,
+    TARGET          : 0,
+    TEXT            : 0,
+    TITLE           : 0,
+    TYPE            : 0,
+    USEMAP          : URI_TYPE,
+    VALIGN          : 0,
+    VALUE           : 0,
+    VALUETYPE       : 0,
+    VERSION         : 0,
+    VLINK           : 0,
+    VSPACE          : 0,
+    WIDTH           : 0
+  };
+
+  var ENTITIES = {
+    LT   : '<',
+    GT   : '>',
+    AMP  : '&',
+    NBSP : '\240',
+    QUOT : '"',
+    APOS : '\''
+  };
+
+  function escapeOneEntity(m) {
+    var name = m[1].toUpperCase();
+    if (ENTITIES.hasOwnProperty(s)) { return ENTITIES[name]; }
+    m = name.match(/^#(\d+)$/);
+    if (m) {
+      return String.fromCharCode(parseInt(m[1], 10));
+    } else if (!!(m = name.match(/^#x([0-9A-F]+)$/))) {
+      return String.fromCharCode(parseInt(m[1], 16));
+    }
+    return '';
+  }
+
+  function unescapeEntities(s) {
+    return s.replace(/&(#\d+|#x[\da-f]+|\w+);/g, escapeOneEntity);
+  }
+
+  function unescapedValueForAttrib(s) {
+    var m = s.match(/=\s*([\"\']?)?(.*)\1/);
+    if (m) {
+      return unescapeEntities(m[2]);
+    } else {
+      return null;
+    }
+  }
+
+  function escapeAttrib(s) {
+    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/&/g, '&gt;')
+      .replace(/\"/g, '&quot;');
+  }
+
+  /** actually does the sanitizing. */
+  return function html_sanitize(html, opt_urlXform, opt_nmTokenXform) {
+    var toks = lex(html);
+    var out = [];
+
+    var ignoring = false;
+    for (var i = 0; i < toks.length; ++i) {
+      var tok = toks[i], type = toks[++i];
+      //alert('tok=' + tok + ', type=' + type + ', ignoring=' + ignoring);
+      if (TOK_TAG_BEGIN === type) {
+        var name = tok.replace(/^[<\/]+/, '').toUpperCase();
+        ignoring = !ELEMENTS.hasOwnProperty(name) || (ELEMENTS[name] & UNSAFE);
+      } else if (TOK_ATTRIB === type && !ignoring) {
+        var name = tok.match(/\w+/)[0].toUpperCase();
+        if (!ATTRIBS.hasOwnProperty(name)) { continue; }
+        var flags = ATTRIBS[name];
+        if (flags & (SCRIPT_TYPE | STYLE_TYPE)) { continue; }
+        if (flags) {
+          // apply transforms
+          // unescape value, transform it.  skip if null, otherwise reescape.
+          var value = unescapedValueForAttrib(tok);
+          if (null == value) { continue; }
+          if ((flags & URI_TYPE) && opt_urlXform) {
+            value = opt_urlXform(value);
+          }
+          if ((flags & NMTOKEN_TYPE) && opt_nmTokenXform) {
+            value = opt_nmTokenXForm(value);
+          }
+          if (null == value) { continue; }
+          tok = name + '="' + escapeAttrib(value) + '"';
+        }
+      }
+      if (!ignoring) { out.push(tok); }
+      // TODO: some way of enforcing attribute constraints
+      if (TOK_TAG_END === type) { ignoring = false; }
+    }
+    return out.join('');
+  };
+
+})();

Modified: incubator/shindig/trunk/features/opensocial-reference/container.js
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-reference/container.js?rev=611350&r1=611349&r2=611350&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-reference/container.js 
(original)
+++ incubator/shindig/trunk/features/opensocial-reference/container.js Fri Jan 
11 18:08:32 2008
@@ -21,9 +21,7 @@
  * @constructor
  * @private
  */
-opensocial.Container = function() {
-  this.cajaEnabled_ = false;
-};
+opensocial.Container = function() {};
 
 
 /**
@@ -290,8 +288,7 @@
  */
 opensocial.Container.prototype.newCollection = function(array, opt_offset,
     opt_totalSize) {
-  return this.wrapCollectionWithCaja_(new opensocial.Collection(array,
-      opt_offset, opt_totalSize));
+  return new opensocial.Collection(array, opt_offset, opt_totalSize);
 };
 
 
@@ -302,8 +299,7 @@
  */
 opensocial.Container.prototype.newPerson = function(opt_params, opt_isOwner,
     opt_isViewer) {
-  return this.wrapPersonWithCaja_(new opensocial.Person(opt_params, 
opt_isOwner,
-      opt_isViewer));
+  return new opensocial.Person(opt_params, opt_isOwner, opt_isViewer);
 };
 
 
@@ -321,7 +317,7 @@
  */
 opensocial.Container.prototype.newActivity = function(title,
     opt_params) {
-  return this.wrapActivityWithCaja_(new opensocial.Activity(title, 
opt_params));
+  return new opensocial.Activity(title, opt_params);
 };
 
 
@@ -340,8 +336,7 @@
  */
 opensocial.Container.prototype.newActivityMediaItem = function(mimeType, url,
     opt_params) {
-  return this.wrapActivityMediaItemWithCaja_(
-      new opensocial.Activity.MediaItem(mimeType, url, opt_params));
+  return new opensocial.Activity.MediaItem(mimeType, url, opt_params);
 };
 
 
@@ -352,8 +347,8 @@
  */
 opensocial.Container.prototype.newResponseItem = function(originalDataRequest,
     data, opt_errorCode, opt_errorMessage) {
-  return this.wrapResponseItemWithCaja_(new opensocial.ResponseItem(
-      originalDataRequest, data, opt_errorCode, opt_errorMessage));
+  return new opensocial.ResponseItem(originalDataRequest, data, opt_errorCode,
+      opt_errorMessage);
 };
 
 
@@ -364,8 +359,7 @@
  */
 opensocial.Container.prototype.newDataResponse = function(responseItems,
     opt_globalError) {
-  return this.wrapDataResponseWithCaja_(new opensocial.DataResponse(
-      responseItems, opt_globalError));
+  return new opensocial.DataResponse(responseItems, opt_globalError);
 };
 
 
@@ -377,7 +371,7 @@
  * @private
  */
 opensocial.Container.prototype.newDataRequest = function() {
-  return this.wrapDataRequestWithCaja_(new opensocial.DataRequest());
+  return new opensocial.DataRequest();
 };
 
 
@@ -389,8 +383,8 @@
  */
 opensocial.Container.prototype.newEnvironment = function(domain, surface,
     supportedSurfaces, supportedFields, opt_params) {
-  return this.wrapEnvironmentWithCaja_(new opensocial.Environment(domain,
-      surface, supportedSurfaces, supportedFields, opt_params));
+  return new opensocial.Environment(domain, surface, supportedSurfaces,
+      supportedFields, opt_params);
 };
 
 
@@ -402,8 +396,7 @@
  */
 opensocial.Container.prototype.newSurface = function(name,
     opt_isPrimaryContent) {
-  return this.wrapSurfaceWithCaja_(new opensocial.Surface(name,
-      opt_isPrimaryContent));
+  return new opensocial.Surface(name, opt_isPrimaryContent);
 };
 
 
@@ -439,38 +432,34 @@
 
   var outers = caja.copy(___.sharedOuters);
 
-  // TODO(doll): Is this the way all containers should do this?
+  // TODO(doll): We need to add caja allows for the gadgets namespace so that
+  // this works properly. It does not belong in gadgets.
   var igOnload = window["_IG_RegisterOnloadHandler"];
   if (igOnload) {
     outers._IG_RegisterOnloadHandler = ___.simpleFunc(igOnload);
   }
 
-  // TODO(doll): Remove need for this
-  outers.expose = function expose(name, func) {
-    // TODO(benl): we should check that name does not contain
-    // anything except numbers and letters.
-    eval(name + ' = func;');
-  };
-
-  outers.emitHtml___ = function emitHtml(html) {
-    // TODO(doll): This only works for the sample container. Really emitHtml
-    // should be a passed in function
-    var oldHtml = document.getElementById("gadgetContent").innerHTML;
-    document.getElementById("gadgetContent").innerHTML = oldHtml + html;
+  outers.emitHtml___ = function emitHtml(var_args) {
+    var html = Array.prototype.slice.call(arguments, 0).join('');
+    document.write(html);
   };
 
-
   outers.document = function() {};
   outers.document.getElementById = function(id) {
     // TODO(benl): namespace-ize id.
-    var element = document.getElementById(id);
-    // TODO(benl): replace innerHTML with hidden getter/setter
-    ___.allowSet(element, 'innerHTML');
+    var element = document.getElementById("DOM-PREFIX-" + id);
+    if (element !== null) {
+      ___.useSetHandler(element, 'innerHTML', function(html) {
+        var temp = html_sanitize(html);
+        return this.innerHTML = temp;
+      });
+    }
     return element;
   };
 
   ___.allowCall(outers.document, 'getElementById');
 
+  // Adding all of the available opensocial calls as defined in the spec
   outers.opensocial = opensocial;
   ___.allowCall(outers.opensocial, 'requestCreateActivity');
   ___.allowCall(outers.opensocial, 'hasPermission');
@@ -481,122 +470,74 @@
   ___.allowCall(outers.opensocial, 'newActivity');
   ___.allowCall(outers.opensocial, 'newActivityMediaItem');
 
+  ___.allowCall(opensocial.Collection.prototype, 'getById');
+  ___.allowCall(opensocial.Collection.prototype, 'size');
+  ___.allowCall(opensocial.Collection.prototype, 'each');
+  ___.allowCall(opensocial.Collection.prototype, 'asArray');
+  ___.allowCall(opensocial.Collection.prototype, 'getTotalSize');
+  ___.allowCall(opensocial.Collection.prototype, 'getOffset');
+
+  // TODO(doll): Call caja method to support all array calls once it exists
+  ___.allowCall(Array.prototype, 'push');
+  ___.allowCall(Array.prototype, 'sort');
+
+  ___.allowCall(opensocial.Person.prototype, 'getId');
+  ___.allowCall(opensocial.Person.prototype, 'getDisplayName');
+  ___.allowCall(opensocial.Person.prototype, 'getField');
+  ___.allowCall(opensocial.Person.prototype, 'isViewer');
+  ___.allowCall(opensocial.Person.prototype, 'isOwner');
+
+  ___.allowCall(opensocial.Activity.prototype, 'getId');
+  ___.allowCall(opensocial.Activity.prototype, 'getField');
+
+  ___.allowCall(opensocial.Activity.MediaItem.prototype, 'getField');
+
+  ___.allowCall(opensocial.ResponseItem.prototype, 'hadError');
+  ___.allowCall(opensocial.ResponseItem.prototype, 'getError');
+  ___.allowCall(opensocial.ResponseItem.prototype, 'getOriginalDataRequest');
+  ___.allowCall(opensocial.ResponseItem.prototype, 'getData');
+
+  ___.allowCall(opensocial.DataResponse.prototype, 'hadError');
+  ___.allowCall(opensocial.DataResponse.prototype, 'get');
+
+  ___.allowCall(opensocial.DataRequest.prototype, 'getRequestObjects');
+  ___.allowCall(opensocial.DataRequest.prototype, 'add');
+  ___.allowCall(opensocial.DataRequest.prototype, 'send');
+  ___.allowCall(opensocial.DataRequest.prototype, 'newFetchPersonRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 'newFetchPeopleRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 
'newFetchGlobalAppDataRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 
'newFetchInstanceAppDataRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 
'newUpdateInstanceAppDataRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 
'newFetchPersonAppDataRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 
'newUpdatePersonAppDataRequest');
+  ___.allowCall(opensocial.DataRequest.prototype, 'newFetchActivitiesRequest');
+
+  ___.allowCall(opensocial.Environment.prototype, 'getDomain');
+  ___.allowCall(opensocial.Environment.prototype, 'getSurface');
+  ___.allowCall(opensocial.Environment.prototype, 'getSupportedSurfaces');
+  ___.allowCall(opensocial.Environment.prototype, 'getParams');
+  ___.allowCall(opensocial.Environment.prototype, 'supportsField');
+  ___.allowCall(opensocial.Environment.prototype, 'hasCapability');
+
+  ___.allowCall(opensocial.Surface.prototype, 'getName');
+  ___.allowCall(opensocial.Surface.prototype, 'isPrimaryContent');
+
   var moduleHandler = ___.freeze({
     getOuters: ___.simpleFunc(function() { return outers; }),
     handle: ___.simpleFunc(function(newModule) { newModule(outers); })
   });
 
-
- this.cajaEnabled_ = true;
   ___.setNewModuleHandler(moduleHandler);
 };
 
-
-opensocial.Container.prototype.wrapCollectionWithCaja_ = function(collection) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(collection, 'getById');
-    ___.allowCall(collection, 'size');
-    ___.allowCall(collection, 'each');
-    ___.allowCall(collection, 'asArray');
-    ___.allowCall(collection, 'getTotalSize');
-    ___.allowCall(collection, 'getOffset');
-
-    // TODO(doll): Call caja method to support all array calls once it exists
-    ___.allowCall(collection.asArray(), 'push');
-    ___.allowCall(collection.asArray(), 'sort');
-  }
-  return collection;
-};
-
-
-opensocial.Container.prototype.wrapPersonWithCaja_ = function(person) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(person, 'getId');
-    ___.allowCall(person, 'getDisplayName');
-    ___.allowCall(person, 'getField');
-    ___.allowCall(person, 'isViewer');
-    ___.allowCall(person, 'isOwner');
-  }
-  return person;
-};
-
-
-opensocial.Container.prototype.wrapActivityWithCaja_ = function(activity) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(activity, 'getId');
-    ___.allowCall(activity, 'getField');
-  }
-  return activity;
-};
-
-
-opensocial.Container.prototype.wrapActivityMediaItemWithCaja_ = function(
-    mediaItem) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(mediaItem, 'getField');
-  }
-  return mediaItem;
-};
-
-
-opensocial.Container.prototype.wrapResponseItemWithCaja_ = function(
-    responseItem) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(responseItem, 'hadError');
-    ___.allowCall(responseItem, 'getError');
-    ___.allowCall(responseItem, 'getOriginalDataRequest');
-    ___.allowCall(responseItem, 'getData');
-  }
-  return responseItem;
-};
-
-
-opensocial.Container.prototype.wrapDataResponseWithCaja_ = function(
-    dataResponse) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(dataResponse, 'hadError');
-    ___.allowCall(dataResponse, 'get');
-  }
-  return dataResponse;
-};
-
-
-opensocial.Container.prototype.wrapDataRequestWithCaja_ = function(request) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(request, 'getRequestObjects');
-    ___.allowCall(request, 'add');
-    ___.allowCall(request, 'send');
-    ___.allowCall(request, 'newFetchPersonRequest');
-    ___.allowCall(request, 'newFetchPeopleRequest');
-    ___.allowCall(request, 'newFetchGlobalAppDataRequest');
-    ___.allowCall(request, 'newFetchInstanceAppDataRequest');
-    ___.allowCall(request, 'newUpdateInstanceAppDataRequest');
-    ___.allowCall(request, 'newFetchPersonAppDataRequest');
-    ___.allowCall(request, 'newUpdatePersonAppDataRequest');
-    ___.allowCall(request, 'newFetchActivitiesRequest');
-  }
-  return request;
-};
-
-
-opensocial.Container.prototype.wrapEnvironmentWithCaja_ = function(
-    environment) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(environment, 'getDomain');
-    ___.allowCall(environment, 'getSurface');
-    ___.allowCall(environment, 'getSupportedSurfaces');
-    ___.allowCall(environment, 'getParams');
-    ___.allowCall(environment, 'supportsField');
-    ___.allowCall(environment, 'hasCapability');
-  }
-  return environment;
-};
-
-
-opensocial.Container.prototype.wrapSurfaceWithCaja_ = function(surface) {
-  if (this.cajaEnabled_) {
-    ___.allowCall(surface, 'getName');
-    ___.allowCall(surface, 'isPrimaryContent');
-  }
-  return surface;
-};
+/**
+ * Default taming is to return obj itself. Depending on
+ * other taming decisions, it may be more appropriate to
+ * return an interposed wrapper.
+ */
+function plugin_tamed(obj) { return obj; }
+
+function plugin_dispatchEvent___(thisNode, event, pluginId, handlerName) {
+  return ___.getOuters(pluginId)[handlerName](plugin_tamed(thisNode),
+      plugin_tamed(event));
+}
\ No newline at end of file


Reply via email to