Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send deep link clicks to frontend app in Connect #33690

Merged
merged 7 commits into from
Oct 24, 2023

Conversation

ravicious
Copy link
Member

@ravicious ravicious commented Oct 19, 2023

#33637 set up Connect to make the OS recognize that it supports teleport:// links. #33639 made it so that the deep links are parsed. This PR sends the parsed result to the frontend app so that it can show the relevant UI.

I'm open to suggestions regarding naming and code organization – we haven't done something like this before, so a lot of the decisions behind naming and code organization are rather arbitrary.

Here's a fiddle with deep links you can use for testing. Remember that this will only work after you build a a packaged app and install it (yarn build-term && CONNECT_TSH_BIN_PATH=$PWD/build/tsh CSC_IDENTITY_AUTO_DISCOVERY=false yarn package-term).

Waiting for the frontend app

When the main process of Connect gets notified by the OS about the deep link click, the frontend app might not be initialized yet. This happens when the app wasn't running when the user clicked a deep link.

I needed to implement some kind of a waiting mechanism so that the renderer (which runs the frontend app) can notify the main process about the frontend app being ready. I took inspiration from Electron's app.whenReady. This function returns a promise which is resolved when Electron is initialized. I added WindowsManager.whenFrontendAppIsReady which resolves when the frontend app is ready. To accomplish this, I send a one-way message from the renderer to the main process, as explained in the official inter-process communication tutorial. We already use this method of communication for many other things within the app.

What it means for the frontend app to be ready

The frontend app is considered to be ready after AppContext.init as well as initUi resolve. This means that the frontend app won't be considered ready until the user goes through the telemetry modal shown on the very first launch of the app.

There's one problem though – if the user has opened some tabs and then closed the app, on next launch we show a modal asking if they want to restore the tabs. This is not considered to be a part of UI initialization process – that is because if you're logged into multiple root clusters ("workspaces"), we ask you about restoring tabs for this workspace only just before switching to it.

I'm going to address this caveat in the next PR which actually implements the in-app behavior of clicking on a Connect My Computer link.

@ravicious ravicious force-pushed the ravicious/deep-link-3-pass-to-frontend branch from d91f360 to c40171f Compare October 19, 2023 14:14
@ravicious ravicious force-pushed the ravicious/deep-link-2-main-process branch from d568d54 to 97eb577 Compare October 20, 2023 10:43
@ravicious ravicious force-pushed the ravicious/deep-link-3-pass-to-frontend branch from c40171f to 9a8c967 Compare October 20, 2023 10:43
Base automatically changed from ravicious/deep-link-2-main-process to master October 20, 2023 11:02
This way it's more clear which messages are sent from the renderer and
which ones are sent to the renderer.

The channels have also been renamed to include the recipient in the
name.
@ravicious ravicious force-pushed the ravicious/deep-link-3-pass-to-frontend branch from 9a8c967 to 418758f Compare October 20, 2023 12:46
Copy link
Contributor

@gzdunek gzdunek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really appreciate splitting the feature into small and focused PRs!

web/packages/teleterm/src/mainProcess/mainProcessClient.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@kimlisa kimlisa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can't pretend i 100% understood what was going on, but it looks good to me :)

web/packages/teleterm/src/mainProcess/windowsManager.ts Outdated Show resolved Hide resolved
web/packages/teleterm/src/mainProcess/windowsManager.ts Outdated Show resolved Hide resolved
@@ -356,4 +360,8 @@ function launchDeepLink(logger: Logger, rawUrl: string): void {

logger.error(`Skipping deep link launch, ${reason}`);
}

// Always pass the result to the frontend app so that the error can be shown to the user.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wanted to understand this better. given this snippet (i got from teleterm readme):

image

when you say frontend app, are you talking about the Teleterm UI (as show in image above)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly.

This is a typical Electron app architecture where the main process (main.ts) opens a new browser window (a new renderer process) which runs some privileged preload code that has access to Node.js APIs (preload.ts) as well as the actual frontend app (ui/boot.tsx). The code of the frontend app doesn't differ that much from a regular app, but the preload code can expose some Node.js APIs to the frontend app as properties defined on window.

For example, the gRPC client we use in Connect is actually a Node.js gRPC client running as a part of the frontend app. There are several limitations when it comes to interactions between the preload code and the frontend app code (because they run in different contexts) and between the main process and the renderer process (because they're separate OS processes).

web/packages/teleterm/src/mainProcess/mainProcessClient.ts Outdated Show resolved Hide resolved
web/packages/teleterm/src/ui/appContext.ts Outdated Show resolved Hide resolved
@ravicious
Copy link
Member Author

@gzdunek Could you double check the changes with IPC channel names?

@github-actions
Copy link

The PR changelog entry failed validation: Changelog entry not found in the PR body. Please add a "no-changelog" label to the PR, or changelog lines starting with changelog: followed by the changelog entries for the PR.

@ravicious ravicious added the no-changelog Indicates that a PR does not require a changelog entry label Oct 24, 2023
@ravicious ravicious added this pull request to the merge queue Oct 24, 2023
Merged via the queue into master with commit c081290 Oct 24, 2023
32 of 33 checks passed
@ravicious ravicious deleted the ravicious/deep-link-3-pass-to-frontend branch October 24, 2023 12:26
@public-teleport-github-review-bot

@ravicious See the table below for backport results.

Branch Result
branch/v14 Create PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/branch/v14 no-changelog Indicates that a PR does not require a changelog entry size/md ui
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants