Reviewers: felix8a,

Description:
* Implement HTML5-conformant behavior for document.title if there is no
  <title> element.
* Remove attribute/property "blacklist" code from TameIFrameElement
  which is no longer necessary since the whitelist is per-attribute.
* Move misplaced @param comment for taming membrane parameter.

Please review this at http://codereview.appspot.com/6843122/

Affected files:
  M     src/com/google/caja/plugin/domado.js
  M     tests/com/google/caja/plugin/es53-test-domado-dom-guest.html
  M     tests/com/google/caja/plugin/es53-test-domado-global.js


Index: tests/com/google/caja/plugin/es53-test-domado-dom-guest.html
===================================================================
--- tests/com/google/caja/plugin/es53-test-domado-dom-guest.html (revision 5166) +++ tests/com/google/caja/plugin/es53-test-domado-dom-guest.html (working copy)
@@ -2497,8 +2497,8 @@
     assertEquals('1', ifr.getAttribute('frameBorder'));
     assertEquals(null, ifr.getAttribute('name'));
     assertEquals(null, ifr.getAttribute('src'));
-    assertEquals(void 0, ifr.name);
-    assertEquals(void 0, ifr.src);
+    assertEquals(null, ifr.name);
+    assertEquals(null, ifr.src);
     pass('testIframeShim');
   });
 </script>
Index: tests/com/google/caja/plugin/es53-test-domado-global.js
===================================================================
--- tests/com/google/caja/plugin/es53-test-domado-global.js     (revision 5166)
+++ tests/com/google/caja/plugin/es53-test-domado-global.js     (working copy)
@@ -105,6 +105,29 @@
     }());

     /**
+      * Tests of global structure-referencing property behavior.
+      */
+    (function () {
+      // Behavior of document.title without any title element present
+      registerGuestTest('testNoElementTitleProp',
+ '<body>' + // TODO(kpreid): That this is required is a HtmlEmitter bug
+          '<script>window.globalGuestTest =' +
+          '    function globalGuestTest() {' +
+          '  assertEquals("head before get", "", ' +
+          '      document.getElementsByTagName("head")[0].innerHTML);' +
+          '  assertEquals("title before set", "", document.title);' +
+          '  assertEquals("head after get", "", ' +
+          '      document.getElementsByTagName("head")[0].innerHTML);' +
+          '  document.title = "t";' +
+          '  assertEquals("title after set", "t", document.title);' +
+          '  assertEquals("head after set", "<title>t</title>", ' +
+          '      document.getElementsByTagName("head")[0].innerHTML);' +
+          '};</script>');
+
+      // TODO(kpreid): Test document.body
+    })();
+
+    /**
* Tests of onload handlers, which are a special case because on* attributes * on <body> are actually aliases for event handlers of the _window_ object, * so since our virtual window object is not backed by anything we have to
Index: src/com/google/caja/plugin/domado.js
===================================================================
--- src/com/google/caja/plugin/domado.js        (revision 5166)
+++ src/com/google/caja/plugin/domado.js        (working copy)
@@ -922,7 +922,6 @@
* objects, and a shared map allowing separate virtual documents to dispatch
    * events across them. (TODO(kpreid): Confirm this explanation is good.)
    *
-   * @param {Object} taming. An interface to a taming membrane.
* @param {Object} opt_rulebreaker. If necessary, authorities to break the
    *     ES5/3 taming membrane and work with the taming-frame system. If
    *     running under SES, pass null instead.
@@ -1519,6 +1518,7 @@
      *     virtual Document node provided to Cajoled code.
* @param {Object} optTargetAttributePresets a record containing the presets
      *     (default and whitelist) for the HTML "target" attribute.
+     * @param {Object} taming. An interface to a taming membrane.
* @return {Object} A collection of privileged access tools, plus the tamed * {@code document} and {@code window} objects under those names. This
      *     object is known as a "domicile".
@@ -3576,6 +3576,11 @@
                     bridal.getAttribute(feral, 'target')));
               }
             }
+          } else {
+            if (typeof console !== 'undefined') {
+              console.warn('Rejecting <' + tagName + '>.setAttribute(',
+                  attribName, ',', value, ')');
+            }
           }
         }
         return value;
@@ -4618,15 +4623,6 @@
         domClass: 'HTMLHtmlElement'
       });

-      var P_blacklist = {
-        enumerable: true,
-        extendedAccessors: true,
-        get: nodeMethod(function () { return undefined; }),
-        set: nodeMethod(function (value, prop) {
-          if (typeof console !== 'undefined')
- console.error('Cannot set the [', prop, '] property of an iframe.');
-        })
-      };
       var TameIFrameElement = defineElement({
         domClass: 'HTMLIFrameElement',
         construct: function () {
@@ -4664,8 +4660,8 @@
           },
           height: NP.filterProp(identity, Number),
           width:  NP.filterProp(identity, Number),
-          src: P_blacklist,
-          name: P_blacklist,
+ src: NP.filterAttr(identity, identity), // rewrite handled for attr + name: NP.filterAttr(identity, identity), // rejection handled for attr
           contentDocument: {
             enumerable: true,
             get: cajaVM.def(function () {
@@ -4693,18 +4689,10 @@
       setOwn(TameIFrameElement.prototype, 'setAttribute',
           nodeMethod(function (attr, value) {
         var attrLc = String(attr).toLowerCase();
-        // The 'name' and 'src' attributes are whitelisted for all tags in
-        // html4-attributes-whitelist.json, since they're needed on tags
- // like <img>. Because there's currently no way to filter attributes
-        // based on the tag, we have to blacklist these two here.
-        // TODO(kpreid): Don't we have per-attribute filtering now?
-        if (attrLc !== 'name' && attrLc !== 'src') {
- return TameElement.prototype.setAttribute.call(this, attr, value);
+        if (attrLc === 'src') {
+          // ...
         }
-        if (typeof console !== 'undefined')
-          console.error('Cannot set the [' + attrLc +
-              '] attribute of an iframe.');
-        return value;
+        return TameElement.prototype.setAttribute.call(this, attr, value);
       }));
       function contentDomicile(tameIFrame) {
// TODO(kpreid): Once we support loading content via src=, we will need
@@ -5318,10 +5306,19 @@
           enumerable: true,
           get: nodeMethod(function() {
             var titleEl = this.getElementsByTagName('title')[0];
-            return trimHTML5Spaces(titleEl.textContent);
+            return titleEl ? trimHTML5Spaces(titleEl.textContent) : "";
           }),
           set: nodeMethod(function(value) {
             var titleEl = this.getElementsByTagName('title')[0];
+            if (!titleEl) {
+              var head = this.getElementsByTagName('head')[0];
+              if (head) {
+                titleEl = this.createElement('title');
+                head.appendChild(titleEl);
+              } else {
+                return;
+              }
+            }
             titleEl.textContent = value;
           })
         },


Reply via email to