From 839c0551039afe229dbae4303d1036de7c7f411f Mon Sep 17 00:00:00 2001 From: David Risney Date: Thu, 30 May 2024 10:33:51 -0700 Subject: [PATCH 1/2] Add WinRT conversion APIs --- specs/CoreWebView2.CreateFromCOMObject.md | 90 ++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/specs/CoreWebView2.CreateFromCOMObject.md b/specs/CoreWebView2.CreateFromCOMObject.md index a5419aa1b..c2a9b4ced 100644 --- a/specs/CoreWebView2.CreateFromCOMObject.md +++ b/specs/CoreWebView2.CreateFromCOMObject.md @@ -17,8 +17,14 @@ To help implement this for Unity, we are adding a new static factory function on class that will allow it to wrap an existing ICoreWebView2 COM object, instead of creating a new one. +To round out the more general scenario of interoperating between libraries written in different +languages, we add the ability to convert a CoreWebView2 to and from .NET and COM, as well as +to and from WinRT and COM. + # Examples -## CoreWebView2.CreateFromComICoreWebView2 + +## COM to .NET + ```c# public class MyWebView2Control { @@ -47,8 +53,52 @@ public class MyWebView2Control } ``` +## WinRT to COM + +```c++ +winrt::com_ptr GetComICoreWebView2FromCoreWebView2( + winrt::Microsoft::Web::WebView2::Core::CoreWebView2 coreWebView2WinRT) +{ + // Get the COM interop interface from the WinRT CoreWebView2. + auto interop = coreWebView2WinRT.as(); + + // Get the COM ICoreWebView2 object from the COM interop interface. + winrt::com_ptr coreWebView2Com; + winrt::check_hresult(interop->GetComICoreWebView2(coreWebView2Com.put())); + + return coreWebView2Com; +} +``` + +## COM to WinRT + +```c++ +winrt::Microsoft::Web::WebView2::Core::CoreWebView2 GetCoreWebView2FromComICoreWebView2( + winrt::com_ptr coreWebView2Com) +{ + auto factory = winrt::get_activation_factory< + winrt::Microsoft::Web::WebView2::Core::CoreWebView2>(); + + // Get the COM interop interface from the WinRT factory. + auto interop = factory.try_as(); + + // Get the WinRT CoreWebView2 object from the COM interop interface as + // its ABI interface. + winrt::com_ptr coreWebView2WinRTAsIUnknown; + winrt::check_hresult(interop->CreateFromComICoreWebView2( + coreWebView2Com.get(), coreWebView2WinRTAsIUnknown.put())); + + // Convert from the WinRT CoreWebView2 object API interface to C++/WinRT type + return coreWebView2WinRTAsIUnknown.as< + winrt::Microsoft::Web::WebView2::Core::CoreWebView2>(); +} +``` + # API Details + +## .NET API + ```c# namespace Microsoft.Web.WebView2.Core { @@ -64,10 +114,48 @@ namespace Microsoft.Web.WebView2.Core /// Thrown when the provided COM pointer is null. /// Thrown when the value is not an ICoreWebView2 COM object and cannot be wrapped. public static CoreWebView2 CreateFromComICoreWebView2(IntPtr value); + + /// + /// Returns the existing COM ICoreWebView2 object underlying this .NET CoreWebView2 object. + /// This allows interacting with the WebView2 control using COM APIs, + /// even if the control was originally created using .NET. + /// + /// Pointer to a COM object that implements the ICoreWebView2 COM interface. + public IntPtr GetComICoreWebView2(); } } ``` +## WinRT COM Interop API + +```c# (but really COM IDL) +/// Interop interface for the CoreWebView2 WinRT object to allow WinRT end +/// developers to be able to use COM interfaces as parameters for some methods. +/// This interface is implemented by the Microsoft.Web.WebView2.Core.CoreWebView2 +/// runtime class. +[uuid(B151AD7C-CFB0-4ECF-B9B2-AFCA868581A6), object, pointer_default(unique)] +interface ICoreWebView2Interop2 : IUnknown { + /// Get a COM ICoreWebView2 interface corresponding to this WinRT CoreWebView2 + /// object. + HRESULT GetComICoreWebView2([out, retval] ICoreWebView2** coreWebView2); +} + +/// Interop interface for the CoreWebView2 WinRT activation factory object to allow +/// WinRT end developers to be able to use COM interfaces as parameters for some +/// methods. +/// This interface is implemented by the Microsoft.Web.WebView2.Core.CoreWebView2 +/// activation factory runtime class. +[uuid(BABBED43-D40E-40CF-B106-8ED65FAE2E7C), object, pointer_default(unique)] +interface ICoreWebView2ActivationFactoryInterop : IUnknown { + /// Creates a CoreWebView2 WinRT object that wraps an existing COM ICoreWebView2 object. + /// This allows interacting with the WebView2 control using WinRT, + /// even if the control was originally created using COM. + HRESULT CreateFromComICoreWebView2([in] ICoreWebView2* coreWebView2Com, + [out, retval] IUnknown** coreWebView2WinRt); +} + +``` + # Appendix We have a couple of other options to accomplish this, including moving the "CreateFromComICoreWebView2" function to the CoreWebView2Controller class instead. CoreWebView2Controller could then be used to get the CoreWebView2 through From 817bb8b1488cbe16503ad510937e76b56c54c9c7 Mon Sep 17 00:00:00 2001 From: David Risney Date: Thu, 30 May 2024 11:02:08 -0700 Subject: [PATCH 2/2] Fix sample method name --- specs/CoreWebView2.CreateFromCOMObject.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/CoreWebView2.CreateFromCOMObject.md b/specs/CoreWebView2.CreateFromCOMObject.md index c2a9b4ced..26c740c2e 100644 --- a/specs/CoreWebView2.CreateFromCOMObject.md +++ b/specs/CoreWebView2.CreateFromCOMObject.md @@ -73,7 +73,7 @@ winrt::com_ptr GetComICoreWebView2FromCoreWebView2( ## COM to WinRT ```c++ -winrt::Microsoft::Web::WebView2::Core::CoreWebView2 GetCoreWebView2FromComICoreWebView2( +winrt::Microsoft::Web::WebView2::Core::CoreWebView2 CreateCoreWebView2FromComICoreWebView2( winrt::com_ptr coreWebView2Com) { auto factory = winrt::get_activation_factory<