You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2011/03/25 16:54:37 UTC

svn commit: r1085433 - in /shindig/trunk: config/ java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/render/ java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ java/gadgets/src/test/jav...

Author: lindner
Date: Fri Mar 25 15:54:36 2011
New Revision: 1085433

URL: http://svn.apache.org/viewvc?rev=1085433&view=rev
Log:
SHINDIG-1504 | patch from Matthew Marum | Removing Quirks mode default

Modified:
    shindig/trunk/config/container.js
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriter.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java
    shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriterTest.java

Modified: shindig/trunk/config/container.js
URL: http://svn.apache.org/viewvc/shindig/trunk/config/container.js?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/config/container.js (original)
+++ shindig/trunk/config/container.js Fri Mar 25 15:54:36 2011
@@ -108,6 +108,12 @@
 // Authority (host:port without scheme) for the proxy and concat servlets.
 "defaultShindigProxyConcatAuthority": "${SERVER_HOST}:${SERVER_PORT}",
 
+// OS 2.0 Gadget DOCTYPE: used in Gadgets with @specificationVersion 2.0 or greater and
+// quirksmode on Gadget has not been set.
+"gadgets.doctype_qname" : "HTML",  //HTML5 doctype
+"gadgets.doctype_pubid" : "",
+"gadgets.doctype_sysid" : "",
+
 // Default Uri config: these must be overridden - specified here for testing purposes
 "gadgets.uri.iframe.unlockedDomain": "${Cur['defaultShindigTestHost']}",
 "gadgets.uri.iframe.lockedDomainSuffix": "${Cur['defaultShindigTestHost']}",

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java Fri Mar 25 15:54:36 2011
@@ -17,7 +17,7 @@
  */
 package org.apache.shindig.gadgets;
 
-import com.google.common.base.Preconditions;
+import org.apache.shindig.common.util.OpenSocialVersion;
 import org.apache.shindig.gadgets.features.FeatureRegistry;
 import org.apache.shindig.gadgets.preload.PreloadedData;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
@@ -25,6 +25,7 @@ import org.apache.shindig.gadgets.spec.L
 import org.apache.shindig.gadgets.spec.View;
 import org.apache.shindig.gadgets.uri.UriCommon;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
@@ -33,6 +34,8 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
+
+
 /**
  * Intermediary representation of all state associated with processing
  * of a single gadget request.
@@ -78,6 +81,31 @@ public class Gadget {
   public GadgetSpec getSpec() {
     return spec;
   }
+  
+  /**
+   * Returns open social specification version for this Gadget 
+   * @return Version for this Gadget
+   */
+  public OpenSocialVersion getSpecificationVersion(){
+    if(spec != null){
+      return spec.getSpecificationVersion();
+    }
+    return null;
+  }
+  
+  /**
+   * Returns if the doctype attribute is set to quirksmode.  
+   * Needed to override default OpenSocial 2.0 behavior which is to render in standards mode,
+   * may not be possible to honor this attribute when inlining (caja)
+   * 
+   * @return TRUE if this Gadget should be rendered in browser quirks mode
+   */
+  public boolean useQuirksMode(){
+    if(spec != null){
+      return GadgetSpec.DOCTYPE_QUIRKSMODE.equals(spec.getModulePrefs().getDoctype());
+    }
+    return false;
+  }
 
   /**
    * @param preloads The preloads for the gadget that is being processed.

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriter.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriter.java?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriter.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriter.java Fri Mar 25 15:54:36 2011
@@ -18,7 +18,7 @@
  */
 package org.apache.shindig.gadgets.render;
 
-import com.google.common.base.Splitter;
+import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.common.JsonSerializer;
 import org.apache.shindig.common.logging.i18n.MessageKeys;
 import org.apache.shindig.common.uri.Uri;
@@ -43,8 +43,8 @@ import org.apache.shindig.gadgets.spec.U
 import org.apache.shindig.gadgets.spec.View;
 import org.apache.shindig.gadgets.uri.JsUriManager;
 import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
-import org.apache.commons.lang.StringUtils;
 import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.Text;
@@ -56,6 +56,7 @@ import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Lists;
@@ -93,6 +94,9 @@ public class RenderingGadgetRewriter imp
       "body{margin: 0px;padding: 0px;background-color:white;}";
   static final String IS_GADGET_BEACON = "window['__isgadget']=true;";
   static final String INSERT_BASE_ELEMENT_KEY = "gadgets.insertBaseElement";
+  static final String REWRITE_DOCTYPE_QNAME = "gadgets.doctype_qname";
+  static final String REWRITE_DOCTYPE_PUBID = "gadgets.doctype_pubid";
+  static final String REWRITE_DOCTYPE_SYSID = "gadgets.doctype_sysid";
   static final String FEATURES_KEY = "gadgets.features";
 
   protected final MessageBundleFactory messageBundleFactory;
@@ -106,6 +110,11 @@ public class RenderingGadgetRewriter imp
 
   protected Boolean externalizeFeatures = false;
 
+  //DOCTYPE for HTML5, OpenSocial 2.0 default
+  private String defaultDoctypeQName = "html";
+  private String defaultDoctypePubId = null;
+  private String defaultDoctypeSysId = null;
+
   /**
    * @param messageBundleFactory Used for injecting message bundles into gadget output.
    */
@@ -121,6 +130,18 @@ public class RenderingGadgetRewriter imp
     this.jsUriManager = jsUriManager;
     this.configContributors = configContributors;
   }
+  
+  public void setDefaultDoctypeQName(String qname) {
+      this.defaultDoctypeQName = qname;
+  }
+  
+  public void setDefaultDoctypePubId( String pubid) {
+      this.defaultDoctypePubId = pubid;
+  }
+  
+  public void setDefaultDoctypeSysId( String sysid) {
+    this.defaultDoctypeSysId = sysid;
+  }
 
   @Inject
   public void setDefaultForcedLibs(@Named("shindig.gadget-rewrite.default-forced-libs")String forcedLibs) {
@@ -143,7 +164,7 @@ public class RenderingGadgetRewriter imp
     try {
       Document document = mutableContent.getDocument();
 
-      Element head = (Element)DomUtil.getFirstNamedChildNode(document.getDocumentElement(), "head");
+      Element head = (Element) DomUtil.getFirstNamedChildNode(document.getDocumentElement(), "head");
 
       // Insert new content before any of the existing children of the head element
       Node firstHeadChild = head.getFirstChild();
@@ -156,6 +177,36 @@ public class RenderingGadgetRewriter imp
         defaultStyle.appendChild(defaultStyle.getOwnerDocument().
             createTextNode(DEFAULT_CSS));
       }
+      // Override & insert DocType if Gadget is written for OpenSocial 2.0 or greater, 
+      // if quirksmode is not set
+      if(gadget.getSpecificationVersion().isEqualOrGreaterThan("2.0.0")
+          && !gadget.useQuirksMode()){
+        String container = gadget.getContext().getContainer();
+        String doctype_qname = defaultDoctypeQName;
+        String doctype_sysid = defaultDoctypeSysId;
+        String doctype_pubid = defaultDoctypePubId;
+        String value = containerConfig.getString(container, REWRITE_DOCTYPE_QNAME);
+        if(value != null){
+          doctype_qname = value;
+        }
+        value = containerConfig.getString(container, REWRITE_DOCTYPE_SYSID);
+        if(value != null){
+          doctype_sysid = value;
+        }
+        value = containerConfig.getString(container, REWRITE_DOCTYPE_PUBID);
+        if(value != null){
+          doctype_pubid = value;
+        }
+        //Don't inject DOCTYPE if QName is null
+        if(doctype_qname != null){
+          DocumentType docTypeNode = document.getImplementation()
+              .createDocumentType(doctype_qname, doctype_pubid, doctype_sysid);
+          if(document.getDoctype() != null){
+            document.removeChild(document.getDoctype());
+          }
+          document.insertBefore(docTypeNode, document.getFirstChild());
+        }
+      }
 
       injectBaseTag(gadget, head);
       injectGadgetBeacon(gadget, head, firstHeadChild);

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java Fri Mar 25 15:54:36 2011
@@ -21,10 +21,12 @@ import com.google.common.annotations.Vis
 import com.google.common.base.Splitter;
 import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.util.HashUtil;
+import org.apache.shindig.common.util.OpenSocialVersion;
 import org.apache.shindig.common.xml.XmlUtil;
 import org.apache.shindig.gadgets.spec.View.ContentType;
 import org.apache.shindig.gadgets.variables.Substitutions;
 
+
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.MapMaker;
@@ -47,6 +49,9 @@ public class GadgetSpec {
   public static final String DEFAULT_VIEW = "default";
   public static final Locale DEFAULT_LOCALE = new Locale("all", "ALL");
 
+  private static final String ATTR_SPECIFICATION_VERSION = "specificationVersion";
+  public static final String DOCTYPE_QUIRKSMODE = "quirksmode";
+
   /**
    * Creates a new Module from the given xml input.
    *
@@ -63,6 +68,8 @@ public class GadgetSpec {
     this.checksum = HashUtil.checksum(original.getBytes());
 
     NodeList children = doc.getChildNodes();
+    //Save specification version of this Gadget
+    setAttribute(ATTR_SPECIFICATION_VERSION,doc.getAttribute(ATTR_SPECIFICATION_VERSION));
 
     ModulePrefs modulePrefs = null;
     Map<String,UserPref> prefsBuilder = Maps.newHashMap();
@@ -137,6 +144,20 @@ public class GadgetSpec {
     checksum = spec.checksum;
     attributes.putAll(spec.attributes);
   }
+  
+  /**
+   * Returns this Gadget's specification version.  Defaults to 1.0 if attribute not set.
+   * @return Version value as String
+   */
+  public OpenSocialVersion getSpecificationVersion(){
+    // 1.0 is default if unspecified as defined in Section 7 of OS 1.1 Core Gadget specification
+    String value = (String)attributes.get(ATTR_SPECIFICATION_VERSION);
+    if (value == null) {
+      return new OpenSocialVersion("1.0");
+    } else {
+      return new OpenSocialVersion(value);
+    }
+  }
 
   /**
    * The url for this gadget spec.
@@ -161,6 +182,7 @@ public class GadgetSpec {
   public ModulePrefs getModulePrefs() {
     return modulePrefs;
   }
+  
 
   /**
    * UserPref

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java Fri Mar 25 15:54:36 2011
@@ -77,6 +77,7 @@ public class ModulePrefs {
   private static final String ATTR_SINGLETON = "singleton";
   private static final String ATTR_SCALING = "scaling";
   private static final String ATTR_SCROLLING = "scrolling";
+  private static final String ATTR_DOCTYPE = "doctype";
   private static final String ATTR_WIDTH = "width";
   private static final String ATTR_HEIGHT = "height";
   private static final String ATTR_CATEGORY = "category";
@@ -342,6 +343,15 @@ public class ModulePrefs {
   public int getHeight() {
     return getIntAttribute(ATTR_HEIGHT);
   }
+  
+  /**
+   * Returns this Gadget's doctype mode.  If null, we will use default mode.
+   * 
+   * @return Value of doctype attribute
+   */
+  public String getDoctype(){
+    return getAttribute(ATTR_DOCTYPE);
+  }
 
   /**
    * @param name the attribute name

Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriterTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriterTest.java?rev=1085433&r1=1085432&r2=1085433&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriterTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingGadgetRewriterTest.java Fri Mar 25 15:54:36 2011
@@ -90,6 +90,10 @@ public class RenderingGadgetRewriterTest
   static final Pattern DOCUMENT_SPLIT_PATTERN = Pattern.compile(
       "(.*)<head>(.*?)<\\/head>(?:.*)<body(.*?)>(.*?)<\\/body>(?:.*)", Pattern.DOTALL |
       Pattern.CASE_INSENSITIVE);
+  private static final String CUSTOM_DOCTYPE = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">";
+  private static final String CUSTOM_DOCTYPE_QNAME = "html";
+  private static final String CUSTOM_DOCTYPE_PUBID = "-//W3C//DTD HTML 4.01 Transitional//EN";
+  private static final String CUSTOM_DOCTYPE_SYSID = "http://www.w3.org/TR/html4/loose.dtd";
 
   static final int BEFORE_HEAD_GROUP = 1;
   static final int HEAD_GROUP = 2;
@@ -138,6 +142,11 @@ public class RenderingGadgetRewriterTest
     String defaultXml = "<Module><ModulePrefs title=''/><Content type='html'/></Module>";
     return makeGadgetWithSpec(defaultXml);
   }
+  
+  private Gadget makeDefaultOpenSocial2Gadget(boolean useQuirks) throws GadgetException {
+    String defaultXml = "<Module specificationVersion='2' ><ModulePrefs " + (useQuirks ? "doctype='quirksmode'" : "") +" title=''/><Content type='html'/></Module>";
+    return makeGadgetWithSpec(defaultXml);
+  }
 
   private String rewrite(Gadget gadget, String content) throws Exception {
     MutableContent mc = new MutableContent(parser, content);
@@ -164,6 +173,63 @@ public class RenderingGadgetRewriterTest
     assertTrue("gadgets.util.runOnLoadHandlers not invoked.",
         matcher.group(BODY_GROUP).contains("gadgets.util.runOnLoadHandlers();"));
   }
+  
+  @Test
+  public void overrideDefaultDoctype() throws Exception{
+    Gadget gadget = makeDefaultOpenSocial2Gadget(false);
+    String body = "hello, world.";
+    String doc = new StringBuilder()
+        .append("<html><head>")
+        .append("</head><body>")
+        .append(body)
+        .append("</body></html>")
+        .toString();
+
+    rewriter.setDefaultDoctypeQName(CUSTOM_DOCTYPE_QNAME);
+    rewriter.setDefaultDoctypePubId(CUSTOM_DOCTYPE_PUBID);
+    rewriter.setDefaultDoctypeSysId(CUSTOM_DOCTYPE_SYSID);
+    String rewritten = rewrite(gadget, doc);
+    
+    Matcher matcher = DOCUMENT_SPLIT_PATTERN.matcher(rewritten);
+    assertTrue("Output is not valid HTML.", matcher.matches());
+    assertTrue("DOCTYPE not preserved", matcher.group(BEFORE_HEAD_GROUP).contains(CUSTOM_DOCTYPE));
+    
+  }
+  
+  @Test
+  public void quirksmodeInOS2() throws Exception{
+    Gadget gadget = makeDefaultOpenSocial2Gadget(true);
+    String body = "hello, world.";
+    String doc = new StringBuilder()
+        .append("<html><head>")
+        .append("</head><body>")
+        .append(body)
+        .append("</body></html>")
+        .toString();
+
+    String rewritten = rewrite(gadget, doc);
+    
+    Matcher matcher = DOCUMENT_SPLIT_PATTERN.matcher(rewritten);
+    assertTrue("Output is not valid HTML.", matcher.matches());
+    assertTrue("Should not include doctype, this will default to quirksmode (old Shindig behavior)", !matcher.group(BEFORE_HEAD_GROUP).contains("<!DOCTYPE"));
+ 
+    gadget = makeDefaultOpenSocial2Gadget(true);
+    String docType = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">";
+    doc = new StringBuilder()
+        .append(docType)
+        .append("<html><head>")
+        .append("</head><body>")
+        .append(body)
+        .append("</body></html>")
+        .toString();   
+    rewritten = rewrite(gadget, doc);
+    
+    matcher = DOCUMENT_SPLIT_PATTERN.matcher(rewritten);
+    assertTrue("Output is not valid HTML.", matcher.matches());
+    assertTrue("Should include doctype, when in quirksmode we should use pre OS2.0 Shindig behavior.", matcher.group(BEFORE_HEAD_GROUP).contains(docType));
+ 
+
+  }
 
   @Test
   public void completeDocument() throws Exception {
@@ -221,6 +287,45 @@ public class RenderingGadgetRewriterTest
 
     // Skipping other tests; code path should be the same for the rest.
   }
+  
+  @Test
+  public void completeDocumentOpenSocial2() throws Exception {
+    String head = "<script src=\"foo.js\"></script><style type=\"text/css\">body{color:red;}</style>";
+    String bodyAttr = " onload=\"foo();\"";
+    String body = "hello, world.";
+    String doc = new StringBuilder()
+        .append("<html><head>")
+        .append(head)
+        .append("</head><body").append(bodyAttr).append('>')
+        .append(body)
+        .append("</body></html>")
+        .toString();
+
+    GadgetContext context = new GadgetContext() {
+      @Override
+      public String getParameter(String name) {
+        if (name.equals("libs")) {
+          return "foo";
+        }
+        return null;
+      }
+    };
+
+    Gadget gadget = makeDefaultOpenSocial2Gadget(false)
+        .setContext(context);
+    expectFeatureCalls(gadget,
+        ImmutableList.<FeatureResource>of(),
+        ImmutableSet.of("foo"),
+        ImmutableList.of(inline("blah", "n/a")));
+
+    String rewritten = rewrite(gadget, doc);
+
+    Matcher matcher = DOCUMENT_SPLIT_PATTERN.matcher(rewritten);
+    assertTrue("Output is not valid HTML.", matcher.matches());
+    assertTrue("Doctype should have been rewritten to HTML5", matcher.group(BEFORE_HEAD_GROUP).contains("<!DOCTYPE html>"));
+
+    // Skipping other tests; code path should be the same for the rest.
+  }
 
   @Test
   public void bidiSettings() throws Exception {