-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Conversation
d91f360
to
c40171f
Compare
d568d54
to
97eb577
Compare
c40171f
to
9a8c967
Compare
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.
9a8c967
to
418758f
Compare
There was a problem hiding this 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!
There was a problem hiding this 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 :)
@@ -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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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).
@gzdunek Could you double check the changes with IPC channel names? |
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 |
@ravicious See the table below for backport results.
|
#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 addedWindowsManager.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 asinitUi
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.