/** * Copyright 2010 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. * */ package org.waveprotocol.box.server.rpc.render.web.text; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.wave.api.Gadget; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.http.HttpServletRequest; /** * Render gadget iframes from Elements. * * @author David Byttow */ public class GadgetRendererImpl implements GadgetRenderer { private static final Set<String> NON_STATE_PROPERTIES = ImmutableSet.of("author", "url"); private final Provider<HttpServletRequest> requestProvider; private final AtomicInteger nextId = new AtomicInteger(0); @Inject public GadgetRendererImpl(Provider<HttpServletRequest> requestProvider) { this.requestProvider = requestProvider; } /* (non-Javadoc) * @see org.waveprotocol.box.server.rpc.render.web.text.GadgetRenderer#render(com.google.wave.api.Gadget, java.util.List, java.lang.StringBuilder) */ @Override public void render(Gadget gadget, List<String> contributors, StringBuilder builder) { String id = "g" + nextId.incrementAndGet(); String parentUrl = requestProvider.get().getRequestURL().toString(); appendState(gadget, id, contributors, builder); builder.append("<iframe class=\"gadget\" " + "id=\"").append(id).append("\" " + "name=\"").append(id).append("\" " + "width=\"100%\" height=\"1px\" ") .append("frameBorder=\"no\" scrolling=\"no\" src=\"" + "http://www.gmodules.com/gadgets/ifr?container=wave&view=default&debug=0&" + "lang=en&country=ALL&nocache=0&wave=1") .append("&mid=").append(id) .append("&parent=").append(Markup.sanitizeAndEncode(parentUrl)) .append("&url=").append(Markup.sanitizeAndEncode(gadget.getUrl())) .append("\"/>"); } private void appendState(Gadget gadget, String id, List<String> contributors, StringBuilder builder) { String output = ""; builder.append("<div class=\"invisible\" id=\"") .append(id) .append("_state\">"); for (Map.Entry<String, String> entry : gadget.getProperties().entrySet()) { if (NON_STATE_PROPERTIES.contains(entry.getKey())) { continue; } renderStateValue("gadget-state", entry.getKey(), entry.getValue(), builder); } for (String participantId : contributors) { renderStateValue("gadget-participant", null, participantId, builder); } renderStateValue("gadget-author", null, gadget.getProperties().get("author"), builder); builder.append("</div>"); } private void renderStateValue(String className, String key, String value, StringBuilder builder) { // TODO: Is this kosher? Should we encode this data in // another way? builder.append("<span class=\"") .append(className) .append("\""); if (key != null) { builder.append(" hiddenKey=\"") .append(Markup.sanitize(key)) .append('"'); } builder.append(">"); if (value != null) { builder.append(Markup.sanitize(value)); } builder.append("</span>"); } }