Blazor.BrowserExtension: Issues Adding Razor Components to Gmail DOM in Chrome Extension

I am developing a Chrome extension using the Blazor.BrowserExtension package. The goal is to manipulate Gmail’s DOM by injecting Razor components and invoking C# methods from custom.js (content script). Below are the relevant parts of my implementation:

manifest.json:

{
  "manifest_version": 3,
  "name": "Test Extension",
  "description": "My browser extension built with Blazor WebAssembly",
  "version": "0.1",
  "background": {
    "service_worker": "content/BackgroundWorker.js",
    "type": "module"
  },
  "permissions": [
    "activeTab",
    "scripting",
    "storage"
  ],
  "host_permissions": [
    "https://mail.google.com/*"
  ],
  "action": {
    "default_popup": "popup.html"
  },
  "options_ui": {
    "page": "options.html",
    "open_in_tab": true
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
     "script-src": "'self' 'unsafe-inline' 'unsafe-eval'",
    "object-src": "'self'"
  },
  "content_scripts": [
    {
      "matches": ["https://mail.google.com/mail/*"],
      "js": ["framework/blazor.webassembly.js","content/custom.js"],
      "run_at": "document_idle"
    }
  ],
  "web_accessible_resources": [
    {
      "resources": [
        "framework/*",
        "content/*",
        "wwwroot/*"
      ],
      "matches": [ "https://mail.google.com/*" ]
    }
  ]
}

Program.cs:

using Blazor.BrowserExtension;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Test.Components;

namespace Test
{
    public static class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            
            builder.UseBrowserExtension(browserExtension =>
            {
                if (browserExtension.Mode == BrowserExtensionMode.ContentScript)
                {
                    builder.RootComponents.RegisterForJavaScript<ButtonComponent>("CustomButton");
                }
                if (browserExtension.Mode == BrowserExtensionMode.Background)
                {
                    builder.RootComponents.AddBackgroundWorker<BackgroundWorker>();
                }
                else
                {
                    builder.RootComponents.Add<App>("#app");
                    builder.RootComponents.Add<HeadOutlet>("head::after");
                }
            });

            builder.Services.AddScoped<ITestService, TestService>();
            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            await builder.Build().RunAsync();
        }
    }
}

ButtonComponent.razor:

@page "/button.html"
@inject IJSRuntime JSRuntime

 <button @onclick="HandleClick" class="gmail-button">
    @ButtonText
</button>

<style>
    .gmail-button { /* styling here */ }
</style>

@code {
    [Parameter]
    public string ButtonText { get; set; } = "Click Me";

    private async Task HandleClick()
    {
        await JSRuntime.InvokeVoidAsync("alert", "Blazor Button Clicked!");
    }
}

custom.js:

(async () => {
    const sendButtonContainer = document.querySelector(".dC");
    if (!sendButtonContainer) {
        console.error("Send button container not found.");
    }

    const blazorScript = document.createElement("script");
    blazorScript.src = chrome.runtime.getURL("framework/blazor.webassembly.js");
    blazorScript.type = "text/javascript";
    blazorScript.onload = async () => {
        console.log("Blazor WebAssembly script loaded.");
        await Blazor.start();

        const blazorContainer = document.createElement("div");
        blazorContainer.id = "blazor-custom-container";
        sendButtonContainer.appendChild(blazorContainer);

        Blazor.rootComponents.add(blazorContainer, 'CustomButton', {
            ButtonText: "Blazor Action"
        });

        console.log("Blazor component added.");
    };

    blazorScript.onerror = () => {
        console.error("Failed to load Blazor WebAssembly script.");
    };

    document.head.appendChild(blazorScript);
})();

When I run this, I encounter the following errors:

  • blazor.webassembly.js:1 Refused to load the script ‘https://mail.google.com/mail/u/0/framework/dotnet.js’ because it violates the Content Security Policy directive: “script-src ‘self’ ‘wasm-unsafe-eval’ …”
  • Uncaught (in promise) Error: Failed to start platform. Reason: TypeError: Failed to fetch dynamically imported module: https://mail.google.com/mail/u/0/framework/dotnet.js
  • Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of “text/html”.
  • blazor.webassembly.js:1 Uncaught (in promise) Error: Failed to start platform.

My Question:

  1. Is it possible to use Blazor.BrowserExtension to inject Razor components into Gmail’s DOM?
  2. Are these errors related to limitations with Blazor.BrowserExtension in handling Gmail’s CSP or resource restrictions?
  3. Should I switch to a pure JavaScript implementation for DOM manipulation in this case?

Any guidance would be appreciated.