Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Function to add a simple host function to the object #4664

Open
Diegorro98 opened this issue Jul 5, 2024 · 5 comments
Open

[Feature]: Function to add a simple host function to the object #4664

Diegorro98 opened this issue Jul 5, 2024 · 5 comments
Assignees
Labels
feature request feature request

Comments

@Diegorro98
Copy link

Diegorro98 commented Jul 5, 2024

Describe the feature/enhancement you need

I would like to have a method similar to AddHostObjectToScript but for functions.

Right now, to add simple functions (in my case using WinUI 3) I need to follow the steps from this guide and the Custom (3rd-party) WinRT components section from the same guide to have these projects:

  • WinRTAdapter
  • Cpp/WinRT component with the following class that handles a function:
    • FuntionHandler.idl:
      namespace CppWinRTComponent
      {
          runtimeclass FunctionHandler
          {
              FunctionHandler();
              event Windows.Foundation.EventHandler<String> Function;
      
              void InvokeFunction(String payload);
          };
      }
      
    • FuntionHandler.h:
      #pragma once
      #include "CppWinRTComponent.g.h"
      namespace winrt::CppWinRTComponent::implementation
      {
          struct FunctionHandler : FunctionHandlerT<FunctionHandler>
          {
              FunctionHandler() = default;
      
              winrt::event_token FunctionEvent(winrt::Windows::Foundation::EventHandler<hstring> const& handler);
              void FunctionEvent(winrt::event_token const& token) noexcept;
      
              void InvokeFunction(hstring const& payload);
      
          private:
              winrt::event<Windows::Foundation::EventHandler<hstring>> m_FunctionEvent;
          };
      }
      namespace winrt::CppWinRTComponent::factory_implementation
      {
          struct FunctionHandler : FunctionHandlerT<FunctionHandler, implementation::FunctionHandler>
          {
          };
      }
    • FuntionHandler.cpp:
      #include "pch.h"
      #include "FunctionHandler.h"
      #include "CppWinRTComponent.g.cpp"
      namespace winrt::CppWinRTComponent::implementation
      {
          winrt::event_token FunctionHandler::FunctionEvent(winrt::Windows::Foundation::EventHandler<hstring> const& handler)
          {
              return m_FunctionEvent.add(handler);
          }
      
          void FunctionHandler::FunctionEvent(winrt::event_token const& token) noexcept
          {
              m_FunctionEvent.remove(token);
          }
      
          void FunctionHandler::InvokeFunction(hstring const& payload)
          {
              m_FunctionEvent(*this, payload);
          }
      }
  • A component projection project

Finally add the following code to the CoreWebView2Initialized event from the WebView2 control from the main project:

using CppWinRTComponent;
private void CoreWebView2Initialized(WebView2 sender, CoreWebView2InitializedEventArgs args)
{
    var functionHandler = new FunctionHandler();
    functionHandler.FunctionEvent += (sender, payload) => Debug.WriteLine($"Function called with the following payload: {payload}");

    var dispatchAdapter = new WinRTAdapter.DispatchAdapter();
    WebView.CoreWebView2.AddHostObjectToScript("functionHandler", dispatchAdapter.WrapObject(functionHandler, dispatchAdapter));
}

To then call it from JavaScript using the following code:

chrome.webview.hostObjects.sync.functionHandler.InvokeFunction("Hello World!");

As you can see, complex work is required to add a simple function, maybe this work can be simplified.

The scenario/use case where you would use this feature

I would use this feature in the above mentioned scenario

How important is this request to you?

Nice to have. There are other ways to tackle this, but having official API support would be beneficial.

Suggested implementation

A function called AddHostFunctionToScript could be created, so the implementation could look as simple as this:

using CppWinRTComponent;
private void CoreWebView2Initialized(WebView2 sender, CoreWebView2InitializedEventArgs args)
{
    WebView.CoreWebView2.AddHostFunctionToScript(
        "addedFunction", 
        (string payload) => Debug.WriteLine($"Function called with the following payload: {payload}")
    );
}

To then call it from JavaScript using the following code:

chrome.webview.hostFunctions.sync.addedFunction("Hello World!");

In .NET, it would need up to 34 method overloads due to the existence of 17 Func delegate types and 17 Action delegate types.

What does your app do? Is there a pending deadline for this request?

No response

@victorhuangwq
Copy link
Collaborator

Hi @david-risney could you take a look to see if this request is worth considering?

@michael-hawker
Copy link

Looping in @nishitha-burman from #3823 as well, as I think this ties into many of the other related issues/requests due to this #2754, #4521, #4664.

I've also just been trying to look at using AddHostObjectToScript from a C# in a WinUI 3 app, I was hoping I could just follow the WPF instructions or something, and surprised I'm having to follow a whole C++ project setup and all these other steps to glue two things together.

With the original WebView in UWP and AddWebAllowedObject this was literally one line and just passing in my C# object from my current project... it's oppressively complex right now to do this.

@michael-hawker
Copy link

Also stumbled upon this old issue which seems to highlight some of the issues I've faced in trying to test this from a WinUI 3 app: #2937

@david-risney
Copy link
Contributor

We'll look into this. We can do some work to improve docs and samples for the existing solution in the shorter term. To make something work like AddWebAllowedObject is a much larger feature that we can look at.

@Diegorro98
Copy link
Author

Kind of out of topic, there's any way native AOT can help to simplify the process to achieve this functionality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request feature request
Projects
None yet
Development

No branches or pull requests

4 participants