Switch more gwt-user code to use SafeHtml.

Review at http://gwt-code-reviews.appspot.com/1614803


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10801 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/DOM.gwt.xml b/user/src/com/google/gwt/dom/DOM.gwt.xml
index 4fe314e..4dfc42f 100644
--- a/user/src/com/google/gwt/dom/DOM.gwt.xml
+++ b/user/src/com/google/gwt/dom/DOM.gwt.xml
@@ -18,6 +18,7 @@
 <!--                                                                        -->
 <module>
   <inherits name="com.google.gwt.core.Core"/>
+  <inherits name="com.google.gwt.safehtml.SafeHtml"/>
   <inherits name="com.google.gwt.user.UserAgent"/>
 
   <replace-with class="com.google.gwt.dom.client.DOMImplOpera">
diff --git a/user/src/com/google/gwt/dom/client/Element.java b/user/src/com/google/gwt/dom/client/Element.java
index 663a1bf..258d3d3 100644
--- a/user/src/com/google/gwt/dom/client/Element.java
+++ b/user/src/com/google/gwt/dom/client/Element.java
@@ -16,6 +16,7 @@
 package com.google.gwt.dom.client;
 
 import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.safehtml.shared.SafeHtml;
 
 /**
  * All HTML element interfaces derive from this class.
@@ -658,6 +659,13 @@
    }-*/;
 
   /**
+   * All of the markup and content within a given element.
+   */
+  public final void setInnerSafeHtml(SafeHtml html) {
+    setInnerHTML(html.asString());
+  }
+
+  /**
    * The text between the start and end tags of the object.
    */
   public final void setInnerText(String text) {
diff --git a/user/src/com/google/gwt/user/client/ui/FormPanel.java b/user/src/com/google/gwt/user/client/ui/FormPanel.java
index 6143ff5..5644ab4 100644
--- a/user/src/com/google/gwt/user/client/ui/FormPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/FormPanel.java
@@ -22,6 +22,8 @@
 import com.google.gwt.event.shared.EventHandler;
 import com.google.gwt.event.shared.GwtEvent;
 import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates;
+import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeUri;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
@@ -208,6 +210,14 @@
     void onSubmit(FormPanel.SubmitEvent event);
   }
 
+  interface IFrameTemplate extends SafeHtmlTemplates {
+    static final IFrameTemplate INSTANCE = GWT.create(IFrameTemplate.class);
+
+    @Template("<iframe src=\"javascript:''\" name='{0}' "
+        + "style='position:absolute;width:0;height:0;border:0'>")
+    SafeHtml get(String name);
+  }
+
   /**
    * Used with {@link #setEncoding(String)} to specify that the form will be
    * submitted using MIME encoding (necessary for {@link FileUpload} to work
@@ -602,8 +612,7 @@
     // because setting an iframe's 'name' property dynamically doesn't work on
     // most browsers.
     Element dummy = Document.get().createDivElement();
-    dummy.setInnerHTML("<iframe src=\"javascript:''\" name='" + frameName
-        + "' style='position:absolute;width:0;height:0;border:0'>");
+    dummy.setInnerSafeHtml(IFrameTemplate.INSTANCE.get(frameName));
 
     synthesizedFrame = dummy.getFirstChildElement();
   }
diff --git a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
index c4b9157..f54d15f 100644
--- a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
@@ -19,6 +19,7 @@
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
@@ -617,10 +618,11 @@
      * case. The usually CSS hacks (display: table-cell, vertical-align: middle)
      * don't work in an absolute positioned DIV.
      */
-    DOM.setInnerHTML(splitDiv,
-        "<table class='hsplitter' height='100%' cellpadding='0' "
-            + "cellspacing='0'><tr><td align='center' valign='middle'>"
-            + thumbImage.getHTML());
+    SafeHtmlBuilder sb = new SafeHtmlBuilder();
+    sb.appendHtmlConstant("<table class='hsplitter' height='100%' cellpadding='0' "
+        + "cellspacing='0'><tr><td align='center' valign='middle'>");
+    sb.append(thumbImage.getSafeHtml());
+    splitDiv.setInnerSafeHtml(sb.toSafeHtml());
 
     addScrolling(leftDiv);
     addScrolling(rightDiv);
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index 5810adf..829127c 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -1007,7 +1007,7 @@
       setItemColSpan(item, 1);
       Element td = DOM.createTD();
       DOM.setElementProperty(td, "vAlign", "middle");
-      DOM.setInnerHTML(td, subMenuIcon.getHTML());
+      td.setInnerSafeHtml(subMenuIcon.getSafeHtml());
       setStyleName(td, "subMenuIcon");
       DOM.appendChild(tr, td);
     }
diff --git a/user/src/com/google/gwt/user/client/ui/NamedFrame.java b/user/src/com/google/gwt/user/client/ui/NamedFrame.java
index c290e00..9fe635b 100644
--- a/user/src/com/google/gwt/user/client/ui/NamedFrame.java
+++ b/user/src/com/google/gwt/user/client/ui/NamedFrame.java
@@ -18,6 +18,8 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.dom.client.IFrameElement;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates;
+import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.uibinder.client.UiConstructor;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
@@ -33,6 +35,12 @@
  * </ul>
  */
 public class NamedFrame extends Frame {
+  interface IFrameTemplate extends SafeHtmlTemplates {
+    static final IFrameTemplate INSTANCE = GWT.create(IFrameTemplate.class);
+
+    @Template("<iframe src='{0}' name='{1}'>")
+    SafeHtml get(String src, String name);
+  }
 
   // Used inside JSNI, so please don't delete this field just because
   // your compiler or IDE says it's unused.
@@ -56,7 +64,6 @@
    * @throws IllegalArgumentException if the supplied name is not allowed 
    */
   private static IFrameElement createIFrame(String src, String name) {
-    // TODO(pdr): add SafeHtml support here to prevent XSS
     if (name == null || !isValidName(name.trim())) {
       throw new IllegalArgumentException(
           "expecting one or more non-whitespace chars with no '<', '>', or '&'");
@@ -65,7 +72,7 @@
     // Use innerHTML to implicitly create the <iframe>. This is necessary
     // because most browsers will not respect a dynamically-set iframe name.
     Element div = DOM.createDiv();
-    div.setInnerHTML("<iframe src=\"" + src + "\" name='" + name + "'>");
+    div.setInnerSafeHtml(IFrameTemplate.INSTANCE.get(src, name));
     return div.getFirstChild().cast();
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
index c3f720d..6d0c9bb 100644
--- a/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
@@ -18,6 +18,7 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
@@ -435,8 +436,11 @@
      * The style name is placed on the table rather than splitElem to allow the
      * splitter to be styled without interfering with layout.
      */
-    DOM.setInnerHTML(splitDiv, "<div class='vsplitter' "
-        + "style='text-align:center;'>" + thumb.getHTML() + "</div>");
+    SafeHtmlBuilder sb = new SafeHtmlBuilder();
+    sb.appendHtmlConstant("<div class='vsplitter' style='text-align:center;'>");
+    sb.append(thumb.getSafeHtml());
+    sb.appendHtmlConstant("</div>");
+    splitDiv.setInnerSafeHtml(sb.toSafeHtml());
 
     addScrolling(topDiv);
     addScrolling(bottomDiv);