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

electron: use inversify in main process #7964

Merged
merged 1 commit into from
Aug 7, 2020
Merged

Conversation

paul-marechal
Copy link
Member

@paul-marechal paul-marechal commented Jun 4, 2020

Closes #3364
Closes #7406
Closes #7964

Combined work with @kittaakos.

What it does

This PR contributes a JSON-RPC communication scheme between the electron-main process and the renderer processes. It is reusing the same architecture as the websocket-based connection between frontend/backend, but adapted to work over electron's ipc apis. Currently there isn't scoped connections, meaning that each renderer process will interact with the same singleton in the electron-main process, but for the current use-cases this is sufficient.

How to test

To verify:

  • yarn --cwd ./examples/electron start -> Should open previous workspace, if any. Otherwise, opens a no-workspace app.
  • yarn --cwd ./examples/electron start ~/Desktop/ -> Opens your app with a workspace to the Desktop.
  • yarn --cwd ./examples/electron start ../.. -> Opens the app to with Theia as the workspace.
  • yarn --cwd ./examples/electron start path/to/missing -> Opens the app without a workspace. See log: Could not resolve the workspace path.
  • mkdir ~/Desktop/path\ with\ space && yarn --cwd ./examples/electron start ~/Desktop/path\ with\ space -> Open the app with the desired workspace. The workspace contains spaces in the FS path.

  • Check updater sample
  • Check File > Settings > Check for Update... -> You will see, there are no updates.
  • Execute the Electron Updater Sample: Mock - Available command and wait a bit.
  • You should receive a notification, about new updates. Click on yes, the electron-main process should print something to the backend console.
  • Refresh the browser window, you should see Disposed a sample updater client. AND Registered a new sample updater client.
  • Open a second workspace, you should see Registered a new sample updater client.. Close the new window, you should see Disposed a sample updater client.

Review checklist

Reminder for reviewers

@paul-marechal paul-marechal requested a review from akosyakov June 4, 2020 15:03
@paul-marechal paul-marechal added electron issues related to the electron target extensibility issues to simplify ability to extend Theia extension system issues related to the extension system labels Jun 4, 2020
@paul-marechal
Copy link
Member Author

@akosyakov here is Electron to use inversify.

This commit adds the bare minimum required to run Electron, as well as a communication scheme between frontend and electron main process (via IpcMain and IpcRenderer Electron APIs).

No communication is happening between electron main process and the backend process at the moment. My concern in that regard is that the backend heavily pollutes its stdout/stderr, so I am not really sure it would be possible to use those streams for IPC. But I also don't see a use for such a communication right now?

@kittaakos kittaakos self-requested a review June 4, 2020 16:09
@paul-marechal
Copy link
Member Author

Are we waiting for #7968 before considering this PR?

@kittaakos
Copy link
Contributor

Are we waiting for #7968 before considering this PR?

Yes, please. Of course, if you have a very good reason, we can start with this, but first, it should be marked as ready for the review.

As for the verification, I want to extend the APIs you have created and want to add support for the electron-updater, if that is feasible, we can be sure the electron-main customization is sufficient in Theia. Thoughts?

@paul-marechal
Copy link
Member Author

paul-marechal commented Jun 11, 2020

Of course, if you have a very good reason, we can start with this, but first, it should be marked as ready for the review.

I just want either you or Anton to go over the new contributions points and messaging utilities to make sure the design is ok. I didn't want to get crazy with a design that would be refused. If the current approach is fine with you, I can clean the PR and mark it as ready for final review.

As for the verification, I want to extend the APIs you have created and want to add support for the electron-updater, if that is feasible, we can be sure the electron-main customization is sufficient in Theia.

I am sorry, I don't understand what you mean. Are you asking if you will be able to add support for electron-updater using the new APIs? Or are you asking to add such support in this PR?

@kittaakos
Copy link
Contributor

I am sorry, I don't understand what you mean. Are you asking if you will be able to add support for electron-updater using the new APIs?

Yes.

Or are you asking to add such support in this PR?

No no, it's out of context.

@paul-marechal
Copy link
Member Author

paul-marechal commented Jun 11, 2020

Hm, I am not familiar with what using electron-updater implies to do, so I cannot tell. Let me look.

@paul-marechal
Copy link
Member Author

paul-marechal commented Jun 11, 2020

@kittaakos I don't see anything that would prevent it, as it seems it doesn't require changes to the Electron main process logic to work. Correct me if I am wrong.

@kittaakos
Copy link
Contributor

Let me look.

You do not have to, just if you're interested.

Here is an example, I want to see the notifications about new updates, do you want to install and so on in the Theia notification center, and not some native dialogs. So that's why your change is super important. Without injection, it is not possible.

@paul-marechal
Copy link
Member Author

Here is an example

From that example, it seems like you will be able to nicely use it after this patch.

Copy link
Contributor

@kittaakos kittaakos left a comment

Choose a reason for hiding this comment

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

I added a few comments. I am going to start with the integration and see how it works. What I definitely miss is the electron application as an argument to the start, stop, and hookApplicationEvents methods. Let me check how well does the API work during the integration.

packages/electron/package.json Outdated Show resolved Hide resolved
packages/electron/src/common/electron-window-protocol.ts Outdated Show resolved Hide resolved
packages/electron/src/electron-main/delete.electron-cli.ts Outdated Show resolved Hide resolved
packages/electron/src/electron-main/delete.tmp.js Outdated Show resolved Hide resolved
@kittaakos
Copy link
Contributor

kittaakos commented Jun 12, 2020

When I start the electron app as usual (yarn --cwd ./examples/electron start) I see the following error notification and no workspace is opened:

Screen Shot 2020-06-12 at 11 56 33

Edit:

  • Then I set a workspace,
  • Stopped the app,
  • Started the app,
  • Had the same error notification, no workspace was opened.

@kittaakos
Copy link
Contributor

I am experiencing #6499 again. If I refresh the browser window, the onDidCloseConnection is not called.

@kittaakos
Copy link
Contributor

kittaakos commented Jun 12, 2020

@marechal-p, please help me with this. I have tried to add a new extension that contributes to the new electronMain extension-point. I made the following changes, rebuilt everything, but nothing happens when I start the app. What am I doing wrong?

examples/electron-api-samples/package.json:

...
  "dependencies": {
    "@theia/core": "^1.2.0",
    "@theia/electron": "^1.2.0"
  },
  "theiaExtensions": [
    {
      "electronMain": "lib/electron-main/update/electron-updater-module"
    }
  ],
...

examples/electron-api-samples/src/electron-main/update/electron-updater-module.ts:

import { ContainerModule } from 'inversify';
import { ElectronApplicationContribution } from '@theia/electron/lib/electron-main/electron-application';
import { ElectronUpdaterContribution } from './electron-updater-contribution';

export default new ContainerModule(bind => {
    bind(ElectronApplicationContribution).to(ElectronUpdaterContribution).inSingletonScope();
});

examples/electron-api-samples/src/electron-main/update/electron-updater-contribution.ts:

import { injectable } from 'inversify';
import { ElectronApplicationContribution } from '@theia/electron/lib/electron-main/electron-application';

@injectable()
export class ElectronUpdaterContribution implements ElectronApplicationContribution {

    async start(): Promise<void> {
        console.log('start');
    }

    async stop(): Promise<void> {
        console.log('stop');
    }

}

And in the example/electron/package.json, I made this change:

diff --git a/examples/electron/package.json b/examples/electron/package.json
index e2dddb190..405bbf2b1 100644
--- a/examples/electron/package.json
+++ b/examples/electron/package.json
@@ -22,6 +22,7 @@
     "@theia/editor": "^1.2.0",
     "@theia/editor-preview": "^1.2.0",
     "@theia/electron": "^1.2.0",
+    "@theia/electron-api-samples": "^1.2.0",
     "@theia/file-search": "^1.2.0",
     "@theia/filesystem": "^1.2.0",
     "@theia/getting-started": "^1.2.0",

I pushed the code to https://github.com/eclipse-theia/theia/compare/electron-updater-example

@paul-marechal paul-marechal force-pushed the mp/electron-main branch 3 times, most recently from b3a027c to d4ebff3 Compare June 16, 2020 19:54
@paul-marechal
Copy link
Member Author

@kittaakos thank you very much for the review, it's encouraging! I still need to investigate the issues you reported about the connection not being closed, as well as why contributions are not picked up.

@kittaakos
Copy link
Contributor

well as why contributions are not picked up.

I am not sure if this is an issue with the changeset, or I misunderstood something.

👍 The PR looks very promising, let me know if you need someone to try it out again.

@kittaakos
Copy link
Contributor

I am going to rebase this from the master after #7968.

It's done. I have verified the electron-main contributions and the dummy updater. It was OK.

@paul-marechal
Copy link
Member Author

I'm ok with the current changes, let's get this merged right after the release? I'll need someone to approve since I cannot do it on my own PRs :)

@kittaakos
Copy link
Contributor

I'm ok with the current changes, let's get this merged right after the release?

I totally agree. Let's schedule another review after 30.7.

I'll need someone to approve since I cannot do it on my own PRs :)

Same for me. 😄

@kittaakos
Copy link
Contributor

@marechal-p, do you have time to update this PR from the master? I want to merge it ASAP. If you don't have time, I can make the required changes later today. Thank you!

@kittaakos
Copy link
Contributor

I can make the required changes later today.

I am going to take care of the update.

@kittaakos
Copy link
Contributor

I did the update:

  • resolved the version conflicts and
  • adjusted the changelog.

I gave the app another try on macOS with Node.js v12.14.1:

  • I verified the lifecycle of the new electronMain contribution: I checked how they behave (onStart and onStop) when the window open/close/refresh happens.
  • I tried the dummy electron updater sample. It worked.
  • I also checked the basic TS functionality with the browser example after a successful rebuild:browser command. It worked fine.

I reviewed @marechal-p's contribution several times by drafting the following PRs:

Here is another one:

The changes from the PRs as mentioned above had been merged back to here.

Here is another review from Windows env. Thanks a lot for your help, @mcgordonite 👍

I am going to leave this PR open for another few days then I'll merge it without further notice. Let me know if anyone has any concerns.

@paul-marechal
Copy link
Member Author

Just tested on Windows that we can launch the Electron app and open new windows. There was a bug where the maximized state was not applied back, I just pushed the fix for it.

@kittaakos
Copy link
Contributor

There was a bug where the maximized state was not applied back, I just pushed the fix for it.

Thanks for the heads-up and the fix, @marechal-p. I did not know we planned to change it. What about these:

const persistedWindowOptionsAdditions = electronStore.get('windowOptions', {});
const windowOptionsAdditions = {
...defaultWindowOptionsAdditions,
...persistedWindowOptionsAdditions
};

I could not find the corresponding logic in the new code. Did we just lose the Added ability to change windowOptions & it's defaults feature?

@paul-marechal
Copy link
Member Author

paul-marechal commented Aug 5, 2020

@kittaakos the mechanism for changing default options is simply different now: One has to rebind the ElectronMainApplication component and override the getDefaultBrowserWindowOptions method. cc @owlJaeger

(It was also one of the reason why this refactoring was needed: the old mechanism was waiting for the frontend to send a message back to the electron main process in order to drive it, now you can directly add the logic within)

@paul-marechal
Copy link
Member Author

paul-marechal commented Aug 5, 2020

@kittaakos at the very least I added back the window options coming from the package.json configuration field. When I first started the PR a lot of patches were not merged so these things must have slept through, my bad.

@kittaakos
Copy link
Contributor

@kittaakos the mechanism for changing default options is simply different now: One has to rebind the ElectronMainApplication component and override the getDefaultBrowserWindowOptions method. cc @owlJaeger

We cannot break existing behavior. It was not even mentioned anywhere.

  • ElectronFrontendApplicationConfig#windowOptions still an existing prop and ignored.

is simply different now

No. It is not simply different. A downstream Theia consumer could define window properties at build time in the package.json. With this change, if one wants to ship two apps, two extensions are required. With this PR the windows config becomes a runtime thing.

Could you please make this PR compliment with the master? Let's change one thing in the PR: support injection in the electron-main. Do you have time to do it, or should I do the revert?

@paul-marechal
Copy link
Member Author

paul-marechal commented Aug 5, 2020

A downstream Theia consumer could define window properties at build time in the package.json.

This has been brought back.

ipcMain.on('set-window-options', (event, options) => {
electronStore.set('windowOptions', options);
});
ipcMain.on('get-persisted-window-options-additions', event => {
event.returnValue = electronStore.get('windowOptions', {});
});

@kittaakos regarding the workaround IPC code, is it ok in this case to make this breaking change? When I mentioned getting rid of it to @owlJaeger that made the PR to introduce it he seemed favorable to the idea. I think that it would be better to get rid of workarounds.

@kittaakos
Copy link
Contributor

is it ok

I do not mind, but you have to ask the community.

@owlJaeger
Copy link
Contributor

owlJaeger commented Aug 5, 2020

regarding the workaround IPC code, is it ok in this case to make this breaking change?

I do not mind it breaking the currently used workarounds. I am looking forward to switching to the extensible solution by rebinding ElectronMainApplication as it should yield all the needed functionality the workarounds were providing. 👍

@kittaakos
Copy link
Contributor

kittaakos commented Aug 6, 2020

We have a conflict again. I am going to make another rebase and merge it tomorrow.

Update: it's done.

All the logic for the electron main process currently has to be added to
our generators, making it hard to extend without committing to Theia.

This commit re-arranges the way Electron is launched to allow people to
more easily change the behavior of their application.

Add a basic CLI to open a workspace by doing `app path/to/workspace`.

CLI can be overriden by application makers by extending and rebinding
`ElectronApplication.launch` and handling yourself the
`ExecutionParams`.

Added a dummy electron-updater sample.

Breaking-Change: Removed the `set-window-options` and
`get-persisted-window-options-additions` Electron IPC handlers from the
Electron Main process.

Signed-off-by: Paul Maréchal <paul.marechal@ericsson.com>
Co-Authored-By: Akos Kitta <kittaakos@typefox.io>
@kittaakos kittaakos self-requested a review August 7, 2020 13:35
Copy link
Contributor

@kittaakos kittaakos left a comment

Choose a reason for hiding this comment

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

Thank you for all of you helping with this PR. Special thanks to @marechal-p for initiating this change.

If you discover any regressions, please file a bug and name me. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
electron issues related to the electron target extensibility issues to simplify ability to extend Theia extension system issues related to the extension system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

electron: provide a customizable entry-point [Feature] Hook into electron main master process
4 participants