As part of our future plans, at Dashlane we want to improve the user experience on Windows. As we always try to raise the bar, we would like to reach more people, and to do so we want to be on the Microsoft store.

Our Windows application is Dashlane’s oldest, and was ready for a facelift. Given that our app had some legacy code that would require too much work to make it compliant for the Windows Store, we decided it was best to create a new app.

As exciting as it can sound, this new project comes with great responsibilities: provide a new platform that can satisfy (almost) everyone.

  1. Our customers: providing a safe tool that they can trust to store passwords and sensitive information.
  2. Our Windows developers: having a new technology which is easy and fun to work on.
  3. Our product team: enable faster iterations, and offer a modern user experience.
  4. Our engineering team: allow us to share code and skills across platforms.

Our Android team is moving to Kotlin. iOS is converging with macOS team in Swift. On Windows we had no strict requirement to move to a native technology, such as WPF. On the other hand, our Web Product team recently developed the web extension in Java Script and React, so we decided to explore technologies that could help increase synergies with their project. The first one we explored is the Electron Framework.

What is Electron?

If you don’t already know about it, Electron is a framework released in 2013 by GitHub which allows you to create Desktop apps with Web technologies. With that, you can easily create a cross-platform application with components which were created for a web use: your website becomes (almost) instantaneously a desktop application! It is widely used with more than 400 applications built on this framework, including Visual Studio Code, Discord, and Slack.

How does it work?

There are two parts in the Electron framework: the back-end and the front-end.

While the back-end simply relies on NodeJS, the front end uses Chromium to display the web page. Chromium is an open-source browser and the base of several other browsers such as Google Chrome. With this, we can use any web technology to display the user interface: HTML, CSS, JS, React… I’m not going to go through all technical details here, there are already a lot of articles about it out there.

Since we basically deal with a browser, it makes it really easy to transpose your existing web application in Electron: the most difficult part is adapting the back-end to NodeJS.

Prototyping with Electron?

We set ourselves two goals for this prototype: running our web application on desktop (whether Linux or Windows), and be able to call a native library from this application.  

Web app in desktop

The idea behind this goal was to see how much work was necessary to transpose our web application in a Desktop context. And the answer is: very little work 😊. In a matter of days, we succeeded to have a working application on Linux (even though Linux is not a targeted platform).

Of course, there were still some bugs, and some features were unavailable, but you could log onto your account and access your passwords. This demonstrates how easy it is to transform your web application in a desktop application which is the main purpose of Electron. It is an excellent option for companies who already have a website and want to provides their users with a desktop version, but don’t have the resources to develop a native application. However, for companies who have the knowledge and resources for a native application, the Electron Framework doesn’t really provide any advantage: the performance (CPU and memory) will always be worse than a native application, if those matters (and it always should 😉).

Call native libraries for windows hello

Before taking our decision, we had to make sure that Electron suited our needs. One of them was to be able to call a native dll written in C++ from the application and be able to call Windows libraries. As an example, we tried to interact with the Windows Hello API. Windows Hello is a feature in Windows 10 which allows you to log in into your session with a pin or a bio-metric device (fingerprint, face recognition, maybe DNA in the future 😁) . With this API, we use Windows Hello to log in in the current application so it’s a good benchmark to see what we can do with the Electron Framework.

Surprisingly it was not difficult to achieve. The ffi package was a big help for that. With this package, you can directly load a dll from JavaScript. The only requirements are:

  • Having a C like interface in the dll.
#ifdef __cplusplus
extern "C" {
#endif
 
enum class UserConsentAvailability : int32_t
{
    Available = 0,
    DeviceNotPresent = 1,
    NotConfiguredForUser = 2,
    DisabledByPolicy = 3,
    DeviceBusy = 4,
    Error,
};
__declspec(dllexport) void checkUserConsentAvailability(void(*callback) (UserConsentAvailability result, void *appData), void *appData);
__declspec(dllexport) UserConsentAvailability checkUserConsentAvailability_sync();
 
enum class UserConsentVerification : int32_t
{
    Verified = 0,
    DeviceNotPresent = 1,
    NotConfiguredForUser = 2,
    DisabledByPolicy = 3,
    DeviceBusy = 4,
    RetriesExhausted = 5,
    Canceled = 6,
    Error,
};
__declspec(dllexport) void verifyUserConsent(const wchar_t * userMessage, void(*callback) (UserConsentVerification result, void *appData), void *appData);
__declspec(dllexport) UserConsentVerification verifyUserConsent_sync(const wchar_t * userMessage);
 
#ifdef __cplusplus
} // extern "C"
#endif
  • Make sure we load dll which corresponds to the architecture of the current process (32 bits vs 64 bits).

With that in mind, it’s really easy to call the functions in the dll:

// import required modules
var ffi = require('ffi');
var ref = require('ref');
var int = ref.types.int;
 
// add dll path to PATH so ffi can find it
var winbioLib = 'winbio.dll';
var dllFolder = __dirname + '/libraries/';
if (process.arch == 'x64'){
    dllFolder += 'x64/';
}
else {
    dllFolder += 'x86/';
}
var dllPath = dllFolder + winbioLib;
var oldPath = process.env.PATH;
process.env['PATH'] = `${process.env.PATH};${dllFolder}`;
 
// load the library and specify the functions which will be called
var winbio = ffi.Library(dllPath, {
    "verifyUserConsent_sync": [int, ['string']],
    "checkUserConsentAvailability_sync": [int, []],
    "verifyUserConsent": ['void', ['string', 'pointer', 'pointer']],
    "checkUserConsentAvailability":  ['void', ['pointer', 'pointer']]
});
 
// reset PATH
process.env['PATH'] = oldPath;
 
// export library's functions
module.exports = winbio;

After that, it’s a piece of cake to call this methods from other JavaScript files. and it works just fine!

By the way, you can see that we have both sync and async methods. For async methods, c++ doesn’t work with promises obviously but it’s still pretty much straight forward. The package ffi provides a method to create callback pointers. Here is an example on how to call checkUserConsentAvailability:

var ffi = require('ffi');
var winbio = require('./winbio')
 
var checkUserConsentCallback = ffi.Callback('void', ['int', 'pointer'], (result, appdata) => {
    // Implement the callback here
})
 
const checkUserConsent = () => {
    winbio.checkUserConsentAvailability(checkUserConsentCallback, null /* appdata is not used here*/)
}

Electron Framework: Pros

The Electron Framework has some advantages which makes the technology interesting.

  • First, it’s really easy to build a new application from an existing web application: minor changes are needed to build a working prototype. It also allows you to have a common code base between your web application and your desktop one and as we know it: common code equals less development time and shared knowledge.
  • The second advantage is the cross-platform benefits. You can build your Electron application to run on either Windows, MacOS, or Linux with almost no cost. So building an Electron application would mean to have a Linux application at (almost) no cost (yeah! ). 
  • The third one involves the Electron community. A lot of applications are already written with this framework which means the community becomes bigger and bigger so it’s easy to find answers to your issues and the bugs can get fixed quite fast.

Electron Framework: Cons

There are also some drawbacks to using this framework.

The first and huge con is the memory consumption whether on the hard drive or in the RAM. As I said earlier, the user interface uses Chromium as a browser to render the web pages. In order to do so, the application has to be shipped with it and it takes a lot of space! Our prototype, which doesn’t have much in terms of features,  takes 180 MB on the hard drive and because of Chromium we cannot go under this limit. Concerning the RAM, our prototype uses between 250 and 300 MB which is quite a lot as well. Looking at existing applications (yes I’m looking at you Slack 😊), it looks really hard to reduce the memory consumption for an Electron application.

Conclusion: we decided not to choose Electron

I really love experimenting and learning new technologies and working on a prototype with the Electron Framework was really fun since it was the first time I was writing JavaScript! However we decided not to go with this technology for mainly two reasons:

  • Too much memory: As everyone experienced at least once in their life, Google Chrome can consume a lot of RAM and Chromium being the core of it does not break this rule. We felt like it was using too much memory for the use we have for it. The size on disk is an issue as well since we need to ship the whole Chromium with our application (there is a project for a Chromium light but it’s still not ready yet).
  • Doubts about the performances: Even though it’s a desktop application, it’s actually a browser running a web application. The performances cannot be the same as using native components and we didn’t want the user to have a bad experience because of this.
  • Too dependent on Chromium: Chromium is developed by Google and building our application on Electron would mean being highly dependent on it. This is a high risk we are unwilling to take.

Our customers trust us with their most sensitive personal data, and keeping their trust is a priority in every business decision we make. So the new application will not use the Electron framework which means our search is not over.

To be continued…