Skip to content

Commit 604bf95

Browse files
authored
Merge pull request #4098 from MicrosoftEdge/createFromCOMObject-patch-1
API Review: CoreWebView2.CreateFromComObject
2 parents 0b37a79 + 83b3b67 commit 604bf95

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
CoreWebView2.CreateFromComICoreWebView2
2+
===
3+
4+
# Background
5+
The new [Unity WebView2](https://learn.microsoft.com/windows/mixed-reality/develop/advanced-concepts/webview2-unity-plugin)
6+
control creates and uses C++ COM to create and manage the
7+
ICoreWebView2* objects. However, Unity developers are often interacting with the Unity WebView2
8+
control using C#/.NET. The Unity WebView2 control doesn't expose the CoreWebView2 directly to devs
9+
using the Unity WebView2 control, so when devs want to call an API on CoreWebView2, they
10+
have to rely on that API being exposed on the Unity WebView2 control, which then internally calls
11+
into CoreWebView2. This is in contrast to our other controls (like WPF WebView2 and Winforms
12+
WebView2 controls) which directly give access to their [CoreWebView2 object](https://learn.microsoft.com/dotnet/api/microsoft.web.webview2.winforms.webview2.corewebview2?view=webview2-dotnet-1.0.2088.41),
13+
allowing devs to call any API that exists or gets
14+
added to the CoreWebView2/ICoreWebView2_*. The Unity WebView2 control can't do this today,
15+
as they are unable to create a CoreWebView2 object that wraps an already existing COM object.
16+
To help implement this for Unity, we are adding a new static factory function on CoreWebView2 .NET
17+
class that will allow it to wrap an existing ICoreWebView2 COM object, instead of creating a new
18+
one.
19+
20+
# Examples
21+
## CoreWebView2.CreateFromComICoreWebView2
22+
```c#
23+
public class MyWebView2Control
24+
{
25+
... // Regular control code
26+
27+
CoreWebView2 _myCoreWebView2 = null;
28+
29+
[DllImport(DLL_NAME, CallingConvention = CallingConvention.StdCall)]
30+
public static extern ComNativePointer GetNativePointer(WebViewInstancePtr instanceId);
31+
32+
// This is the CoreWebView2 property which allows developers to access CoreWebView2 APIs directly.
33+
public CoreWebView2 CoreWebView2
34+
{
35+
get
36+
{
37+
if (!_myCoreWebView2)
38+
{
39+
IntPtr comPtr = WebViewNative.GetNativePointer(InstanceId);
40+
41+
_myCoreWebView2 = CoreWebView2.CreateFromComICoreWebView2(comPtr);
42+
}
43+
return _myCoreWebView2;
44+
}
45+
}
46+
47+
}
48+
```
49+
50+
51+
# API Details
52+
```c#
53+
namespace Microsoft.Web.WebView2.Core
54+
{
55+
public class CoreWebView2
56+
{
57+
/// <summary>
58+
/// Creates a CoreWebView2 object that wraps an existing COM ICoreWebView2 object.
59+
/// This allows interacting with the WebView2 control using .NET,
60+
/// even if the control was originally created using COM.
61+
/// </summary>
62+
/// <param name="value">Pointer to a COM object that implements the ICoreWebView2 COM interface.</param>
63+
/// <returns>Returns a .NET CoreWebView2 object that wraps the COM object.</returns>
64+
/// <exception cref="ArgumentNullException">Thrown when the provided COM pointer is null.</exception>
65+
/// <exception cref="InvalidComObjectException">Thrown when the value is not an ICoreWebView2 COM object and cannot be wrapped.</exception>
66+
public static CoreWebView2 CreateFromComICoreWebView2(IntPtr value);
67+
}
68+
}
69+
```
70+
71+
# Appendix
72+
We have a couple of other options to accomplish this, including moving the "CreateFromComICoreWebView2" function to the
73+
CoreWebView2Controller class instead. CoreWebView2Controller could then be used to get the CoreWebView2 through
74+
its CoreWebView2 property which already exists. Or we could expose a new constructor on CoreWebView2/CoreWebView2Controller,
75+
instead of a factory method.
76+
77+
We decided on using the CoreWebView2 due to it being the class most likely to be exposed and used
78+
in .NET, and which is the same across different C# frameworks.
79+
We decided on a factory method to not give the impression that a new constructor is the default
80+
one (we don't currently have any public constructors), and to make the intent and usage of
81+
the method more obvious.

0 commit comments

Comments
 (0)