tauri icon indicating copy to clipboard operation
tauri copied to clipboard

[feat] Support for Browser Profiles

Open zphrs opened this issue 1 year ago • 7 comments

(see Wry issue here: https://github.com/tauri-apps/wry/issues/1321)

Describe the problem

I would ideally like to be able to create separate browsing profiles to segment Cookies, localStorage, and IndexedDB data into different profiles. Here are some use cases which could benefit from this feature:

  • Supporting multiple account login without any further server-side development
  • Local-first applications like Excalidraw which typically stores user data within either localStorage or an IndexedDB table
  • To limit third party tracking cookies across different webviews

The above use cases are very similar to the use cases for the data_directory() api. However, as I noted in the Alternatives considered section, the data_directory() api is not supported on MacOS.

Describe the solution you'd like

Platform-Specific Implementation Details

In macOS 14 and iOS 17 Apple has released new DataStore APIs which should enable this feature.

In Windows Microsoft has released new Multiple Profile Support which should enable this feature.

I assume we can polyfill this feature to WebkitGTK using the existing data_directory() function on the WebviewBuilder struct. Ideally the polyfill would create additional subdirectories within the default data directory to support the different profile names. For private profiles (i.e. incognito windows) which shouldn't be persisted I propose the use of the tmp directory to store those temporary profiles. While we won't get the performance advantages listed below in the Alternatives Considered, a polyfill will at least allow some support in the interim before GTK supports browser profiles.

Proposed API

The following is inspired by the above linked guides from the shared features which both Apple and Microsoft support. Note that Microsoft supports one additional configuration for a Profile, ScriptLocale, which I chose to exclude from the API since WebKit does not support it in their implementation. Conveniently both support private windows and custom names, although WebKit requires that the name is a UUID whereas Webview2 has some arbitrary name constraints.

In terms of the API itself, I propose one new struct, a WebviewProfile which will store all of the necessary references and metadata needed for profiles. I also propose the following public functions for WebviewProfile, App, and WebviewBuilder:

For WebviewProfile

  • WebviewProfile::default() -> WebviewProfile returns the default profile.
  • WebviewProfile::private() -> WebviewProfile returns a temporary profile.
  • WebviewProfile::new(name: String) -> WebviewProfile returns a new profile, storing the display name as metadata. It will not check whether the name has been used before as that would require access to the App state.
  • WebviewProfile::filePath(&self) -> Option<Path> returns Some(directory) where all of the user data is stored if it isn't private, otherwise returns None. Note that this option resolves the complaint (#8635) around trying to locate where the browser persists user data when using the default data_directory(), both in the default case, and in the case of a custom profile. I assume that we can hard-code platform-dependent paths manually to support this api.
  • WebviewProfile::display() -> String returns the configured display name, "private", or "default" depending on the type of profile.
    • Should also implement std::fmt which should call the above function.

For App

  • App::getWebviewProfiles(&self) -> HashMap<String, WebviewProfile> which will function similarly to App::windows(&self) in returning a HashMap with Strings mapping to WebviewProfiles. The keys are the same as the String passed into WebviewProfile::new(). Note that private profiles will not be included in the returned HashMap.
  • App::addWebviewProfile(&mut self, profile: WebviewProfile) -> Result(Self) which will add a new profile to the app. It will return Ok(Self) if the profile was successfully created or an error detailing what went wrong. For example it should return an AlreadyExists error if a profile with the same ID already exists.
  • App::deleteWebviewProfile(&mut self, profile: WebviewProfile) -> Result(boolean) which will delete the webview profile and return true if it exists within the app, otherwise returning false. Will refuse to delete the profile if it is still in use by a webview, instead returning an error. Will also refuse to delete the default profile, instead returning an error.

For WebviewBuilder

  • WebviewBuilder::profile(mut self, profile: WebviewProfile) -> Self which will configure the profile to be used for that webview. When the WebviewBuilder is used to make a webview if the existing profiles do not contain a profile with the passed in profile's id then it will attempt to call addWebviewProfile() on the App and return the result from that call. Otherwise it will use the existing profile's ID.

For Webview

  • Webview::profile(self) -> WebviewProfile which will return the active profile for the webview.

Alternatives considered

I initially considered using the data_directory() api to emulate different profiles across all platforms, similar to what I proposed for the WebkitGTK polyfill. Unfortunately, as @FabianLars points out in #8637, "We can't control the data dir on macos."

Additionally, Microsoft justifies the addition of multiple profiles (over the existing data folder api) as follows:

Previously, without multi-profile support, to achieve data separation, a WebView2 app could use different user data folders for different WebView2 controls. However, in that approach, you must run multiple WebView2 runtime instances (each including a browser process and a bunch of child processes), which consumed more system resources including memory, CPU footprint, and disk space. source

Additional context

No response

zphrs avatar Mar 27 '24 08:03 zphrs

Also I just wanted to clarify that I am happy to attempt the implementation of this myself as long as this feature request is given the go ahead.

zphrs avatar Mar 28 '24 20:03 zphrs

This sounds like a good proposal and would need to be implemented in wry crate first. Requiring macOS 14 is annoying though so might need to be put behind a feature flag or something. Also what about android?

Anyways feel free to experiment and open a PR if you want, contributions are always welcome.

amrbashir avatar Mar 29 '24 00:03 amrbashir

For Android I suggest we use the same polyfill that I proposed for WebkitGTK as Android currently also lacks support for multiple browser profiles. Also yeah, having limited backwards support for MacOS is annoying so I agree a feature flag would be appropriate for this feature.

zphrs avatar Jul 19 '24 23:07 zphrs

Is there any result yet

Sjj1024 avatar Mar 29 '25 02:03 Sjj1024

Unfortunately I've been too busy with other projects to work on this. If you (or anyone else) would like to take it over, feel free! I might eventually get around to it if no one else takes it over.

zphrs avatar Mar 29 '25 03:03 zphrs

@zphrs Is there any progress on this function at present?

wf-soft avatar Jun 16 '25 18:06 wf-soft

Nope, see my comment from March 28.

zphrs avatar Jun 17 '25 04:06 zphrs