Repository: tauri
Issue: [feat] Support for Browser Profiles
Labels: type: feature request

### 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](https://webkit.org/blog/14423/building-profiles-with-new-webkit-api/) which should enable this feature.

In Windows Microsoft has released new [Multiple Profile Support](https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/multi-profile-support?tabs=dotnetcsharp) 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`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2controlleroptions.scriptlocale?view=webview2-dotnet-1.0.2420.47#microsoft-web-webview2-core-corewebview2controlleroptions-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](https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2controlleroptions?view=webview2-dotnet-1.0.2420.47).

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 the 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, that "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](https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/multi-profile-support?tabs=dotnetcsharp#previous-approach-using-a-different-user-data-folder-for-each-webview2-control)

### Additional context

_No response_