From 5bb29e99ba276b295cbd6ebd660145944e8d30e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 23 Jul 2021 23:06:59 +0200 Subject: [PATCH] Adding a "allowApi" property to authorize the API in a website. --- docs/maps/website-in-map.md | 16 ++++++++++++++++ front/src/Phaser/Game/GameScene.ts | 13 +++++++++++++ front/src/Phaser/Map/PropertyUtils.ts | 17 +++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/docs/maps/website-in-map.md b/docs/maps/website-in-map.md index 849a30e0..7c7f8025 100644 --- a/docs/maps/website-in-map.md +++ b/docs/maps/website-in-map.md @@ -22,3 +22,19 @@ The `url` can be absolute, or relative to your map. Internally, WorkAdventure will create an "iFrame" to load the website. Some websites forbid being opened by iframes using the [`X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) HTTP header. + +{.alert.alert-warning} +Please note that the website always appears **on top** of the tiles (even if you put the object layer that +contains the "website" object under the tiles). + +## Allowing the scripting API in your iframe + +If you are planning to use the WorkAdventure scripting API inside your iframe, you need +to explicitly allow it, by setting an additional `allowApi` property to `true`. + +
+
+ +
A "website" object that can communicate using the Iframe API
+
+
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 596fcc58..8f33d8e5 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -200,6 +200,7 @@ export class GameScene extends DirtyScene { private startPositionCalculator!: StartPositionCalculator; private sharedVariablesManager!: SharedVariablesManager; private objectsByType = new Map(); + private inMapIframes = new Array(); constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) { super({ @@ -497,6 +498,15 @@ export class GameScene extends DirtyScene { iframe.style.border = "none"; this.add.dom(object.x, object.y).setElement(iframe).setOrigin(0, 0); + + const allowApi = PropertyUtils.findBooleanProperty( + "allowApi", + object.properties, + ); + if (allowApi) { + iframeListener.registerIframe(iframe); + this.inMapIframes.push(iframe); + } } } } @@ -1293,6 +1303,9 @@ ${escapedMessage} for (const script of scripts) { iframeListener.unregisterScript(script); } + for (const iframe of this.inMapIframes) { + iframeListener.unregisterIframe(iframe); + } this.stopJitsi(); audioManager.unloadAudio(); diff --git a/front/src/Phaser/Map/PropertyUtils.ts b/front/src/Phaser/Map/PropertyUtils.ts index a23ef269..b9aff8d7 100644 --- a/front/src/Phaser/Map/PropertyUtils.ts +++ b/front/src/Phaser/Map/PropertyUtils.ts @@ -8,6 +8,23 @@ export class PropertyUtils { return properties?.find((property) => property.name === name)?.value; } + public static findBooleanProperty( + name: string, + properties: ITiledMapProperty[] | undefined, + context?: string + ): boolean | undefined { + const property = PropertyUtils.findProperty(name, properties); + if (property === undefined) { + return undefined; + } + if (typeof property !== "boolean") { + throw new Error( + 'Expected property "' + name + '" to be a boolean. ' + (context ? " (" + context + ")" : "") + ); + } + return property; + } + public static mustFindProperty( name: string, properties: ITiledMapProperty[] | undefined,