Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBeat Schwarzentrub2021-05-06 14:07:25 +0000
committerBeat Schwarzentrub2021-05-06 17:03:45 +0000
commit700c717d6e03a13f535d2f0b858620fe69095c79 (patch)
tree07c88f35db25df9c1a3d89d134b0514de3b0da1e
parentc04f796d47624e95a512e2e8d081ef6e6c975da2 (diff)
downloadorg.eclipse.scout.rt-700c717d6e03a13f535d2f0b858620fe69095c79.tar.gz
org.eclipse.scout.rt-700c717d6e03a13f535d2f0b858620fe69095c79.tar.xz
org.eclipse.scout.rt-700c717d6e03a13f535d2f0b858620fe69095c79.zip
BrowserField: add method to send messages to the embedded page
- AbstractBrowserField#postMessage: Send data to an embedded page (iframe) - AbstractBrowserField#execPostMessage: Callback that preserves the original form of the received data, i.e. objects are converted to IDataObject instead of String. The previous method that converted everything to a String was removed with 22.0 (see release notes). - AbstractBrowserField#getConfiguredTrustedMessageOrigins: New property to specify valid origins. Messages from other origins are automatically filtered in the UI to prevent sending potentially malicious data to the server. The default value is an empty list, which essentially disables this filter (same behavior as before). 270605 Change-Id: I6de030d7af8589e2cba9982c378eea4dfa340d30 Reviewed-on: https://git.eclipse.org/r/c/scout/org.eclipse.scout.rt/+/180316 Tested-by: Scout Bot <scout-bot@eclipse.org> Reviewed-by: Beat Schwarzentrub <bsh@bsiag.com>
-rw-r--r--eclipse-scout-core/src/form/fields/browserfield/BrowserField.js16
-rw-r--r--eclipse-scout-core/src/form/fields/browserfield/BrowserFieldAdapter.js12
-rw-r--r--eclipse-scout-core/src/iframe/IFrame.js9
-rw-r--r--org.eclipse.scout.rt.client/pom.xml5
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/AbstractBrowserFieldExtension.java2
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/BrowserFieldChains.java2
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/IBrowserFieldExtension.java2
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java80
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java23
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java41
-rw-r--r--org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserFieldUIFacade.java2
-rw-r--r--org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserFieldTest.java22
-rw-r--r--org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java64
-rw-r--r--org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json4
14 files changed, 233 insertions, 51 deletions
diff --git a/eclipse-scout-core/src/form/fields/browserfield/BrowserField.js b/eclipse-scout-core/src/form/fields/browserfield/BrowserField.js
index f021236dc7..d817c18ed3 100644
--- a/eclipse-scout-core/src/form/fields/browserfield/BrowserField.js
+++ b/eclipse-scout-core/src/form/fields/browserfield/BrowserField.js
@@ -23,6 +23,7 @@ export default class BrowserField extends ValueField {
this.trackLocation = false;
this.sandboxEnabled = true;
this.sandboxPermissions = null;
+ this.trustedMessageOrigins = [];
this.scrollBarEnabled = true;
this.showInExternalWindow = false;
this._messageListener = null;
@@ -264,17 +265,28 @@ export default class BrowserField extends ValueField {
}
_onMessage(event) {
+ // Only handle event originating form "our" iframe
if (event.source !== this.$field[0].contentWindow) {
- $.log.isTraceEnabled() && $.log.trace('skipped post-message, because different source. data=' + event.data + ' origin=' + event.origin);
return;
}
- $.log.isDebugEnabled() && $.log.debug('received post-message data=' + event.data + ' origin=' + event.origin);
+ // Check if the origin is trusted before we do anything else with the data
+ if (this.trustedMessageOrigins && this.trustedMessageOrigins.length &&
+ !this.trustedMessageOrigins.some(origin => origin === event.origin)) {
+ $.log.warn('blocked message from untrusted origin ' + event.origin);
+ return;
+ }
+ $.log.isDebugEnabled() && $.log.debug('received post-message: data=' + event.data + ', origin=' + event.origin);
this.trigger('message', {
data: event.data,
origin: event.origin
});
}
+ postMessage(message, targetOrigin) {
+ $.log.isDebugEnabled() && $.log.debug('send post-message: message=' + message + ', targetOrigin=' + targetOrigin);
+ this.iframe && this.iframe.postMessage(message, targetOrigin);
+ }
+
setTrackLocation(trackLocation) {
this.setProperty('trackLocation', trackLocation);
this.iframe.setTrackLocation(trackLocation);
diff --git a/eclipse-scout-core/src/form/fields/browserfield/BrowserFieldAdapter.js b/eclipse-scout-core/src/form/fields/browserfield/BrowserFieldAdapter.js
index 2ef7b3ba19..8564cee5d9 100644
--- a/eclipse-scout-core/src/form/fields/browserfield/BrowserFieldAdapter.js
+++ b/eclipse-scout-core/src/form/fields/browserfield/BrowserFieldAdapter.js
@@ -40,6 +40,18 @@ export default class BrowserFieldAdapter extends ValueFieldAdapter {
}
}
+ _onModelPostMessage(event) {
+ this.widget.postMessage(event.message, event.targetOrigin);
+ }
+
+ onModelAction(event) {
+ if (event.type === 'postMessage') {
+ this._onModelPostMessage(event);
+ } else {
+ super.onModelAction(event);
+ }
+ }
+
_orderPropertyNamesOnSync(newProperties) {
// IE won't show scrollbars if the location is set before scrollBarEnabled is set to true.
// Rendering the location again after setting the scrollBarEnabled property as done in IFrame.js doesn't seem to work.
diff --git a/eclipse-scout-core/src/iframe/IFrame.js b/eclipse-scout-core/src/iframe/IFrame.js
index 4e05b7f34e..ef3a576f1a 100644
--- a/eclipse-scout-core/src/iframe/IFrame.js
+++ b/eclipse-scout-core/src/iframe/IFrame.js
@@ -28,7 +28,7 @@ export default class IFrame extends Widget {
}
_render() {
- var cssClass = 'iframe ' + Device.get().cssClassForIphone();
+ let cssClass = 'iframe ' + Device.get().cssClassForIphone();
if (this.wrapIframe) {
this.$container = this.$parent.appendDiv('iframe-wrapper');
this.$iframe = this.$container.appendElement('<iframe>', cssClass);
@@ -144,4 +144,11 @@ export default class IFrame extends Widget {
this._renderLocation();
}
}
+
+ postMessage(message, targetOrigin) {
+ if (!this.rendered) {
+ return;
+ }
+ this.$iframe[0].contentWindow.postMessage(message, targetOrigin);
+ }
}
diff --git a/org.eclipse.scout.rt.client/pom.xml b/org.eclipse.scout.rt.client/pom.xml
index 2812b4f5bf..22c1a30d39 100644
--- a/org.eclipse.scout.rt.client/pom.xml
+++ b/org.eclipse.scout.rt.client/pom.xml
@@ -36,5 +36,10 @@
<groupId>org.eclipse.scout.rt</groupId>
<artifactId>org.eclipse.scout.rt.shared</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.eclipse.scout.rt</groupId>
+ <artifactId>org.eclipse.scout.rt.dataobject</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/AbstractBrowserFieldExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/AbstractBrowserFieldExtension.java
index 0238ef402f..08061dd6e4 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/AbstractBrowserFieldExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/AbstractBrowserFieldExtension.java
@@ -22,7 +22,7 @@ public abstract class AbstractBrowserFieldExtension<OWNER extends AbstractBrowse
}
@Override
- public void execPostMessage(BrowserFieldPostMessageChain chain, String data, String origin) {
+ public void execPostMessage(BrowserFieldPostMessageChain chain, Object data, String origin) {
chain.execPostMessage(data, origin);
}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/BrowserFieldChains.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/BrowserFieldChains.java
index b1d4749c02..419a1a2133 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/BrowserFieldChains.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/BrowserFieldChains.java
@@ -35,7 +35,7 @@ public final class BrowserFieldChains {
super(extensions);
}
- public void execPostMessage(final String data, final String origin) {
+ public void execPostMessage(final Object data, final String origin) {
MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
@Override
protected void callMethod(IBrowserFieldExtension<? extends AbstractBrowserField> next) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/IBrowserFieldExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/IBrowserFieldExtension.java
index be37221248..c97a768900 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/IBrowserFieldExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/fields/browserfield/IBrowserFieldExtension.java
@@ -17,7 +17,7 @@ import org.eclipse.scout.rt.client.ui.form.fields.browserfield.AbstractBrowserFi
public interface IBrowserFieldExtension<OWNER extends AbstractBrowserField> extends IFormFieldExtension<OWNER> {
- void execPostMessage(BrowserFieldPostMessageChain chain, String data, String origin);
+ void execPostMessage(BrowserFieldPostMessageChain chain, Object data, String origin);
void execExternalWindowStateChanged(BrowserFieldExternalWindowStateChangedChain chain, boolean state);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
index 2f3d272bb2..cc456cca32 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
@@ -12,6 +12,7 @@ package org.eclipse.scout.rt.client.ui.form.fields.browserfield;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
@@ -27,6 +28,7 @@ import org.eclipse.scout.rt.client.extension.ui.form.fields.browserfield.Browser
import org.eclipse.scout.rt.client.extension.ui.form.fields.browserfield.BrowserFieldChains.BrowserFieldPostMessageChain;
import org.eclipse.scout.rt.client.extension.ui.form.fields.browserfield.IBrowserFieldExtension;
import org.eclipse.scout.rt.client.ui.form.fields.AbstractFormField;
+import org.eclipse.scout.rt.dataobject.IDataObject;
import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.Order;
import org.eclipse.scout.rt.platform.annotations.ConfigOperation;
@@ -92,6 +94,15 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
}
/**
+ * @return a list of origin URIs from which this field will receive messages posted via <i>postMessage</i>. If this is
+ * {@code null} or empty, messages from all origins are accepted. The default is empty.
+ * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">window.postMessage (MDN)</a>
+ */
+ protected List<String> getConfiguredTrustedMessageOrigins() {
+ return Collections.emptyList();
+ }
+
+ /**
* Configures the browser field general behavior. By default the content of the browser field is shown inline or in an
* inline container (e.g. an &lt;iframe&gt; for the HTML5 UI layer), some very specific web pages (e.g. using
* plug-ins, complex frames within the webpage) might not be displayed well or may even lead to a browser crash.
@@ -150,35 +161,36 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
}
/**
- * This callback is invoked when the application has received a post-message from the embedded browser (IFRAME) or
- * external window.
+ * This callback is invoked when the field has received a message from the embedded page ({@code iframe}) or external
+ * window.
* <p>
- * The default does nothing.
+ * The {@code data} can either be a {@link String}, a {@link Number}, a {@link Boolean} or an {@link IDataObject}.
* <p>
- * <b>Important:</b> this callback is only invoked when the IFRAME is not restricted by the sandbox property. You must
- * either disable sandbox completely ({@link #getConfiguredSandboxEnabled()} returns false) or grant the required
- * permissions ({@link SandboxPermission#AllowScripts}).
+ * If {@link #getTrustedMessageOrigins()} is set, the UI should already have checked that the sender is one of the
+ * trusted origins. However, for security reasons, the {@code origin} should be checked again here.
* <p>
- * Example java script call (for &lt;iframe&gt;):
- *
- * <pre>
- * window.parent.postMessage('hello application!', 'http://localhost:8082')
- * </pre>
+ * The default does nothing.
* <p>
- * Other example java script call (for external windows, does not work with all browsers):
- *
- * <pre>
- * window.opener.postMessage('hello application!', 'http://localhost:8082')
- * </pre>
+ * Possible reasons why this method is not called:
+ * <ul>
+ * <li>The embedded page use the wrong target {@code window}.
+ * <li>The browser blocked the message for some unknown reason (check the F12 developer console).
+ * <li>The sandbox is enabled and does not allow sending messages.
+ * <li>The embedded page specified the wrong {@code targetOrigin} when calling <i>postMessage</i>.
+ * <li>The sender origin does not match the list {@link #getTrustedMessageOrigins()}.
+ * <li>The browser field is disabled.
+ * </ul>
*
* @param data
+ * Message received from the {@code iframe}. Can be a {@link String}, a {@link Number}, a {@link Boolean} or
+ * an {@link IDataObject}
* @param origin
- * The origin of the window that sent the message at the time postMessage was called
- * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">Window.postMessage()</a>
+ * The origin of the window that sent the message.
+ * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">window.postMessage (MDN)</a>
*/
@ConfigOperation
- @Order(260)
- protected void execPostMessage(String data, String origin) {
+ @Order(261)
+ protected void execPostMessage(Object data, String origin) {
}
/**
@@ -202,6 +214,7 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
setScrollBarEnabled(getConfiguredScrollBarEnabled());
setSandboxEnabled(getConfiguredSandboxEnabled());
setSandboxPermissions(getConfiguredSandboxPermissions());
+ setTrustedMessageOrigins(getConfiguredTrustedMessageOrigins());
setShowInExternalWindow(getConfiguredShowInExternalWindow());
setExternalWindowButtonText(getConfiguredExternalWindowButtonText());
setExternalWindowFieldText(getConfiguredExternalWindowFieldText());
@@ -347,6 +360,17 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
return (Set<BinaryResource>) propertySupport.getProperty(PROP_ATTACHMENTS);
}
+ protected void firePostMessage(Object message, String targetOrigin) {
+ fireBrowserFieldEvent(new BrowserFieldEvent(this, BrowserFieldEvent.TYPE_POST_MESSAGE)
+ .withMessage(message)
+ .withTargetOrigin(targetOrigin));
+ }
+
+ @Override
+ public void postMessage(Object message, String targetOrigin) {
+ firePostMessage(message, targetOrigin);
+ }
+
@Override
public void setScrollBarEnabled(boolean scrollBarEnabled) {
propertySupport.setProperty(PROP_SCROLL_BAR_ENABLED, scrollBarEnabled);
@@ -392,6 +416,16 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
propertySupport.setProperty(PROP_SANDBOX_PERMISSIONS, sandboxPermission);
}
+ @Override
+ public List<String> getTrustedMessageOrigins() {
+ return propertySupport.getPropertyList(PROP_TRUSTED_MESSAGE_ORIGINS);
+ }
+
+ @Override
+ public void setTrustedMessageOrigins(List<String> trustedMessageOrigins) {
+ propertySupport.setPropertyList(PROP_TRUSTED_MESSAGE_ORIGINS, trustedMessageOrigins);
+ }
+
@SuppressWarnings("unchecked")
@Override
public EnumSet<SandboxPermission> getSandboxPermissions() {
@@ -456,7 +490,7 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
}
@Override
- public void firePostMessageFromUI(String data, String origin) {
+ public void firePostMessageFromUI(Object data, String origin) {
if (!isEnabledIncludingParents() || !isVisibleIncludingParents()) {
return;
}
@@ -474,7 +508,7 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
}
}
- protected final void interceptPostMessage(String data, String origin) {
+ protected final void interceptPostMessage(Object data, String origin) {
List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions();
BrowserFieldPostMessageChain chain = new BrowserFieldPostMessageChain(extensions);
chain.execPostMessage(data, origin);
@@ -493,7 +527,7 @@ public abstract class AbstractBrowserField extends AbstractFormField implements
}
@Override
- public void execPostMessage(BrowserFieldPostMessageChain chain, String data, String origin) {
+ public void execPostMessage(BrowserFieldPostMessageChain chain, Object data, String origin) {
getOwner().execPostMessage(data, origin);
}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
index 5f0993f51a..2cb75e20ac 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
@@ -18,10 +18,13 @@ import org.eclipse.scout.rt.client.ui.IModelEvent;
public class BrowserFieldEvent extends EventObject implements IModelEvent {
private static final long serialVersionUID = 1L;
- // state
+
public static final int TYPE_CONTENT_CHANGED = 900;
+ public static final int TYPE_POST_MESSAGE = 901;
private final int m_type;
+ private Object m_message;
+ private String m_targetOrigin;
public BrowserFieldEvent(IBrowserField browserField, int type) {
super(browserField);
@@ -37,6 +40,24 @@ public class BrowserFieldEvent extends EventObject implements IModelEvent {
return m_type;
}
+ public Object getMessage() {
+ return m_message;
+ }
+
+ public BrowserFieldEvent withMessage(Object message) {
+ m_message = message;
+ return this;
+ }
+
+ public String getTargetOrigin() {
+ return m_targetOrigin;
+ }
+
+ public BrowserFieldEvent withTargetOrigin(String targetOrigin) {
+ m_targetOrigin = targetOrigin;
+ return this;
+ }
+
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
index 4e7eaf365f..497c803d40 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
@@ -11,9 +11,11 @@
package org.eclipse.scout.rt.client.ui.form.fields.browserfield;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+import org.eclipse.scout.rt.dataobject.IDataObject;
import org.eclipse.scout.rt.platform.resource.BinaryResource;
import org.eclipse.scout.rt.platform.util.event.IFastListenerList;
@@ -63,6 +65,7 @@ public interface IBrowserField extends IFormField {
String PROP_SCROLL_BAR_ENABLED = "scrollBarEnabled";
String PROP_SANDBOX_ENABLED = "sandboxEnabled";
String PROP_SANDBOX_PERMISSIONS = "sandboxPermissions";
+ String PROP_TRUSTED_MESSAGE_ORIGINS = "trustedMessageOrigins";
String PROP_SHOW_IN_EXTERNAL_WINDOW = "showInExternalWindow";
String PROP_EXTERNAL_WINDOW_FIELD_TEXT = "externalWindowFieldText";
String PROP_EXTERNAL_WINDOW_BUTTON_TEXT = "externalWindowButtonText";
@@ -120,6 +123,21 @@ public interface IBrowserField extends IFormField {
*/
Set<BinaryResource> getAttachments();
+ /**
+ * Sends a message to the embedded web page ({@code iframe}).
+ *
+ * @param message
+ * The message to send. Can be a {@link String}, a {@link Number}, a {@link Boolean} or an
+ * {@link IDataObject}. All other objects are ignored.
+ * @param targetOrigin
+ * The expected origin of the receiving {@code window}. If the origin does not match, the browser will not
+ * dispatch the message for security reasons. See the
+ * <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">documentation</a> for
+ * details.
+ * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">window.postMessage (MDN)</a>
+ */
+ void postMessage(Object message, String targetOrigin);
+
void setScrollBarEnabled(boolean scrollBarEnabled);
boolean isScrollBarEnabled();
@@ -178,6 +196,21 @@ public interface IBrowserField extends IFormField {
EnumSet<SandboxPermission> getSandboxPermissions();
/**
+ * @return a list of origin URIs from which this field will receive messages posted via <i>postMessage</i>. If this is
+ * {@code null} or empty, messages from all origins are accepted.
+ * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">window.postMessage (MDN)</a>
+ */
+ List<String> getTrustedMessageOrigins();
+
+ /**
+ * @param trustedMessageOrigins
+ * A list of origin URIs from which this field will receive messages posted via <i>postMessage</i>. If this
+ * is {@code null} or empty, messages from all origins are accepted.
+ * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">window.postMessage (MDN)</a>
+ */
+ void setTrustedMessageOrigins(List<String> trustedMessageOrigins);
+
+ /**
* Configures the browser field general behavior. By default the content of the browser field is shown inline or in an
* inline container (e.g. an &lt;iframe&gt; for the HTML5 UI layer), some very specific web pages (e.g. using
* plug-ins, complex frames within the webpage) might not be displayed well or may even lead to a browser crash.
@@ -188,9 +221,9 @@ public interface IBrowserField extends IFormField {
* <p>
* Property can only be changed during initialization, it can not be changed during runtime.
*
- * @param <code>false</code>
- * to disable &lt;iframe&gt; usage, <code>true</code> otherwise.
- * @see #isShowContentInIFrameEnabled()
+ * @param showInExternalWindow
+ * <code>false</code> to disable &lt;iframe&gt; usage, <code>true</code> otherwise.
+ * @see #isShowInExternalWindow()
*/
void setShowInExternalWindow(boolean showInExternalWindow);
@@ -198,7 +231,7 @@ public interface IBrowserField extends IFormField {
* Returns whether content should be shown inline.
*
* @return <code>false</code> to disable &lt;iframe&gt; usage, <code>true</code> otherwise.
- * @see #setShowContentInIFrameEnabled(boolean)
+ * @see #setShowInExternalWindow(boolean)
*/
boolean isShowInExternalWindow();
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserFieldUIFacade.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserFieldUIFacade.java
index 602fe39431..869958580f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserFieldUIFacade.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserFieldUIFacade.java
@@ -16,7 +16,7 @@ public interface IBrowserFieldUIFacade {
void firePostExternalWindowStateFromUI(boolean windowState);
- void firePostMessageFromUI(String data, String origin);
+ void firePostMessageFromUI(Object data, String origin);
BinaryResource requestBinaryResourceFromUI(String filename);
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserFieldTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserFieldTest.java
index 3cd2820527..d399c456ac 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserFieldTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserFieldTest.java
@@ -31,28 +31,24 @@ import org.junit.runner.RunWith;
*/
@RunWith(PlatformTestRunner.class)
public class JsonBrowserFieldTest extends BaseFormFieldTest {
- /**
- * <ul>
- * <li>0: origin</li>
- * <li>1: data</li>
- * </ul>
- */
- private String[] m_lastPostMessage;
+
+ private Object m_lastPostMessageData;
+ private String m_lastPostMessageOrigin;
private Boolean m_lastExternalWindowState;
private AbstractBrowserField m_model = new AbstractBrowserField() {
@Override
- protected void execPostMessage(String data, String origin) {
- m_lastPostMessage = new String[]{origin, data};
+ protected void execPostMessage(Object data, String origin) {
+ m_lastPostMessageData = data;
+ m_lastPostMessageOrigin = origin;
}
@Override
protected void execExternalWindowStateChanged(boolean windowState) {
m_lastExternalWindowState = windowState;
}
-
};
private JsonBrowserField<IBrowserField> m_browserField = new JsonBrowserField<>(m_model, m_session, m_session.createUniqueId(), new JsonAdapterMock());
@@ -75,9 +71,8 @@ public class JsonBrowserFieldTest extends BaseFormFieldTest {
map.put("origin", origin);
map.put("data", data);
m_browserField.handleUiEvent(new JsonEvent("xyz", "postMessage", new JSONObject(map)));
- Assert.assertNotNull(m_lastPostMessage);
- Assert.assertEquals(origin, m_lastPostMessage[0]);
- Assert.assertEquals(data, m_lastPostMessage[1]);
+ Assert.assertEquals(data, m_lastPostMessageData);
+ Assert.assertEquals(origin, m_lastPostMessageOrigin);
}
@Test
@@ -89,5 +84,4 @@ public class JsonBrowserFieldTest extends BaseFormFieldTest {
Assert.assertNotNull(m_lastExternalWindowState);
Assert.assertEquals(true, m_lastExternalWindowState);
}
-
}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
index e946af8dd8..fdc9e157cd 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
@@ -10,6 +10,8 @@
*/
package org.eclipse.scout.rt.ui.html.json.form.fields.browserfield;
+import java.util.Collection;
+import java.util.List;
import java.util.Set;
import org.eclipse.scout.rt.client.job.ModelJobs;
@@ -17,6 +19,10 @@ import org.eclipse.scout.rt.client.ui.form.fields.browserfield.BrowserFieldEvent
import org.eclipse.scout.rt.client.ui.form.fields.browserfield.BrowserFieldListener;
import org.eclipse.scout.rt.client.ui.form.fields.browserfield.IBrowserField;
import org.eclipse.scout.rt.client.ui.form.fields.browserfield.IBrowserField.SandboxPermission;
+import org.eclipse.scout.rt.dataobject.DoList;
+import org.eclipse.scout.rt.dataobject.IDataObject;
+import org.eclipse.scout.rt.dataobject.IDataObjectMapper;
+import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.resource.BinaryResource;
import org.eclipse.scout.rt.ui.html.IUiSession;
import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
@@ -26,6 +32,7 @@ import org.eclipse.scout.rt.ui.html.json.form.fields.JsonFormField;
import org.eclipse.scout.rt.ui.html.res.BinaryResourceHolder;
import org.eclipse.scout.rt.ui.html.res.BinaryResourceUrlUtility;
import org.eclipse.scout.rt.ui.html.res.IBinaryResourceProvider;
+import org.json.JSONArray;
import org.json.JSONObject;
public class JsonBrowserField<BROWSER_FIELD extends IBrowserField> extends JsonFormField<BROWSER_FIELD> implements IBinaryResourceProvider {
@@ -81,6 +88,20 @@ public class JsonBrowserField<BROWSER_FIELD extends IBrowserField> extends JsonF
return sb.toString();
}
});
+ putJsonProperty(new JsonProperty<IBrowserField>(IBrowserField.PROP_TRUSTED_MESSAGE_ORIGINS, model) {
+ @Override
+ protected List<String> modelValue() {
+ return getModel().getTrustedMessageOrigins();
+ }
+
+ @Override
+ public Object prepareValueForToJson(Object value) {
+ if (value == null) {
+ return JSONObject.NULL;
+ }
+ return new JSONArray((Collection<?>) value); // Do NOT remove the cast! It is required to use the correct constructor.
+ }
+ });
putJsonProperty(new JsonProperty<IBrowserField>(IBrowserField.PROP_SHOW_IN_EXTERNAL_WINDOW, model) {
@Override
protected Boolean modelValue() {
@@ -151,10 +172,39 @@ public class JsonBrowserField<BROWSER_FIELD extends IBrowserField> extends JsonF
addPropertyChangeEvent(IBrowserField.PROP_LOCATION, getLocation());
}
+ protected void handleModelPostMessage(Object message, String targetOrigin) {
+ JSONObject eventData = new JSONObject();
+ eventData.put("message", messageToJson(message));
+ eventData.put("targetOrigin", targetOrigin);
+ addActionEvent(EVENT_POST_MESSAGE, eventData);
+ }
+
+ protected Object messageToJson(Object message) {
+ if (message == null) {
+ return JSONObject.NULL;
+ }
+ if (message instanceof IDataObject) {
+ IDataObjectMapper mapper = BEANS.get(IDataObjectMapper.class);
+ String str = mapper.writeValue(message);
+ if (message instanceof DoList) {
+ return new JSONArray(str);
+ }
+ return new JSONObject(str);
+ }
+ if (message instanceof String || message instanceof Number || message instanceof Boolean) {
+ return message;
+ }
+ // Unsupported (subclasses may override this method to change that)
+ throw new IllegalArgumentException("Unsupported message type: " + message);
+ }
+
protected void handleModelBrowserFieldEvent(BrowserFieldEvent event) {
if (BrowserFieldEvent.TYPE_CONTENT_CHANGED == event.getType()) {
handleModelContentChanged();
}
+ else if (BrowserFieldEvent.TYPE_POST_MESSAGE == event.getType()) {
+ handleModelPostMessage(event.getMessage(), event.getTargetOrigin());
+ }
}
@Override
@@ -187,8 +237,20 @@ public class JsonBrowserField<BROWSER_FIELD extends IBrowserField> extends JsonF
}
protected void handleUiPostMessage(JsonEvent event) {
- String data = event.getData().optString("data", null);
+ Object data = event.getData().opt("data");
String origin = event.getData().optString("origin", null);
+
+ // Support for arbitrary objects (optional support, requires object mapper implementation)
+ if (data instanceof JSONObject || data instanceof JSONArray) {
+ // Convert "org.json" object to IDataObject
+ IDataObjectMapper mapper = BEANS.opt(IDataObjectMapper.class);
+ if (mapper != null) {
+ data = mapper.readValue(data.toString(), IDataObject.class);
+ }
+ else {
+ data = data.toString();
+ }
+ }
getModel().getUIFacade().firePostMessageFromUI(data, origin);
}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
index 7b8463e284..fa8a154799 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
@@ -354,7 +354,9 @@
"autoCloseExternalWindow": false,
"sandboxEnabled": true,
"scrollBarEnabled": false,
- "showInExternalWindow": false
+ "showInExternalWindow": false,
+ "trustedMessageOrigins": [],
+ "trackLocation": false
},
"BeanField": {
"preventInitialFocus": true

Back to the top