Add @MimeType and @DoNotEmbed support to <ui:data.

Change-Id: Ie10be09bf9248de10c28c700db170dc56887b461
Review-Link: https://gwt-review.googlesource.com/#/c/9515/
(cherry picked from commit 0e1066b77b605846d58bdda907431b4eac7abdbc)
diff --git a/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java b/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java
index 02c09c2..aeff25f 100644
--- a/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java
@@ -21,6 +21,8 @@
 import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.CssResource.Import;
 import com.google.gwt.resources.client.DataResource;
+import com.google.gwt.resources.client.DataResource.DoNotEmbed;
+import com.google.gwt.resources.client.DataResource.MimeType;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
 import com.google.gwt.resources.client.ImageResource.RepeatStyle;
@@ -45,6 +47,8 @@
 
   private final JClassType clientBundleType;
   private final JClassType dataResourceType;
+  private final JClassType doNotEmbedType;
+  private final JClassType dataMimeTypeType;
   private final JClassType imageOptionType;
   private final JClassType imageResourceType;
   private final JClassType repeatStyleType;
@@ -61,6 +65,8 @@
 
     clientBundleType = types.findType(ClientBundle.class.getName());
     dataResourceType = types.findType(DataResource.class.getCanonicalName());
+    doNotEmbedType = types.findType(DoNotEmbed.class.getCanonicalName());
+    dataMimeTypeType = types.findType(MimeType.class.getCanonicalName());
     imageOptionType = types.findType(ImageOptions.class.getCanonicalName());
     imageResourceType = types.findType(ImageResource.class.getCanonicalName());
     repeatStyleType = types.findType(RepeatStyle.class.getCanonicalName());
@@ -87,6 +93,8 @@
     // Imports
     writer.write("import %s;", clientBundleType.getQualifiedSourceName());
     writer.write("import %s;", dataResourceType.getQualifiedSourceName());
+    writer.write("import %s;", doNotEmbedType.getQualifiedSourceName());
+    writer.write("import %s;", dataMimeTypeType.getQualifiedSourceName());
     writer.write("import %s;", imageResourceType.getQualifiedSourceName());
     writer.write("import %s;", imageOptionType.getQualifiedSourceName());
     writer.write("import %s;", importAnnotationType.getQualifiedSourceName());
@@ -108,6 +116,15 @@
     // Write data methods
     for (ImplicitDataResource data : bundleClass.getDataMethods()) {
       writer.write("@Source(\"%s\")", data.getSource());
+      writer.newline();
+      if (data.getDoNotEmbed() == Boolean.TRUE) {
+        writer.write("@DoNotEmbed");
+        writer.newline();
+      }
+      if (data.getMimeType() != null) {
+        writer.write("@MimeType(\"%s\")", data.getMimeType());
+        writer.newline();
+      }
       writer.write("%s %s();", dataResourceType.getName(), data.getName());
       writer.newline();
     }
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
index b7e16ca..1aacda7 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
@@ -93,6 +93,8 @@
   private static final String SOURCE_ATTRIBUTE = "src";
   private static final String TYPE_ATTRIBUTE = "type";
   private static final String GSS_ATTRIBUTE = "gss";
+  private static final String DO_NOT_EMBED_ATTRIBUTE = "doNotEmbed";
+  private static final String MIME_TYPE_ATTRIBUTE = "mimeType";
 
   // TODO(rjrjr) Make all the ElementParsers receive their dependencies via
   // constructor like this one does, and make this an ElementParser. I want
@@ -182,8 +184,12 @@
   private void createData(XMLElement elem) throws UnableToCompleteException {
     String name = elem.consumeRequiredRawAttribute(FIELD_ATTRIBUTE);
     String source = elem.consumeRequiredRawAttribute(SOURCE_ATTRIBUTE);
-    ImplicitDataResource dataMethod = bundleClass.createDataResource(name,
-        source);
+    // doNotEmbed is optional on DataResource
+    Boolean doNotEmbed = elem.consumeBooleanConstantAttribute(DO_NOT_EMBED_ATTRIBUTE);
+    // mimeType is optional on DataResource
+    String mimeType = elem.consumeRawAttribute(MIME_TYPE_ATTRIBUTE);
+    ImplicitDataResource dataMethod = bundleClass.createDataResource(
+        name, source, mimeType, doNotEmbed);
     FieldWriter field = fieldManager.registerField(dataResourceType,
         dataMethod.getName());
     field.setInitializer(String.format("%s.%s()",
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
index e1afec8..9c98cf2 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
@@ -82,10 +82,14 @@
    *
    * @param name the method name and the ui:field name
    * @param source path to the resource
+   * @param mimeType type of the resource
+   * @param doNotEmbed flag to prevent embedding the data resource
+   *
    * @return the newly-created DataResource
    */
-  public ImplicitDataResource createDataResource(String name, String source) {
-    ImplicitDataResource data = new ImplicitDataResource(name, source);
+  public ImplicitDataResource createDataResource(
+      String name, String source, String mimeType, Boolean doNotEmbed) {
+    ImplicitDataResource data = new ImplicitDataResource(name, source, mimeType, doNotEmbed);
     dataMethods.add(data);
     return data;
   }
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java
index 428ea8d..cce237e 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java
@@ -20,11 +20,15 @@
  */
 public class ImplicitDataResource {
   private final String name;
+  private final String mimeType;
   private final String source;
+  private final Boolean doNotEmbed;
 
-  ImplicitDataResource(String name, String source) {
+  ImplicitDataResource(String name, String source, String mimeType, Boolean doNotEmbed) {
     this.name = name;
     this.source = source;
+    this.mimeType = mimeType;
+    this.doNotEmbed = doNotEmbed;
   }
 
   public String getName() {
@@ -34,4 +38,12 @@
   public String getSource() {
     return source;
   }
+
+  public String getMimeType() {
+    return mimeType;
+  }
+
+  public Boolean getDoNotEmbed() {
+    return doNotEmbed;
+  }
 }
diff --git a/user/src/com/google/gwt/uibinder/resources/UiBinder.xsd b/user/src/com/google/gwt/uibinder/resources/UiBinder.xsd
index 1e431e3..b7c2bf6 100644
--- a/user/src/com/google/gwt/uibinder/resources/UiBinder.xsd
+++ b/user/src/com/google/gwt/uibinder/resources/UiBinder.xsd
@@ -196,6 +196,14 @@
             name="src"
             type="xs:string"
             use="required" />
+        <xs:attribute
+            name="doNotEmbed"
+            type="xs:boolean"
+            use="optional" />
+        <xs:attribute
+            name="mimeType"
+            type="xs:string"
+            use="optional" />
 
         <xs:anyAttribute
             processContents="lax" />
diff --git a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
index 9cf5732..c4f5fe4 100644
--- a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
@@ -666,6 +666,19 @@
     assertEquals("P", widgetUi.flowPanelWithTag.getElement().getTagName());
   }
 
+  public void testEmbeddedSvgMimeType() {
+    String url = widgetUi.embeddedSvgData.getSafeUri().asString();
+    if (url.startsWith("data:")) {
+      assertTrue(url.startsWith("data:image/svg+xml"));
+    }
+  }
+
+  public void testLinkedSvgNotEmbedded() {
+    String url = widgetUi.linkedSvgData.getSafeUri().asString();
+    assertFalse(url.startsWith("data:"));
+    assertTrue(url, url.endsWith(".svg"));
+  }
+
   /**
    * Assert that the expect strings are found in body, and in the order given.
    * WARNING: both body and expected are normalized to lower case, to get around
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
index 00cee8c..9d9ac3e 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
@@ -217,6 +217,8 @@
   @UiField Label labelWithComputedText;
   @UiField FlowPanel flowPanelWithTag;
   @UiField Element myElementWithTagName;
+  @UiField DataResource embeddedSvgData;
+  @UiField DataResource linkedSvgData;
 
   ValueChangeEvent<Double> doubleValueChangeEvent;
 
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
index 4d91c61..2e30fee 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
@@ -142,6 +142,7 @@
     cursor:cursor,pointer;
   }
 </ui:style>
+
 <ui:data field='heartCursorResource' src='heart.cur'/>
 
 <ui:style field='mySpritelyStyle'>
@@ -164,11 +165,15 @@
       font-size: 1.5em;
     }
 </ui:style>
+
 <ui:image field='prettyImage' />
 <ui:image field='prettyTilingImage' src='prettyImage.png' flipRtl='true' repeatStyle='Both'/>
 <ui:image field='right'/>
 <ui:image field='down'/>
 
+<ui:data field="embeddedSvgData" src="background.svg" mimeType="image/svg+xml" />
+<ui:data field="linkedSvgData" src="background.svg" doNotEmbed="true" />
+
 <gwt:DockPanel ui:field="root" width="100%" verticalAlignment="ALIGN_TOP">
   <gwt:Dock direction='NORTH'>
     <gwt:HTML ui:field='styleLess' styleName=''>
@@ -186,7 +191,7 @@
   <gwt:Dock direction='WEST'>
     <gwt:HTML ui:field='sideBarWidget' pixelSize="100, 150">
       <div ui:field="sideBar"
-      style='border: 4px solid gray; padding: 4px; margin: 4px;'
+          style='border: 4px solid gray; padding: 4px; margin: 4px;'
       >This could<br/>
         be a<br/>
         side bar<br/>
diff --git a/user/test/com/google/gwt/uibinder/test/client/background.svg b/user/test/com/google/gwt/uibinder/test/client/background.svg
new file mode 100644
index 0000000..b61f202
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/test/client/background.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
+  <circle stroke="#000000" r="5" cy="10" cx="10" stroke-width="0" fill="#FF0000" />
+</svg>