Add spec for SharedClusterEnvironment.md#5633
Conversation
API proposal for a shared WebView2 cluster environment using the symmetric Create + synchronous Get model (Approach 2). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- (1.7) Rename PerExeProfileIsolation -> PerHostProfileIsolation for OS-neutrality - (1.6) Document per-Id persisted state in the Get reference doc-comment - (1.10) Add API-shape decisions section: new options type vs extending ICoreWebView2EnvironmentOptions, and WinRT mismatch-surfacing (result/status enum vs COMException) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per repo spec conventions (template: 'talk about behavior, not implementation'), replace the storage/locking pseudocode (registry paths, AcquireLock/WriteRecord, WAIT_ABANDONED) with observable behavior guarantees, and condense the alternatives-considered section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Top-level sections now exactly match the spec template (Background, Conceptual, Examples, API Details, Appendix). Remove the 'Open questions' section (no other spec has one) and the reviewer-facing 'API-shape decisions'/'Behavior guarantees' Appendix subsections; keep a lean 'Alternatives considered' and 'Relationship to existing options', matching how other specs use the Appendix. Also fix the C++ example's Get error handling and add Id constraints. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CreateCoreWebView2ClusterEnvironment -> CreateOrJoinCoreWebView2ClusterEnvironment, the handler and the .NET/WinRT async method renamed to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The GUIDs were fabricated placeholders; real IIDs are allocated at implementation time. Matches specs like CustomDataPartition.md that omit uuid in the review IDL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
No WebView2 spec exposes an HRESULT constant as API. Match the convention (e.g. MultiProfile.md) of throwing a COMException and comparing ex.HResult against the HRESULT value with a comment naming the error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Trim API Details doc-comments to concise behavior, matching LMC reference conventions and the template style guide (describe behavior, not implementation). Removed implementation detail (storage/persistence 'State' note, Id->folder mapping rationale), design commentary (OS-neutral naming, sync justification), and conceptual/strategy narrative already covered in the Conceptual section. Standardized on 'options' over 'pinned set' jargon. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Drop internal shell/widgets example - Use 'WebView2 environment' rather than 'browser process tree' - Remove 'by accident' framing for cooperating apps - Remove reviewer-meta spec-scope/alternatives line from Background - Remove template conceptual-note line - Remove 'constant in a shared header' parenthetical Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The full P1/P2/P3 comparison lives in the internal design doc; the condensed duplicate is not public-doc material and most specs do not carry a rejected-designs section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ChannelSearchKind only defines search order and is incomplete without ReleaseChannels (its matched pair). Keep the first iteration minimal; channel-selection options can be appended later on a derived options interface without breaking compat. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The prior text cited remote-debugging port/logging as omitted, but those are set via AdditionalBrowserArguments, which is included. Reframe: every exposed option is process-wide and first-creator-supplied; runtime-locating options (BrowserExecutableFolder, TargetCompatibleBrowserVersion, ReleaseChannels/ChannelSearchKind) are deferred to a later derived interface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Appendix: keep only the process-wide new-type paragraph; drop the omitted-options list and any future-addition promise - Standardize 'attach to an identical cluster' -> 'attach to a cluster with matching options' - Name the model 'symmetric create-or-join' to match CreateOrJoin... - Re-flow the awkward Background line wrap - Remove the duplicate mismatch comment in the .NET example Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Model create/join outcomes with a COREWEBVIEW2_CLUSTER_ENVIRONMENT_STATUS enum (Succeeded, OptionsMismatch) returned in the completion handler, alongside errorCode (Print-style), instead of a bespoke HRESULT. - Surface not-supported (sandboxed/low-integrity/UWP, cannot share/access the UDF) via the synchronous return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) for CreateOrJoin (handler not called) and as the HRESULT/COMException for the synchronous Get. - Add ERROR_NOT_SUPPORTED handling to both examples; fix .NET Get-inside-try and retry status check. - Address PR feedback: gets->creates; recommend a stable descriptive Id (need not be a GUID); define 'cooperating host apps'; state a cluster occupies its own UDF namespace and never joins a CreateCoreWebView2EnvironmentWithOptions environment. - Standardize terminology (cluster options, shared browser process, matching options); trim implementation detail from PerHostProfileIsolation; clarify profile-isolation wording. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adopt the ICoreWebView2ClusterEnvironmentCreateResult interface (Status + Environment) in the completion handler instead of separate status/environment parameters, matching the ICoreWebView2ExperimentalUpdateRuntimeResult / ICoreWebView2ExecuteScriptResult idiom and making the COM handler a clean source for the existing WinRT CreateResult projection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Reframe the excluded options as a deliberate scoping choice for this initial version, not a technical 'cannot be shared'. - Simplify the Id-to-folder sentence and drop the confusing on-disk-layout clause. - Clarify that a private fallback environment uses your own user data folder with its own separate data. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new specification document describing a proposed “Shared WebView2 Cluster Environment” API, including rationale, recommended usage patterns, and Win32/.NET surface area.
Changes:
- Introduces a new spec for explicit create-or-join shared WebView2 environments keyed by a stable cluster
Id. - Documents the synchronous “Get, then Create” flow, including mismatch handling and fallback to private environments.
- Defines proposed Win32 COM/IDL and .NET/WinRT API shapes with usage examples.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address Priyank's editorial comments: determines vs fixes; drop informal phrasing ('paid to launch', 'we mean', 'likes it'); apps -> applications; runtime -> WebView2 Runtime; de-emphasize sync/async in prose; rename BuildMyOptions -> BuildClusterOptions; standardize 'exists' over 'configured'; use nullptr in COM doc-comments; name the shared browser process; fix a missing blank line.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Label the Win32 C++ API Details code block as cpp. - Reword the CreateOrJoin doc-comment to drop synchronous/asynchronous adjectives and name CreateOrJoinCoreWebView2ClusterEnvironment and the handler parameter directly. - Standardize on Id for the concept/property in prose and doc-comments; keep the literal signature parameters lowercase id. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ainer, errors - Add ReleaseChannels and ChannelSearchKind to cluster options (COM + WinRT), matching the PoC implementation; defaults all-channels and MOST_STABLE. - Fix options lifetime: a cluster exists only while its browser process is running; Get returns ERROR_NOT_FOUND when not running (was incorrectly 'available whether or not running'). - Define what 'match' means: all options except Id equal, AdditionalBrowserArguments exact string, custom schemes same in same order. - Tighten NOT_SUPPORTED wording to sandboxed AppContainer (UWP), matching the AppContainer gate in the implementation. - Rename heading to Description; add Win32-only support note; add cross-host diagnostics trust note; validate existing options in samples; make failing-create handling concrete; state handler errorCode carries the same failures as CreateCoreWebView2EnvironmentWithOptions; align custom-scheme memory wording. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add %LOCALAPPDATA%\Microsoft\WebView2Clusters\<Id> as the runtime-derived cluster user data folder, and state that CreateCoreWebView2EnvironmentWithOptions cannot join a cluster even when passed a cluster folder path explicitly. Matches DeriveClusterUserDataFolder and the IsClusterUserDataFolder guard in entry.cc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…l match, concurrency, trust/identity/session model, loader-override contract, and consistency fixes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ef97d825-5b56-4882-8226-a3af1d04c96a
…and fix consistency Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ef97d825-5b56-4882-8226-a3af1d04c96a
|
|
||
| A host process must be able to create and share the cluster's per-user user data | ||
| folder. A host that cannot, such as a sandboxed AppContainer process (for example, a | ||
| UWP app), fails with `ERROR_NOT_SUPPORTED`. A transient failure to access an |
There was a problem hiding this comment.
This text makes it sound like UWP / AppContainer apps cannot use this feature. But later on you say that the all hosts must run at same IL / elevation state. I'm guessing that this text just needs to be more explicit like
A host that cannot, such as a sandboxed AppContainer process (for example, a
UWP app), fails withERROR_NOT_SUPPORTED.
Should become like:
A host that cannot, such as a sandbox AppContainer process (for example, a
UWP app) trying to join a cluster environment started by a medium IL process,
fails withERROR_NOT_SUPPORTED.
There was a problem hiding this comment.
Good catch, the wording was misleading. Reworded to a positive support statement: cluster environments are supported for standard desktop host processes, meaning non-sandboxed, non-containerized applications running at medium or high integrity level. Applications that cannot create or share the per-user user data folder fail with ERROR_NOT_SUPPORTED.
| elevation among hosts is not supported and is not guaranteed to fail cleanly. This | ||
| mirrors the existing guidance against sharing a single user data folder across | ||
| elevation with `CreateCoreWebView2EnvironmentWithOptions`. | ||
|
|
There was a problem hiding this comment.
This is great documentation and sample code for creating a shared cluster. I would also expect to see documentation and sample code for deleting a shared cluster. If Word and Excel are sharing a cluster and they both get uninstalled respectively, what is responsible for deleting the UDF?
There was a problem hiding this comment.
Good call. Added a "Deleting a cluster's user data folder" section. WebView2 does not delete the cluster's user data folder automatically, so cleanup is the cooperating apps' shared responsibility. The last app being uninstalled should confirm no other cooperating app is still using the cluster, then delete the folder. The sample reads the path from ICoreWebView2Environment.UserDataFolder and deletes on BrowserProcessExited, once the shared browser has exited.
| reusing `ICoreWebView2EnvironmentOptions`. `ICoreWebView2ClusterEnvironmentOptions` | ||
| applies to the whole shared browser process. The first host to establish the cluster | ||
| supplies the options, and every host that attaches shares them; there is no per-host | ||
| override. The type intentionally exposes only a subset of the environment options. |
There was a problem hiding this comment.
It would be good to list the options that are excluded and why.
- ExclusiveUserDataFolderAccess - this one doesn't really make sense when the whole point of this API is to share the environment with multiple apps.
- IsCustomCrashReportingEnabled - why is this excluded?
- ScrollBarStyle - why is this excluded?
- TargetCompatibleBrowserVersion - why is this excluded?
There was a problem hiding this comment.
For the first version our intention was to keep sharing simple rather than surface many options that aren't widely used. The options not exposed here take their default values for the cluster. We can add more in a later version if there's demand.
| `CreateCoreWebView2EnvironmentWithOptions`, including the existing loader overrides such | ||
| as the `WEBVIEW2_BROWSER_EXECUTABLE_FOLDER` environment variable and the corresponding | ||
| registry override. This initial version does **not** coordinate those overrides across | ||
| hosts. The cluster options do not capture them, they are not part of the options match, |
There was a problem hiding this comment.
You could add the executableFolder as a property on the options. The reason below is that apps would have to ensure they have the same value, but that's true of all the options. Not sure why this isn't supported?
There was a problem hiding this comment.
Intentional. As the WebView2 team we want to encourage the evergreen runtime, so we deliberately left browserExecutableFolder out rather than have shared clusters pin a fixed-version runtime. If you feel we should expose it, let me know.
| [propput] HRESULT AdditionalBrowserArguments([in] LPCWSTR value); | ||
|
|
||
| /// Specifies the default display language for the shared environment. The default | ||
| /// is the empty string (the runtime default). The returned string is allocated |
There was a problem hiding this comment.
If one process creates the shared env and leaves Language empty string, and then a second process gets the shared env options, will Language be empty string, or the effective value now actually used? Eg will it be "" or something like "en-us"? If blank, will that be a problem if two different processes have different OS locale settings?
There was a problem hiding this comment.
Get returns the option as the first host supplied it, not a resolved value, so an empty Language comes back as "", never "en-US". We do not substitute a default: when it is empty, WebView2 passes no --lang switch and the shared browser uses its own OS-derived default, fixed by the first host at launch. Hosts that both leave it empty match; if apps need a specific language, they should set the same non-empty value.
…ed-options rationale Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ef97d825-5b56-4882-8226-a3af1d04c96a
This is a review for the new Shared WebView2 Cluster Environment API.