/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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 com.vaadin.client.ui;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorMap;
import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
import com.vaadin.client.WidgetUtil;
import com.vaadin.shared.ui.embedded.EmbeddedConstants;
public class VEmbedded extends HTML {
public static String CLASSNAME = "v-embedded";
/** For internal use only. May be removed or replaced in the future. */
public Element browserElement;
/** For internal use only. May be removed or replaced in the future. */
public String type;
/** For internal use only. May be removed or replaced in the future. */
public String mimetype;
/** For internal use only. May be removed or replaced in the future. */
public ApplicationConnection client;
public VEmbedded() {
setStyleName(CLASSNAME);
}
/**
* Creates the Object and Embed tags for the Flash plugin so it works
* cross-browser.
* <p>
* For internal use only. May be removed or replaced in the future.
*
* @param uidl
* The UIDL
* @return Tags concatenated into a string
*/
public String createFlashEmbed(UIDL uidl) {
/*
* To ensure cross-browser compatibility we are using the twice-cooked
* method to embed flash i.e. we add a OBJECT tag for IE ActiveX and
* inside it a EMBED for all other browsers.
*/
StringBuilder html = new StringBuilder();
// Start the object tag
html.append("<object ");
/*
* Add classid required for ActiveX to recognize the flash. This is a
* predefined value which ActiveX recognizes and must be the given
* value. More info can be found on
* http://kb2.adobe.com/cps/415/tn_4150.html. Allow user to override
* this by setting his own classid.
*/
if (uidl.hasAttribute("classid")) {
html.append(
"classid=\""
+ WidgetUtil.escapeAttribute(
uidl.getStringAttribute("classid"))
+ "\" ");
} else {
html.append(
"classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" ");
}
/*
* Add codebase required for ActiveX and must be exactly this according
* to http://kb2.adobe.com/cps/415/tn_4150.html to work with the above
* given classid. Again, see more info on
* http://kb2.adobe.com/cps/415/tn_4150.html. Limiting Flash version to
* 6.0.0.0 and above. Allow user to override this by setting his own
* codebase
*/
if (uidl.hasAttribute("codebase")) {
html.append(
"codebase=\""
+ WidgetUtil.escapeAttribute(
uidl.getStringAttribute("codebase"))
+ "\" ");
} else {
html.append(
"codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" ");
}
ComponentConnector paintable = ConnectorMap.get(client)
.getConnector(this);
String height = paintable.getState().height;
String width = paintable.getState().width;
// Add width and height
html.append("width=\"" + WidgetUtil.escapeAttribute(width) + "\" ");
html.append("height=\"" + WidgetUtil.escapeAttribute(height) + "\" ");
html.append("type=\"application/x-shockwave-flash\" ");
// Codetype
if (uidl.hasAttribute("codetype")) {
html.append(
"codetype=\""
+ WidgetUtil.escapeAttribute(
uidl.getStringAttribute("codetype"))
+ "\" ");
}
// Standby
if (uidl.hasAttribute("standby")) {
html.append(
"standby=\""
+ WidgetUtil.escapeAttribute(
uidl.getStringAttribute("standby"))
+ "\" ");
}
// Archive
if (uidl.hasAttribute("archive")) {
html.append(
"archive=\""
+ WidgetUtil.escapeAttribute(
uidl.getStringAttribute("archive"))
+ "\" ");
}
// End object tag
html.append(">");
// Ensure we have an movie parameter
Map<String, String> parameters = getParameters(uidl);
if (parameters.get("movie") == null) {
parameters.put("movie", getSrc(uidl, client));
}
// Add parameters to OBJECT
for (String name : parameters.keySet()) {
html.append("<param ");
html.append("name=\"" + WidgetUtil.escapeAttribute(name) + "\" ");
html.append("value=\""
+ WidgetUtil.escapeAttribute(parameters.get(name)) + "\" ");
html.append("/>");
}
// Build inner EMBED tag
html.append("<embed ");
html.append("src=\"" + WidgetUtil.escapeAttribute(getSrc(uidl, client))
+ "\" ");
html.append("width=\"" + WidgetUtil.escapeAttribute(width) + "\" ");
html.append("height=\"" + WidgetUtil.escapeAttribute(height) + "\" ");
html.append("type=\"application/x-shockwave-flash\" ");
// Add the parameters to the Embed
for (String name : parameters.keySet()) {
html.append(WidgetUtil.escapeAttribute(name));
html.append("=");
html.append("\"" + WidgetUtil.escapeAttribute(parameters.get(name))
+ "\"");
}
// End embed tag
html.append("></embed>");
if (uidl.hasAttribute(EmbeddedConstants.ALTERNATE_TEXT)) {
html.append(
uidl.getStringAttribute(EmbeddedConstants.ALTERNATE_TEXT));
}
// End object tag
html.append("</object>");
return html.toString();
}
/**
* Returns a map (name -> value) of all parameters in the UIDL.
* <p>
* For internal use only. May be removed or replaced in the future.
*
* @param uidl
* @return
*/
public static Map<String, String> getParameters(UIDL uidl) {
Map<String, String> parameters = new HashMap<>();
Iterator<Object> childIterator = uidl.getChildIterator();
while (childIterator.hasNext()) {
Object child = childIterator.next();
if (child instanceof UIDL) {
UIDL childUIDL = (UIDL) child;
if (childUIDL.getTag().equals("embeddedparam")) {
String name = childUIDL.getStringAttribute("name");
String value = childUIDL.getStringAttribute("value");
parameters.put(name, value);
}
}
}
return parameters;
}
/**
* Helper to return translated src-attribute from embedded's UIDL
* <p>
* For internal use only. May be removed or replaced in the future.
*
* @param uidl
* @param client
* @return
*/
public String getSrc(UIDL uidl, ApplicationConnection client) {
String url = client.translateVaadinUri(uidl.getStringAttribute("src"));
if (url == null) {
return "";
}
return url;
}
@Override
protected void onDetach() {
if (BrowserInfo.get().isIE()) {
// Force browser to fire unload event when component is detached
// from the view (IE doesn't do this automatically)
if (browserElement != null) {
/*
* src was previously set to javascript:false, but this was not
* enough to overcome a bug when detaching an iframe with a pdf
* loaded in IE9. about:blank seems to cause the adobe reader
* plugin to unload properly before the iframe is removed. See
* #7855
*/
DOM.setElementAttribute(browserElement, "src", "about:blank");
}
}
super.onDetach();
}
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (DOM.eventGetType(event) == Event.ONLOAD) {
VConsole.log("Embeddable onload");
Util.notifyParentOfSizeChange(this, true);
}
}
}