From 0aa5543397a1a65b04f9cba11a1e9be0406342ea Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Wed, 17 Apr 2024 11:14:33 +0100 Subject: [PATCH] Let AppConnection know if its target app uses the Puter SDK Apps are not required to use the Puter SDK. If they don't, then we can still launch them, close them, and listen to their close event, but are unable to send messages to them. --- packages/puter-js/src/modules/UI.js | 20 +++++++++++++++++--- src/IPC.js | 12 +----------- src/helpers.js | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/puter-js/src/modules/UI.js b/packages/puter-js/src/modules/UI.js index 849d4cad..abfd43c2 100644 --- a/packages/puter-js/src/modules/UI.js +++ b/packages/puter-js/src/modules/UI.js @@ -14,7 +14,11 @@ class AppConnection extends EventListener { // Whether the target app is open #isOpen; - constructor(messageTarget, appInstanceID, targetAppInstanceID) { + // Whether the target app uses the Puter SDK, and so accepts messages + // (Closing and close events will still function.) + #usesSDK; + + constructor(messageTarget, appInstanceID, targetAppInstanceID, usesSDK) { super([ 'message', // The target sent us something with postMessage() 'close', // The target app was closed @@ -23,6 +27,7 @@ class AppConnection extends EventListener { this.appInstanceID = appInstanceID; this.targetAppInstanceID = targetAppInstanceID; this.#isOpen = true; + this.#usesSDK = usesSDK; // TODO: Set this.#puterOrigin to the puter origin @@ -54,12 +59,21 @@ class AppConnection extends EventListener { }); } + // Does the target app use the Puter SDK? If not, certain features will be unavailable. + get usesSDK() { return this.#usesSDK; } + + // Send a message to the target app. Requires the target to use the Puter SDK. postMessage(message) { if (!this.#isOpen) { console.warn('Trying to post message on a closed AppConnection'); return; } + if (!this.#usesSDK) { + console.warn('Trying to post message to a non-SDK app'); + return; + } + this.messageTarget.postMessage({ msg: 'messageToApp', appInstanceID: this.appInstanceID, @@ -155,7 +169,7 @@ class UI extends EventListener { } if (this.parentInstanceID) { - this.#parentAppConnection = new AppConnection(this.messageTarget, this.appInstanceID, this.parentInstanceID); + this.#parentAppConnection = new AppConnection(this.messageTarget, this.appInstanceID, this.parentInstanceID, true); } // Tell the host environment that this app is using the Puter SDK and is ready to receive messages, @@ -374,7 +388,7 @@ class UI extends EventListener { } else if (e.data.msg === 'childAppLaunched') { // execute callback with a new AppConnection to the child - const connection = new AppConnection(this.messageTarget, this.appInstanceID, e.data.child_instance_id); + const connection = new AppConnection(this.messageTarget, this.appInstanceID, e.data.child_instance_id, e.data.uses_sdk); this.#callbackFunctions[e.data.original_msg_id](connection); } else{ diff --git a/src/IPC.js b/src/IPC.js index dbe18eb1..6e9b4cc3 100644 --- a/src/IPC.js +++ b/src/IPC.js @@ -90,17 +90,7 @@ window.addEventListener('message', async (event) => { $(target_iframe).attr('data-appUsesSDK', 'true'); // If we were waiting to launch this as a child app, report to the parent that it succeeded. - const child_launch_callback = window.child_launch_callbacks[event.data.appInstanceID]; - if (child_launch_callback) { - const parent_iframe = iframe_for_app_instance(child_launch_callback.parent_instance_id); - // send confirmation to requester window - parent_iframe.contentWindow.postMessage({ - msg: 'childAppLaunched', - original_msg_id: child_launch_callback.launch_msg_id, - child_instance_id: event.data.appInstanceID, - }, '*'); - delete window.child_launch_callbacks[event.data.appInstanceID]; - } + window.report_app_launched(event.data.appInstanceID, { uses_sdk: true }); // Send any saved broadcasts to the new app globalThis.services.get('broadcast').sendSavedBroadcastsTo(event.data.appInstanceID); diff --git a/src/helpers.js b/src/helpers.js index 5c0ff66a..1273bb2b 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -3523,3 +3523,19 @@ window.window_for_app_instance = (instance_id) => { window.iframe_for_app_instance = (instance_id) => { return $(window_for_app_instance(instance_id)).find('.window-app-iframe').get(0); }; + +// Run any callbacks to say that the app has launched +window.report_app_launched = (instance_id, { uses_sdk = true }) => { + const child_launch_callback = window.child_launch_callbacks[instance_id]; + if (child_launch_callback) { + const parent_iframe = iframe_for_app_instance(child_launch_callback.parent_instance_id); + // send confirmation to requester window + parent_iframe.contentWindow.postMessage({ + msg: 'childAppLaunched', + original_msg_id: child_launch_callback.launch_msg_id, + child_instance_id: instance_id, + uses_sdk: uses_sdk, + }, '*'); + delete window.child_launch_callbacks[instance_id]; + } +}