瀏覽代碼

Fix warnings in SessionManager

Bond_009 5 年之前
父節點
當前提交
c601def484
共有 2 個文件被更改,包括 156 次插入131 次删除
  1. 12 1
      Emby.Server.Implementations/ApplicationHost.cs
  2. 144 130
      Emby.Server.Implementations/Session/SessionManager.cs

+ 12 - 1
Emby.Server.Implementations/ApplicationHost.cs

@@ -808,7 +808,18 @@ namespace Emby.Server.Implementations
             ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, ProviderManager);
             serviceCollection.AddSingleton(ChannelManager);
 
-            SessionManager = new SessionManager(UserDataManager, LoggerFactory, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, this, AuthenticationRepository, DeviceManager, MediaSourceManager);
+            SessionManager = new SessionManager(
+                LoggerFactory.CreateLogger<SessionManager>(),
+                UserDataManager,
+                LibraryManager,
+                UserManager,
+                musicManager,
+                DtoService,
+                ImageProcessor,
+                this,
+                AuthenticationRepository,
+                DeviceManager,
+                MediaSourceManager);
             serviceCollection.AddSingleton(SessionManager);
 
             serviceCollection.AddSingleton<IDlnaManager>(

+ 144 - 130
Emby.Server.Implementations/Session/SessionManager.cs

@@ -30,17 +30,17 @@ using Microsoft.Extensions.Logging;
 namespace Emby.Server.Implementations.Session
 {
     /// <summary>
-    /// Class SessionManager
+    /// Class SessionManager.
     /// </summary>
     public class SessionManager : ISessionManager, IDisposable
     {
         /// <summary>
-        /// The _user data repository
+        /// The _user data repository.
         /// </summary>
         private readonly IUserDataManager _userDataManager;
 
         /// <summary>
-        /// The _logger
+        /// The _logger.
         /// </summary>
         private readonly ILogger _logger;
 
@@ -57,36 +57,19 @@ namespace Emby.Server.Implementations.Session
         private readonly IDeviceManager _deviceManager;
 
         /// <summary>
-        /// The _active connections
+        /// The _active connections.
         /// </summary>
         private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
             new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase);
 
-        public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
-
-        public event EventHandler<GenericEventArgs<AuthenticationResult>> AuthenticationSucceeded;
-
-        /// <summary>
-        /// Occurs when [playback start].
-        /// </summary>
-        public event EventHandler<PlaybackProgressEventArgs> PlaybackStart;
-        /// <summary>
-        /// Occurs when [playback progress].
-        /// </summary>
-        public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
-        /// <summary>
-        /// Occurs when [playback stopped].
-        /// </summary>
-        public event EventHandler<PlaybackStopEventArgs> PlaybackStopped;
+        private Timer _idleTimer;
 
-        public event EventHandler<SessionEventArgs> SessionStarted;
-        public event EventHandler<SessionEventArgs> CapabilitiesChanged;
-        public event EventHandler<SessionEventArgs> SessionEnded;
-        public event EventHandler<SessionEventArgs> SessionActivity;
+        private DtoOptions _itemInfoDtoOptions;
+        private bool _disposed = false;
 
         public SessionManager(
+            ILogger<SessionManager> logger,
             IUserDataManager userDataManager,
-            ILoggerFactory loggerFactory,
             ILibraryManager libraryManager,
             IUserManager userManager,
             IMusicManager musicManager,
@@ -97,8 +80,8 @@ namespace Emby.Server.Implementations.Session
             IDeviceManager deviceManager,
             IMediaSourceManager mediaSourceManager)
         {
+            _logger = logger;
             _userDataManager = userDataManager;
-            _logger = loggerFactory.CreateLogger(nameof(SessionManager));
             _libraryManager = libraryManager;
             _userManager = userManager;
             _musicManager = musicManager;
@@ -108,9 +91,49 @@ namespace Emby.Server.Implementations.Session
             _authRepo = authRepo;
             _deviceManager = deviceManager;
             _mediaSourceManager = mediaSourceManager;
+
             _deviceManager.DeviceOptionsUpdated += OnDeviceManagerDeviceOptionsUpdated;
         }
 
+        /// <inheritdoc />
+        public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
+
+        /// <inheritdoc />
+        public event EventHandler<GenericEventArgs<AuthenticationResult>> AuthenticationSucceeded;
+
+        /// <summary>
+        /// Occurs when [playback start].
+        /// </summary>
+        public event EventHandler<PlaybackProgressEventArgs> PlaybackStart;
+
+        /// <summary>
+        /// Occurs when [playback progress].
+        /// </summary>
+        public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
+
+        /// <summary>
+        /// Occurs when [playback stopped].
+        /// </summary>
+        public event EventHandler<PlaybackStopEventArgs> PlaybackStopped;
+
+        /// <inheritdoc />
+        public event EventHandler<SessionEventArgs> SessionStarted;
+
+        /// <inheritdoc />
+        public event EventHandler<SessionEventArgs> CapabilitiesChanged;
+
+        /// <inheritdoc />
+        public event EventHandler<SessionEventArgs> SessionEnded;
+
+        /// <inheritdoc />
+        public event EventHandler<SessionEventArgs> SessionActivity;
+
+        /// <summary>
+        /// Gets all connections.
+        /// </summary>
+        /// <value>All connections.</value>
+        public IEnumerable<SessionInfo> Sessions => _activeConnections.Values.OrderByDescending(c => c.LastActivityDate);
+
         private void OnDeviceManagerDeviceOptionsUpdated(object sender, GenericEventArgs<Tuple<string, DeviceOptions>> e)
         {
             foreach (var session in Sessions)
@@ -130,14 +153,17 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
-        private bool _disposed = false;
-
+        /// <inheritdoc />
         public void Dispose()
         {
             Dispose(true);
             GC.SuppressFinalize(this);
         }
 
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
         protected virtual void Dispose(bool disposing)
         {
             if (_disposed)
@@ -147,15 +173,17 @@ namespace Emby.Server.Implementations.Session
 
             if (disposing)
             {
-                // TODO: dispose stuff
+                _idleTimer?.Dispose();
             }
 
+            _idleTimer = null;
+
             _deviceManager.DeviceOptionsUpdated -= OnDeviceManagerDeviceOptionsUpdated;
 
             _disposed = true;
         }
 
-        public void CheckDisposed()
+        private void CheckDisposed()
         {
             if (_disposed)
             {
@@ -163,12 +191,6 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
-        /// <summary>
-        /// Gets all connections.
-        /// </summary>
-        /// <value>All connections.</value>
-        public IEnumerable<SessionInfo> Sessions => _activeConnections.Values.OrderByDescending(c => c.LastActivityDate);
-
         private void OnSessionStarted(SessionInfo info)
         {
             if (!string.IsNullOrEmpty(info.DeviceId))
@@ -199,13 +221,13 @@ namespace Emby.Server.Implementations.Session
                 new SessionEventArgs
                 {
                     SessionInfo = info
-
                 },
                 _logger);
 
             info.Dispose();
         }
 
+        /// <inheritdoc />
         public void UpdateDeviceName(string sessionId, string deviceName)
         {
             var session = GetSession(sessionId);
@@ -225,7 +247,6 @@ namespace Emby.Server.Implementations.Session
         /// <param name="remoteEndPoint">The remote end point.</param>
         /// <param name="user">The user.</param>
         /// <returns>SessionInfo.</returns>
-        /// <exception cref="ArgumentNullException">user</exception>
         public SessionInfo LogSessionActivity(
             string appName,
             string appVersion,
@@ -263,14 +284,7 @@ namespace Emby.Server.Implementations.Session
 
                 if ((activityDate - userLastActivityDate).TotalSeconds > 60)
                 {
-                    try
-                    {
-                        _userManager.UpdateUser(user);
-                    }
-                    catch (Exception ex)
-                    {
-                        _logger.LogError("Error updating user", ex);
-                    }
+                    _userManager.UpdateUser(user);
                 }
             }
 
@@ -287,18 +301,20 @@ namespace Emby.Server.Implementations.Session
             return session;
         }
 
+        /// <inheritdoc />
         public void CloseIfNeeded(SessionInfo session)
         {
             if (!session.SessionControllers.Any(i => i.IsSessionActive))
             {
                 var key = GetSessionKey(session.Client, session.DeviceId);
 
-                _activeConnections.TryRemove(key, out var removed);
+                _activeConnections.TryRemove(key, out _);
 
                 OnSessionEnded(session);
             }
         }
 
+        /// <inheritdoc />
         public void ReportSessionEnded(string sessionId)
         {
             CheckDisposed();
@@ -308,7 +324,7 @@ namespace Emby.Server.Implementations.Session
             {
                 var key = GetSessionKey(session.Client, session.DeviceId);
 
-                _activeConnections.TryRemove(key, out var removed);
+                _activeConnections.TryRemove(key, out _);
 
                 OnSessionEnded(session);
             }
@@ -339,7 +355,7 @@ namespace Emby.Server.Implementations.Session
                     var runtimeTicks = libraryItem.RunTimeTicks;
 
                     MediaSourceInfo mediaSource = null;
-                    if (libraryItem is IHasMediaSources hasMediaSources)
+                    if (libraryItem is IHasMediaSources)
                     {
                         mediaSource = await GetMediaSource(libraryItem, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
 
@@ -391,7 +407,6 @@ namespace Emby.Server.Implementations.Session
         /// Removes the now playing item id.
         /// </summary>
         /// <param name="session">The session.</param>
-        /// <exception cref="ArgumentNullException">item</exception>
         private void RemoveNowPlayingItem(SessionInfo session)
         {
             session.NowPlayingItem = null;
@@ -404,9 +419,7 @@ namespace Emby.Server.Implementations.Session
         }
 
         private static string GetSessionKey(string appName, string deviceId)
-        {
-            return appName + deviceId;
-        }
+            => appName + deviceId;
 
         /// <summary>
         /// Gets the connection.
@@ -426,6 +439,7 @@ namespace Emby.Server.Implementations.Session
             {
                 throw new ArgumentNullException(nameof(deviceId));
             }
+
             var key = GetSessionKey(appName, deviceId);
 
             CheckDisposed();
@@ -498,7 +512,7 @@ namespace Emby.Server.Implementations.Session
         {
             var users = new List<User>();
 
-            if (!session.UserId.Equals(Guid.Empty))
+            if (session.UserId != Guid.Empty)
             {
                 var user = _userManager.GetUserById(session.UserId);
 
@@ -517,8 +531,6 @@ namespace Emby.Server.Implementations.Session
             return users;
         }
 
-        private Timer _idleTimer;
-
         private void StartIdleCheckTimer()
         {
             if (_idleTimer == null)
@@ -594,11 +606,11 @@ namespace Emby.Server.Implementations.Session
         }
 
         /// <summary>
-        /// Used to report that playback has started for an item
+        /// Used to report that playback has started for an item.
         /// </summary>
         /// <param name="info">The info.</param>
         /// <returns>Task.</returns>
-        /// <exception cref="ArgumentNullException">info</exception>
+        /// <exception cref="ArgumentNullException"><c>info</c> is <c>null</c>.</exception>
         public async Task OnPlaybackStart(PlaybackStartInfo info)
         {
             CheckDisposed();
@@ -610,7 +622,7 @@ namespace Emby.Server.Implementations.Session
 
             var session = GetSession(info.SessionId);
 
-            var libraryItem = info.ItemId.Equals(Guid.Empty)
+            var libraryItem = info.ItemId == Guid.Empty
                 ? null
                 : GetNowPlayingItem(session, info.ItemId);
 
@@ -648,7 +660,6 @@ namespace Emby.Server.Implementations.Session
                     ClientName = session.Client,
                     DeviceId = session.DeviceId,
                     Session = session
-
                 },
                 _logger);
 
@@ -679,13 +690,14 @@ namespace Emby.Server.Implementations.Session
             _userDataManager.SaveUserData(user, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None);
         }
 
+        /// <inheritdoc />
         public Task OnPlaybackProgress(PlaybackProgressInfo info)
         {
             return OnPlaybackProgress(info, false);
         }
 
         /// <summary>
-        /// Used to report playback progress for an item
+        /// Used to report playback progress for an item.
         /// </summary>
         /// <returns>Task.</returns>
         public async Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated)
@@ -852,7 +864,7 @@ namespace Emby.Server.Implementations.Session
                 {
                     MediaSourceInfo mediaSource = null;
 
-                    if (libraryItem is IHasMediaSources hasMediaSources)
+                    if (libraryItem is IHasMediaSources)
                     {
                         mediaSource = await GetMediaSource(libraryItem, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
                     }
@@ -924,7 +936,6 @@ namespace Emby.Server.Implementations.Session
                     ClientName = session.Client,
                     DeviceId = session.DeviceId,
                     Session = session
-
                 },
                 _logger);
         }
@@ -962,13 +973,17 @@ namespace Emby.Server.Implementations.Session
         /// <param name="sessionId">The session identifier.</param>
         /// <param name="throwOnMissing">if set to <c>true</c> [throw on missing].</param>
         /// <returns>SessionInfo.</returns>
-        /// <exception cref="ResourceNotFoundException">sessionId</exception>
+        /// <exception cref="ResourceNotFoundException">
+        /// No session with an Id equal to <c>sessionId</c> was found
+        /// and <c>throwOnMissing</c> is <c>true</c>.
+        /// </exception>
         private SessionInfo GetSession(string sessionId, bool throwOnMissing = true)
         {
             var session = Sessions.FirstOrDefault(i => string.Equals(i.Id, sessionId, StringComparison.Ordinal));
             if (session == null && throwOnMissing)
             {
-                throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId));
+                throw new ResourceNotFoundException(
+                    string.Format(CultureInfo.InvariantCulture, "Session {0} not found.", sessionId));
             }
 
             return session;
@@ -981,12 +996,14 @@ namespace Emby.Server.Implementations.Session
 
             if (session == null)
             {
-                throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId));
+                throw new ResourceNotFoundException(
+                    string.Format(CultureInfo.InvariantCulture, "Session {0} not found.", sessionId));
             }
 
             return session;
         }
 
+        /// <inheritdoc />
         public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1007,6 +1024,7 @@ namespace Emby.Server.Implementations.Session
             return SendGeneralCommand(controllingSessionId, sessionId, generalCommand, cancellationToken);
         }
 
+        /// <inheritdoc />
         public Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1051,6 +1069,7 @@ namespace Emby.Server.Implementations.Session
             return Task.WhenAll(GetTasks());
         }
 
+        /// <inheritdoc />
         public async Task SendPlayCommand(string controllingSessionId, string sessionId, PlayRequest command, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1092,7 +1111,8 @@ namespace Emby.Server.Implementations.Session
             {
                 if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full))
                 {
-                    throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
+                    throw new ArgumentException(
+                        string.Format(CultureInfo.InvariantCulture, "{0} is not allowed to play media.", user.Name));
                 }
             }
 
@@ -1200,6 +1220,7 @@ namespace Emby.Server.Implementations.Session
             return _musicManager.GetInstantMixFromItem(item, user, new DtoOptions(false) { EnableImages = false });
         }
 
+        /// <inheritdoc />
         public Task SendBrowseCommand(string controllingSessionId, string sessionId, BrowseRequest command, CancellationToken cancellationToken)
         {
             var generalCommand = new GeneralCommand
@@ -1216,6 +1237,7 @@ namespace Emby.Server.Implementations.Session
             return SendGeneralCommand(controllingSessionId, sessionId, generalCommand, cancellationToken);
         }
 
+        /// <inheritdoc />
         public Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1299,12 +1321,12 @@ namespace Emby.Server.Implementations.Session
 
             var session = GetSession(sessionId);
 
-            if (session.UserId.Equals(userId))
+            if (session.UserId == userId)
             {
                 throw new ArgumentException("The requested user is already the primary user of the session.");
             }
 
-            if (session.AdditionalUsers.All(i => !i.UserId.Equals(userId)))
+            if (session.AdditionalUsers.All(i => i.UserId != userId))
             {
                 var user = _userManager.GetUserById(userId);
 
@@ -1430,19 +1452,19 @@ namespace Emby.Server.Implementations.Session
 
         private string GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName)
         {
-            var existing = _authRepo.Get(new AuthenticationInfoQuery
-            {
-                DeviceId = deviceId,
-                UserId = user.Id,
-                Limit = 1
-
-            }).Items.FirstOrDefault();
-
-            var allExistingForDevice = _authRepo.Get(new AuthenticationInfoQuery
-            {
-                DeviceId = deviceId
+            var existing = _authRepo.Get(
+                new AuthenticationInfoQuery
+                {
+                    DeviceId = deviceId,
+                    UserId = user.Id,
+                    Limit = 1
+                }).Items.FirstOrDefault();
 
-            }).Items;
+            var allExistingForDevice = _authRepo.Get(
+                new AuthenticationInfoQuery
+                {
+                    DeviceId = deviceId
+                }).Items;
 
             foreach (var auth in allExistingForDevice)
             {
@@ -1461,7 +1483,7 @@ namespace Emby.Server.Implementations.Session
 
             if (existing != null)
             {
-                _logger.LogInformation("Reissuing access token: " + existing.AccessToken);
+                _logger.LogInformation("Reissuing access token: {Token}", existing.AccessToken);
                 return existing.AccessToken;
             }
 
@@ -1486,6 +1508,7 @@ namespace Emby.Server.Implementations.Session
             return newToken.AccessToken;
         }
 
+        /// <inheritdoc />
         public void Logout(string accessToken)
         {
             CheckDisposed();
@@ -1495,19 +1518,20 @@ namespace Emby.Server.Implementations.Session
                 throw new ArgumentNullException(nameof(accessToken));
             }
 
-            var existing = _authRepo.Get(new AuthenticationInfoQuery
-            {
-                Limit = 1,
-                AccessToken = accessToken
-
-            }).Items.FirstOrDefault();
+            var existing = _authRepo.Get(
+                new AuthenticationInfoQuery
+                {
+                    Limit = 1,
+                    AccessToken = accessToken
+                }).Items;
 
-            if (existing != null)
+            if (existing.Count > 0)
             {
-                Logout(existing);
+                Logout(existing[0]);
             }
         }
 
+        /// <inheritdoc />
         public void Logout(AuthenticationInfo existing)
         {
             CheckDisposed();
@@ -1533,6 +1557,7 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        /// <inheritdoc />
         public void RevokeUserTokens(Guid userId, string currentAccessToken)
         {
             CheckDisposed();
@@ -1551,6 +1576,7 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        /// <inheritdoc />
         public void RevokeToken(string token)
         {
             Logout(token);
@@ -1607,10 +1633,8 @@ namespace Emby.Server.Implementations.Session
             _deviceManager.SaveCapabilities(deviceId, capabilities);
         }
 
-        private DtoOptions _itemInfoDtoOptions;
-
         /// <summary>
-        /// Converts a BaseItem to a BaseItemInfo
+        /// Converts a BaseItem to a BaseItemInfo.
         /// </summary>
         private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource)
         {
@@ -1685,6 +1709,7 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        /// <inheritdoc />
         public void ReportNowViewingItem(string sessionId, string itemId)
         {
             if (string.IsNullOrEmpty(itemId))
@@ -1692,23 +1717,26 @@ namespace Emby.Server.Implementations.Session
                 throw new ArgumentNullException(nameof(itemId));
             }
 
-            //var item = _libraryManager.GetItemById(new Guid(itemId));
+            var item = _libraryManager.GetItemById(new Guid(itemId));
 
-            //var info = GetItemInfo(item, null, null);
+            var info = GetItemInfo(item, null);
 
-            //ReportNowViewingItem(sessionId, info);
+            ReportNowViewingItem(sessionId, info);
         }
 
+        /// <inheritdoc />
         public void ReportNowViewingItem(string sessionId, BaseItemDto item)
         {
-            //var session = GetSession(sessionId);
+            throw new NotImplementedException();
 
-            //session.NowViewingItem = item;
+            // var session = GetSession(sessionId);
+            // session.NowViewingItem = item;
         }
 
+        /// <inheritdoc />
         public void ReportTranscodingInfo(string deviceId, TranscodingInfo info)
         {
-            var session = Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId));
+            var session = Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId, StringComparison.Ordinal));
 
             if (session != null)
             {
@@ -1716,17 +1744,18 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        /// <inheritdoc />
         public void ClearTranscodingInfo(string deviceId)
         {
             ReportTranscodingInfo(deviceId, null);
         }
 
+        /// <inheritdoc />
         public SessionInfo GetSession(string deviceId, string client, string version)
-        {
-            return Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
-                string.Equals(i.Client, client));
-        }
+            => Sessions.FirstOrDefault(
+                i => string.Equals(i.DeviceId, deviceId, StringComparison.Ordinal) && string.Equals(i.Client, client, StringComparison.Ordinal));
 
+        /// <inheritdoc />
         public SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion)
         {
             if (info == null)
@@ -1759,23 +1788,24 @@ namespace Emby.Server.Implementations.Session
             return LogSessionActivity(appName, appVersion, deviceId, deviceName, remoteEndpoint, user);
         }
 
+        /// <inheritdoc />
         public SessionInfo GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint)
         {
-            var result = _authRepo.Get(new AuthenticationInfoQuery
+            var items = _authRepo.Get(new AuthenticationInfoQuery
             {
-                AccessToken = token
-            });
-
-            var info = result.Items.FirstOrDefault();
+                AccessToken = token,
+                Limit = 1
+            }).Items;
 
-            if (info == null)
+            if (items.Count == 0)
             {
                 return null;
             }
 
-            return GetSessionByAuthenticationToken(info, deviceId, remoteEndpoint, null);
+            return GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null);
         }
 
+        /// <inheritdoc />
         public Task SendMessageToAdminSessions<T>(string name, T data, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1785,6 +1815,7 @@ namespace Emby.Server.Implementations.Session
             return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken);
         }
 
+        /// <inheritdoc />
         public Task SendMessageToUserSessions<T>(List<Guid> userIds, string name, Func<T> dataFn, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1796,11 +1827,10 @@ namespace Emby.Server.Implementations.Session
                 return Task.CompletedTask;
             }
 
-            var data = dataFn();
-
-            return SendMessageToSessions(sessions, name, data, cancellationToken);
+            return SendMessageToSessions(sessions, name, dataFn(), cancellationToken);
         }
 
+        /// <inheritdoc />
         public Task SendMessageToUserSessions<T>(List<Guid> userIds, string name, T data, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1809,6 +1839,7 @@ namespace Emby.Server.Implementations.Session
             return SendMessageToSessions(sessions, name, data, cancellationToken);
         }
 
+        /// <inheritdoc />
         public Task SendMessageToUserDeviceSessions<T>(string deviceId, string name, T data, CancellationToken cancellationToken)
         {
             CheckDisposed();
@@ -1817,22 +1848,5 @@ namespace Emby.Server.Implementations.Session
 
             return SendMessageToSessions(sessions, name, data, cancellationToken);
         }
-
-        public Task SendMessageToUserDeviceAndAdminSessions<T>(string deviceId, string name, T data, CancellationToken cancellationToken)
-        {
-            CheckDisposed();
-
-            var sessions = Sessions
-                .Where(i => string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase) || IsAdminSession(i));
-
-            return SendMessageToSessions(sessions, name, data, cancellationToken);
-        }
-
-        private bool IsAdminSession(SessionInfo s)
-        {
-            var user = _userManager.GetUserById(s.UserId);
-
-            return user != null && user.Policy.IsAdministrator;
-        }
     }
 }