File: PhotinoWebViewManager.cs
Web Access
Project: src\src\Components\WebView\Samples\PhotinoPlatform\src\Microsoft.AspNetCore.Components.WebView.Photino.csproj (Microsoft.AspNetCore.Components.WebView.Photino)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.FileProviders;
using PhotinoNET;
 
namespace Microsoft.AspNetCore.Components.WebView.Photino;
 
internal class PhotinoWebViewManager : WebViewManager
{
    private readonly PhotinoWindow _window;
    private readonly Uri _appBaseUri;
 
    // On Windows, we can't use a custom scheme to host the initial HTML,
    // because webview2 won't let you do top-level navigation to such a URL.
    // On Linux/Mac, we must use a custom scheme, because their webviews
    // don't have a way to intercept http:// scheme requests.
    internal static readonly string BlazorAppScheme = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
        ? "http"
        : "app";
 
    internal static readonly string AppBaseOrigin
        = $"{BlazorAppScheme}://0.0.0.0/";
 
    public PhotinoWebViewManager(PhotinoWindow window, IServiceProvider provider, Dispatcher dispatcher, Uri appBaseUri, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath)
        : base(provider, dispatcher, appBaseUri, fileProvider, jsComponents, hostPageRelativePath)
    {
        _appBaseUri = appBaseUri;
        _window = window ?? throw new ArgumentNullException(nameof(window));
        _window.WebMessageReceived += (sender, message) =>
        {
            // On some platforms, we need to move off the browser UI thread
            Task.Factory.StartNew(message =>
            {
                // TODO: Fix this. Photino should ideally tell us the URL that the message comes from so we
                // know whether to trust it. Currently it's hardcoded to trust messages from any source, including
                // if the webview is somehow navigated to an external URL.
                var messageOriginUrl = _appBaseUri;
 
                MessageReceived(messageOriginUrl, (string)message!);
            }, message, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
        };
    }
 
    public Stream? HandleWebRequest(string url, out string? contentType)
    {
        // It would be better if we were told whether or not this is a navigation request, but
        // since we're not, guess.
        var hasFileExtension = url.LastIndexOf('.') > url.LastIndexOf('/');
 
        if (_appBaseUri.IsBaseOf(new Uri(url))
            && TryGetResponseContent(url, !hasFileExtension, out _, out _, out var content, out var headers))
        {
            headers.TryGetValue("Content-Type", out contentType);
            return content;
        }
        else
        {
            contentType = default;
            return null;
        }
    }
 
    protected override void NavigateCore(Uri absoluteUri)
    {
        _window.Load(absoluteUri);
    }
 
    protected override void SendMessage(string message)
    {
        _window.SendWebMessage(message);
    }
}