| File: IpcCommon.cs | Web Access |
| Project: src\aspnetcore\src\Components\WebView\WebView\src\Microsoft.AspNetCore.Components.WebView.csproj (Microsoft.AspNetCore.Components.WebView) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Linq; using System.Text.Json; namespace Microsoft.AspNetCore.Components.WebView; internal sealed class IpcCommon { private const string _ipcMessagePrefix = "__bwv:"; public static string Serialize(OutgoingMessageType messageType, params object[] args) => Serialize(messageType.ToString(), args); public static string Serialize(IncomingMessageType messageType, params object[] args) => Serialize(messageType.ToString(), args); public static bool TryDeserializeIncoming(string message, out IncomingMessageType messageType, out ArraySegment<JsonElement> args) => TryDeserialize(message, out messageType, out args); public static bool TryDeserializeOutgoing(string message, out OutgoingMessageType messageType, out ArraySegment<JsonElement> args) => TryDeserialize(message, out messageType, out args); private static string Serialize(string messageType, object[] args) { // We could come up with something a little more low-level here if we // wanted to avoid a couple of allocations var messageTypeAndArgs = args.Prepend(messageType); // Note we do NOT need the JSRuntime specific JsonSerializerOptions as the args needing special handling // (JS/DotNetObjectReference & Byte Arrays) have already been serialized earlier in the JSRuntime. // We run the serialization here to add the `messageType`. return $"{_ipcMessagePrefix}{JsonSerializer.Serialize(messageTypeAndArgs, JsonSerializerOptionsProvider.Options)}"; } private static bool TryDeserialize<T>(string message, out T messageType, out ArraySegment<JsonElement> args) { // We don't want to get confused by unrelated messages that the developer is sending // over the same webview IPC channel, so ignore anything else if (message != null && message.StartsWith(_ipcMessagePrefix, StringComparison.Ordinal)) { var messageAfterPrefix = message.AsSpan(_ipcMessagePrefix.Length); var parsed = (JsonElement[])JsonSerializer.Deserialize(messageAfterPrefix, typeof(JsonElement[]), JsonSerializerOptionsProvider.Options); messageType = (T)Enum.Parse(typeof(T), parsed[0].GetString()); args = new ArraySegment<JsonElement>(parsed, 1, parsed.Length - 1); return true; } else { messageType = default; args = default; return false; } } public enum IncomingMessageType { AttachPage, BeginInvokeDotNet, EndInvokeJS, OnRenderCompleted, OnLocationChanged, ReceiveByteArrayFromJS, OnLocationChanging, } public enum OutgoingMessageType { RenderBatch, Navigate, AttachToDocument, EndInvokeDotNet, NotifyUnhandledException, BeginInvokeJS, SendByteArrayToJS, SetHasLocationChangingListeners, EndLocationChanging, Refresh, } }