diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index 5c254bbd00..29eb3cb8be 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -145,13 +145,34 @@ const onSecretRequested = async function({ console.log(`CrossSigningManager: Ignoring request from untrusted device ${deviceId}`); return; } - const callbacks = client.getCrossSigningCacheCallbacks(); - if (!callbacks.getCrossSigningKeyCache) return; - if (name === "m.cross_signing.self_signing") { - const key = await callbacks.getCrossSigningKeyCache("self_signing"); - return key && encodeBase64(key); - } else if (name === "m.cross_signing.user_signing") { - const key = await callbacks.getCrossSigningKeyCache("user_signing"); + if (name.startsWith("m.cross_signing")) { + const callbacks = client.getCrossSigningCacheCallbacks(); + if (!callbacks.getCrossSigningKeyCache) return; + /* Explicit enumeration here is deliberate – never share the master key! */ + if (name === "m.cross_signing.self_signing") { + const key = await callbacks.getCrossSigningKeyCache("self_signing"); + if (!key) { + console.log( + `self_signing requested by ${deviceId}, but not found in cache`, + ); + } + return key && encodeBase64(key); + } else if (name === "m.cross_signing.user_signing") { + const key = await callbacks.getCrossSigningKeyCache("user_signing"); + if (!key) { + console.log( + `user_signing requested by ${deviceId}, but not found in cache`, + ); + } + return key && encodeBase64(key); + } + } else if (name === "m.megolm_backup.v1") { + const key = await client._crypto.getSessionBackupPrivateKey(); + if (!key) { + console.log( + `session backup key requested by ${deviceId}, but not found in cache`, + ); + } return key && encodeBase64(key); } console.warn("onSecretRequested didn't recognise the secret named ", name); diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js index 64caba0fdf..ea76c85643 100644 --- a/src/FromWidgetPostMessageApi.js +++ b/src/FromWidgetPostMessageApi.js @@ -24,6 +24,8 @@ import {MatrixClientPeg} from "./MatrixClientPeg"; import RoomViewStore from "./stores/RoomViewStore"; import {IntegrationManagers} from "./integrations/IntegrationManagers"; import SettingsStore from "./settings/SettingsStore"; +import {Capability, KnownWidgetActions} from "./widgets/WidgetApi"; +import SdkConfig from "./SdkConfig"; const WIDGET_API_VERSION = '0.0.2'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -213,11 +215,18 @@ export default class FromWidgetPostMessageApi { const data = event.data.data; const val = data.value; - if (ActiveWidgetStore.widgetHasCapability(widgetId, 'm.always_on_screen')) { + if (ActiveWidgetStore.widgetHasCapability(widgetId, Capability.AlwaysOnScreen)) { ActiveWidgetStore.setWidgetPersistence(widgetId, val); } } else if (action === 'get_openid') { // Handled by caller + } else if (action === KnownWidgetActions.GetRiotWebConfig) { + if (ActiveWidgetStore.widgetHasCapability(widgetId, Capability.GetRiotWebConfig)) { + this.sendResponse(event, { + api: INBOUND_API_NAME, + config: SdkConfig.get(), + }); + } } else { console.warn('Widget postMessage event unhandled'); this.sendError(event, {message: 'The postMessage was unhandled'}); diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index d40a8ab637..30c2389b1e 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -27,6 +27,7 @@ import {MatrixClientPeg} from "./MatrixClientPeg"; import SettingsStore from "./settings/SettingsStore"; import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog"; import WidgetUtils from "./utils/WidgetUtils"; +import {KnownWidgetActions} from "./widgets/WidgetApi"; if (!global.mxFromWidgetMessaging) { global.mxFromWidgetMessaging = new FromWidgetPostMessageApi(); @@ -75,6 +76,17 @@ export default class WidgetMessaging { }); } + /** + * Tells the widget that the client is ready to handle further widget requests. + * @returns {Promise<*>} Resolves after the widget has acknowledged the ready message. + */ + flagReadyToContinue() { + return this.messageToWidget({ + api: OUTBOUND_API_NAME, + action: KnownWidgetActions.ClientReady, + }); + } + /** * Request a screenshot from a widget * @return {Promise} To be resolved with screenshot data when it has been generated diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index a26478c461..0a8bf7443b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -419,6 +419,12 @@ export default class AppTile extends React.Component { if (this.props.onCapabilityRequest) { this.props.onCapabilityRequest(requestedCapabilities); } + + // We only tell Jitsi widgets that we're ready because they're realistically the only ones + // using this custom extension to the widget API. + if (this.props.type === 'jitsi') { + widgetMessaging.flagReadyToContinue(); + } }).catch((err) => { console.log(`Failed to get capabilities for widget type ${this.props.type}`, this.props.id, err); }); diff --git a/src/components/views/settings/CrossSigningPanel.js b/src/components/views/settings/CrossSigningPanel.js index cf47c797fc..b960434ca1 100644 --- a/src/components/views/settings/CrossSigningPanel.js +++ b/src/components/views/settings/CrossSigningPanel.js @@ -32,6 +32,8 @@ export default class CrossSigningPanel extends React.PureComponent { error: null, crossSigningPublicKeysOnDevice: false, crossSigningPrivateKeysInStorage: false, + selfSigningPrivateKeyCached: false, + userSigningPrivateKeyCached: false, secretStorageKeyInAccount: false, secretStorageKeyNeedsUpgrade: null, }; @@ -71,10 +73,13 @@ export default class CrossSigningPanel extends React.PureComponent { async _getUpdatedStatus() { const cli = MatrixClientPeg.get(); + const pkCache = cli.getCrossSigningCacheCallbacks(); const crossSigning = cli._crypto._crossSigningInfo; const secretStorage = cli._crypto._secretStorage; const crossSigningPublicKeysOnDevice = crossSigning.getId(); const crossSigningPrivateKeysInStorage = await crossSigning.isStoredInSecretStorage(secretStorage); + const selfSigningPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("self_signing")); + const userSigningPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("user_signing")); const secretStorageKeyInAccount = await secretStorage.hasKey(); const homeserverSupportsCrossSigning = await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"); @@ -84,6 +89,8 @@ export default class CrossSigningPanel extends React.PureComponent { this.setState({ crossSigningPublicKeysOnDevice, crossSigningPrivateKeysInStorage, + selfSigningPrivateKeyCached, + userSigningPrivateKeyCached, secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, @@ -130,6 +137,8 @@ export default class CrossSigningPanel extends React.PureComponent { error, crossSigningPublicKeysOnDevice, crossSigningPrivateKeysInStorage, + selfSigningPrivateKeyCached, + userSigningPrivateKeyCached, secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, @@ -209,6 +218,14 @@ export default class CrossSigningPanel extends React.PureComponent {