From 4868cdbfa37ead93812307ec9786744441faf4e3 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 9 Jul 2018 14:13:10 +0100 Subject: [PATCH] Change BrowserRendererRegistry not to be static, and to scope the BrowserRenderer IDs to each instance This is to ensure that, in multiuser scenarios, users can't interfere with each other by posting events for somebody else's renderer ID. TODO: Still need to wire up or replace the temporary static BrowserRendererRegistry.CurrentUserInstance property to provide per-user storage. --- .../Rendering/BrowserRenderer.cs | 4 ++-- .../BrowserRendererEventDispatcher.cs | 2 +- .../Rendering/BrowserRendererRegistry.cs | 22 +++++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs index 550c019d1e..675fc29e3e 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering /// The to use when initializing components. public BrowserRenderer(IServiceProvider serviceProvider): base(serviceProvider) { - _browserRendererId = BrowserRendererRegistry.Add(this); + _browserRendererId = BrowserRendererRegistry.CurrentUserInstance.Add(this); } internal void DispatchBrowserEvent(int componentId, int eventHandlerId, UIEventArgs eventArgs) @@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering /// public void Dispose() { - BrowserRendererRegistry.TryRemove(_browserRendererId); + BrowserRendererRegistry.CurrentUserInstance.TryRemove(_browserRendererId); } /// diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs index f005c4f96b..01ec744b84 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering BrowserEventDescriptor eventDescriptor, string eventArgsJson) { var eventArgs = ParseEventArgsJson(eventDescriptor.EventArgsType, eventArgsJson); - var browserRenderer = BrowserRendererRegistry.Find(eventDescriptor.BrowserRendererId); + var browserRenderer = BrowserRendererRegistry.CurrentUserInstance.Find(eventDescriptor.BrowserRendererId); browserRenderer.DispatchBrowserEvent( eventDescriptor.ComponentId, eventDescriptor.EventHandlerId, diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererRegistry.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererRegistry.cs index 805c772d44..a0aa2a3860 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererRegistry.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererRegistry.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; @@ -12,18 +12,26 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering /// their associated component instances aren't GCed when events may still /// be received for them. /// - internal static class BrowserRendererRegistry + internal class BrowserRendererRegistry { - private static int _nextId; - private static IDictionary _browserRenderers + private int _nextId; + private IDictionary _browserRenderers = new Dictionary(); + /// TODO: Don't have just one global static instance. + /// For multi-user scenarios, we need the current instance to be distinct for each user, + /// and ensure it's always set to that user's value whenever there are incoming JS interop + /// calls. We could store the value in the IServiceProvider but then we still need some way + /// of reaching the current user's IServiceProvider inside calls to .NET from JS interop. + internal static BrowserRendererRegistry CurrentUserInstance { get; } + = new BrowserRendererRegistry(); + /// /// Adds the and gets a unique identifier for it. /// /// /// A unique identifier for the . - public static int Add(BrowserRenderer browserRenderer) + public int Add(BrowserRenderer browserRenderer) { lock (_browserRenderers) { @@ -39,7 +47,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering /// /// The identifier of the instance to be returned. /// The corresponding instance. - public static BrowserRenderer Find(int browserRendererId) + public BrowserRenderer Find(int browserRendererId) { lock (_browserRenderers) { @@ -52,7 +60,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering /// /// The identifier of the to remove. /// if the was present; otherwise . - public static bool TryRemove(int browserRendererId) + public bool TryRemove(int browserRendererId) { lock (_browserRenderers) {