From 09c2d899ac90ecb6d0cfb00aaadf3136ff635ae8 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 19 Jul 2019 19:04:48 +0100 Subject: [PATCH] Defer IM token until widget is shown and permission granted This defers the work to request the IM token when displaying a widget until after we know that widget will actually be shown and the user has granted permission for this widget to be displayed. This is useful in general to avoid making unnecessary token checks, but it's particularly helpful with the new Terms API, so that we only show the Terms flow when widget are actually being used (as opposed to entering the room where widgets exist, but haven't been shown / permitted). Part of https://github.com/vector-im/riot-web/issues/10088 --- src/components/views/elements/AppTile.js | 54 +++++++++++++++--------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 034a3318a5..b0639ff1fe 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -139,7 +139,10 @@ export default class AppTile extends React.Component { } componentWillMount() { - this.setScalarToken(); + // Only fetch IM token on mount if we're showing and have permission to load + if (this.props.show && this.state.hasPermissionToLoad) { + this.setScalarToken(); + } } componentDidMount() { @@ -164,8 +167,6 @@ export default class AppTile extends React.Component { * Component initialisation is only complete when this function has resolved */ setScalarToken() { - this.setState({initialising: true}); - if (!WidgetUtils.isScalarUrl(this.props.url)) { console.warn('Non-scalar widget, not setting scalar token!', url); this.setState({ @@ -214,11 +215,20 @@ export default class AppTile extends React.Component { componentWillReceiveProps(nextProps) { if (nextProps.url !== this.props.url) { this._getNewState(nextProps); - this.setScalarToken(); - } else if (nextProps.show && !this.props.show && this.props.waitForIframeLoad) { - this.setState({ - loading: true, - }); + // Fetch IM token for new URL if we're showing and have permission to load + if (this.props.show && this.state.hasPermissionToLoad) { + this.setScalarToken(); + } + } else if (nextProps.show && !this.props.show) { + if (this.props.waitForIframeLoad) { + this.setState({ + loading: true, + }); + } + // Fetch IM token now that we're showing if we already have permission to load + if (this.state.hasPermissionToLoad) { + this.setScalarToken(); + } } else if (nextProps.widgetPageTitle !== this.props.widgetPageTitle) { this.setState({ widgetPageTitle: nextProps.widgetPageTitle, @@ -410,6 +420,8 @@ export default class AppTile extends React.Component { console.warn('Granting permission to load widget - ', this.state.widgetUrl); localStorage.setItem(this.state.widgetPermissionId, true); this.setState({hasPermissionToLoad: true}); + // Now that we have permission, fetch the IM token + this.setScalarToken(); } _revokeWidgetPermission() { @@ -525,13 +537,24 @@ export default class AppTile extends React.Component { ); - if (this.state.initialising) { + if (!this.state.hasPermissionToLoad) { + const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId); + appTileBody = ( +
+ +
+ ); + } else if (this.state.initialising) { appTileBody = (
{ loadingElement }
); - } else if (this.state.hasPermissionToLoad == true) { + } else { if (this.isMixedContent()) { appTileBody = (
@@ -571,17 +594,6 @@ export default class AppTile extends React.Component {
; } } - } else { - const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId); - appTileBody = ( -
- -
- ); } }