Tons of cleanup working preperation for preview release (#178)
This commit is contained in:
Родитель
d75ae9d4d4
Коммит
a0570b8eef
|
@ -56,7 +56,7 @@ public class XboxLiveConfigurationEditor : EditorWindow
|
|||
|
||||
if (this.configuration != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.configuration.PrimaryServiceConfigId) || this.configuration.TitleId == 0 || string.IsNullOrEmpty(this.configuration.AppId))
|
||||
if (string.IsNullOrEmpty(this.configuration.ServiceConfigurationId) || this.configuration.TitleId == 0 || string.IsNullOrEmpty(this.configuration.AppId))
|
||||
{
|
||||
EditorGUILayout.HelpBox("Your Xbox Live configuration appears invalid. You will need to re-associate your game before you can create a finished build.", MessageType.Warning, true);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class XboxLiveConfigurationEditor : EditorWindow
|
|||
PropertyLabel("Publisher", this.configuration.PublisherDisplayName);
|
||||
PropertyLabel("App ID", this.configuration.AppId);
|
||||
PropertyLabel("Product Family Name", this.configuration.ProductFamilyName);
|
||||
PropertyLabel("SCID", this.configuration.PrimaryServiceConfigId);
|
||||
PropertyLabel("SCID", this.configuration.ServiceConfigurationId);
|
||||
PropertyLabel("Title ID", this.configuration.TitleId.ToString());
|
||||
PropertyLabel("Sandbox", this.configuration.Sandbox);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace Microsoft.Xbox.Services.ConnectedStorage
|
|||
if (resultCallBack != null)
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
var configId = XboxLive.Instance.AppConfig.PrimaryServiceConfigId;
|
||||
var configId = XboxLive.Instance.AppConfig.ServiceConfigurationId;
|
||||
var initTask = GameSaveProvider.GetForUserAsync(xboxLiveUser.WindowsSystemUser, configId).AsTask();
|
||||
if (initTask.Result.Status == GameSaveErrorStatus.Ok)
|
||||
{
|
||||
|
|
|
@ -64,7 +64,7 @@ public class UserProfile : MonoBehaviour
|
|||
public void Start()
|
||||
{
|
||||
// Disable the sign-in button if there's no configuration available.
|
||||
if (XboxLive.Instance.AppConfig == null || XboxLive.Instance.AppConfig.AppId == null)
|
||||
if (XboxLive.Instance.AppConfig == null || XboxLive.Instance.AppConfig.ServiceConfigurationId == null)
|
||||
{
|
||||
this.ConfigAvailable = false;
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class UserProfile : MonoBehaviour
|
|||
{
|
||||
XboxLiveUserManager.Instance.UserForSingleUserMode = Instantiate(this.XboxLiveUserPrefab);
|
||||
this.XboxLiveUser = XboxLiveUserManager.Instance.UserForSingleUserMode;
|
||||
if (XboxLive.Instance.AppConfig != null && XboxLive.Instance.AppConfig.AppId != null)
|
||||
if (XboxLive.Instance.AppConfig != null && XboxLive.Instance.AppConfig.ServiceConfigurationId != null)
|
||||
{
|
||||
this.SignIn();
|
||||
}
|
||||
|
|
|
@ -44,8 +44,6 @@ public class XboxLiveUserInfo : MonoBehaviour
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MockXboxLiveData.Load(Path.Combine(Application.dataPath, "MockData.json"));
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
|
|
|
@ -49,6 +49,7 @@ External/**/lib/
|
|||
External/**/bin/
|
||||
External/**/Debug/
|
||||
External/**/Release/
|
||||
Tests/**/*.dll
|
||||
|
||||
**/*.classpath
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ Global
|
|||
api\Microsoft.Xbox.Services.Shared.projitems*{035e5e11-4a0b-4d1f-ba13-9b62ccafb2b8}*SharedItemsImports = 13
|
||||
api\Microsoft.Xbox.Services.Shared.projitems*{b7130c4b-b36b-4449-80b0-60037fc2e0cd}*SharedItemsImports = 4
|
||||
api\Microsoft.Xbox.Services.Shared.projitems*{cbd81e44-f37f-47d6-b71b-a43a748ae09c}*SharedItemsImports = 4
|
||||
api\Microsoft.Xbox.Services.Shared.projitems*{cfb2ca8f-6611-4dca-981c-4b7afcca19a8}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
|
@ -165,6 +166,54 @@ Global
|
|||
{4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|ARM.ActiveCfg = Release|ARM
|
||||
{4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|x64.ActiveCfg = Release|x64
|
||||
{4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|x86.ActiveCfg = Release|x86
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x64.Build.0 = Debug|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|ARM.ActiveCfg = Debug|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|ARM.Build.0 = Debug|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|x64.ActiveCfg = Debug|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|x64.Build.0 = Debug|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|x86.ActiveCfg = Debug|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.DebugNET35|x86.Build.0 = Debug|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|ARM.Build.0 = Release|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|x64.ActiveCfg = Release|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|x64.Build.0 = Release|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.Release|x86.Build.0 = Release|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|ARM.ActiveCfg = Release|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|ARM.Build.0 = Release|ARM
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|x64.ActiveCfg = Release|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|x64.Build.0 = Release|x64
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|x86.ActiveCfg = Release|Win32
|
||||
{8F96710E-5169-4917-8874-7DE248F4D243}.ReleaseNET35|x86.Build.0 = Release|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|x64.Build.0 = Debug|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|ARM.ActiveCfg = Debug|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|ARM.Build.0 = Debug|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|x64.ActiveCfg = Debug|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|x64.Build.0 = Debug|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|x86.ActiveCfg = Debug|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.DebugNET35|x86.Build.0 = Debug|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|ARM.Build.0 = Release|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|x64.ActiveCfg = Release|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|x64.Build.0 = Release|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.Release|x86.Build.0 = Release|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|ARM.ActiveCfg = Release|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|ARM.Build.0 = Release|ARM
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|x64.ActiveCfg = Release|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|x64.Build.0 = Release|x64
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|x86.ActiveCfg = Release|Win32
|
||||
{1B0DFB7F-2CD5-48DE-80D4-5CC56C22AEEE}.ReleaseNET35|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
public string AgeGroup { get; set; }
|
||||
public string Privileges { get; set; }
|
||||
public string WebAccountId { get; set; }
|
||||
public AuthConfig AuthConfig { get; set; }
|
||||
public IntPtr XboxLiveUserPtr { get; }
|
||||
|
||||
public Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh)
|
||||
|
@ -37,10 +36,10 @@ namespace Microsoft.Xbox.Services.System
|
|||
return Task.FromResult(new SignInResult(SignInStatus.Success));
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
public Task<GetTokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
{
|
||||
string[] authHeaderParts = authHeader.Substring(9).Split(';');
|
||||
return Task.FromResult(new TokenAndSignatureResult
|
||||
return Task.FromResult(new GetTokenAndSignatureResult
|
||||
{
|
||||
Gamertag = this.Gamertag,
|
||||
XboxUserId = this.XboxUserId,
|
||||
|
|
|
@ -3,17 +3,11 @@
|
|||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
|
||||
public partial class XboxLive
|
||||
{
|
||||
public static bool UseMockServices
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public static bool UseMockHttp
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,11 +5,11 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
public partial class XboxLiveAppConfiguration
|
||||
{
|
||||
public static XboxLiveAppConfiguration Load(string path)
|
||||
private static XboxLiveAppConfiguration Load()
|
||||
{
|
||||
return new XboxLiveAppConfiguration
|
||||
{
|
||||
PrimaryServiceConfigId = "00000000-0000-0000-0000-0000694f5acb",
|
||||
ServiceConfigurationId = "00000000-0000-0000-0000-0000694f5acb",
|
||||
TitleId = 1766808267,
|
||||
Environment = string.Empty,
|
||||
Sandbox = "JDTDWX.0",
|
||||
|
|
|
@ -9,10 +9,5 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public static bool UseMockHttp
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,28 +4,43 @@
|
|||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System.IO;
|
||||
using global::Microsoft.Xbox.Services.System;
|
||||
using global::System;
|
||||
using global::System.Runtime.InteropServices;
|
||||
|
||||
public partial class XboxLiveAppConfiguration
|
||||
{
|
||||
public static XboxLiveAppConfiguration Load(string path)
|
||||
private static XboxLiveAppConfiguration Load()
|
||||
{
|
||||
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
|
||||
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
|
||||
|
||||
string fullPath = Path.Combine(installedLocation.Path, path);
|
||||
if (!File.Exists(fullPath))
|
||||
IntPtr appConfigPtr;
|
||||
var result = GetXboxLiveAppConfigSingleton(out appConfigPtr);
|
||||
if (result != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
throw new FileNotFoundException(string.Format("Unable to find Xbox Live app configuration file '{0}'.", path));
|
||||
throw new XboxException(result);
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(fullPath);
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
var appConfigStruct = Marshal.PtrToStructure<XSAPI_XBOX_LIVE_APP_CONFIG>(appConfigPtr);
|
||||
|
||||
return new XboxLiveAppConfiguration
|
||||
{
|
||||
throw new XboxException(string.Format("Xbox Live app configeration file '{0}' was empty.", path));
|
||||
TitleId = appConfigStruct.titleId,
|
||||
Environment = MarshalingHelpers.Utf8ToString(appConfigStruct.environment),
|
||||
Sandbox = MarshalingHelpers.Utf8ToString(appConfigStruct.sandbox),
|
||||
ServiceConfigurationId = MarshalingHelpers.Utf8ToString(appConfigStruct.scid)
|
||||
};
|
||||
}
|
||||
|
||||
return JsonSerialization.FromJson<XboxLiveAppConfiguration>(content);
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct XSAPI_XBOX_LIVE_APP_CONFIG
|
||||
{
|
||||
public UInt32 titleId;
|
||||
public IntPtr scid;
|
||||
public IntPtr environment;
|
||||
public IntPtr sandbox;
|
||||
};
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT GetXboxLiveAppConfigSingleton(
|
||||
out IntPtr ppConfig);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System.Threading.Tasks;
|
||||
using Microsoft.Xbox.Services.System;
|
||||
|
||||
public partial class XboxLiveUser
|
||||
|
@ -14,41 +13,51 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
public XboxLiveUser(Windows.System.User systemUser)
|
||||
{
|
||||
var user = new UserImpl(systemUser);
|
||||
var userImpl = new UserImpl(systemUser);
|
||||
this.userImpl = userImpl;
|
||||
|
||||
// The UserImpl monitors the underlying system for sign out events
|
||||
// and notifies us that a user has been signed out. We can then
|
||||
// pass that event on the application with a concrete reference.
|
||||
user.SignInCompleted += (sender, args) =>
|
||||
userImpl.SignInCompleted += (sender, args) =>
|
||||
{
|
||||
OnSignInCompleted(this);
|
||||
};
|
||||
user.SignOutCompleted += (sender, args) =>
|
||||
if (SignInCompleted != null)
|
||||
{
|
||||
OnSignOutCompleted(this);
|
||||
SignInCompleted(null, new SignInCompletedEventArgs(this));
|
||||
}
|
||||
};
|
||||
userImpl.SignOutCompleted += (sender, args) =>
|
||||
{
|
||||
if (SignOutCompleted != null)
|
||||
{
|
||||
SignOutCompleted(null, new SignOutCompletedEventArgs(this));
|
||||
}
|
||||
};
|
||||
|
||||
this.userImpl = user;
|
||||
}
|
||||
|
||||
internal XboxLiveUser(global::System.IntPtr xboxLiveUserPtr)
|
||||
{
|
||||
var user = new UserImpl(xboxLiveUserPtr);
|
||||
var userImpl = new UserImpl(xboxLiveUserPtr);
|
||||
this.userImpl = userImpl;
|
||||
|
||||
// The UserImpl monitors the underlying system for sign out events
|
||||
// and notifies us that a user has been signed out. We can then
|
||||
// pass that event on the application with a concrete reference.
|
||||
user.SignInCompleted += (sender, args) =>
|
||||
userImpl.SignInCompleted += (sender, args) =>
|
||||
{
|
||||
OnSignInCompleted(this);
|
||||
};
|
||||
user.SignOutCompleted += (sender, args) =>
|
||||
if (SignInCompleted != null)
|
||||
{
|
||||
OnSignOutCompleted(this);
|
||||
SignInCompleted(null, new SignInCompletedEventArgs(this));
|
||||
}
|
||||
};
|
||||
|
||||
this.userImpl = user;
|
||||
user.UpdatePropertiesFromXboxLiveUserPtr();
|
||||
userImpl.SignOutCompleted += (sender, args) =>
|
||||
{
|
||||
if (SignOutCompleted != null)
|
||||
{
|
||||
SignOutCompleted(null, new SignOutCompletedEventArgs(this));
|
||||
}
|
||||
};
|
||||
userImpl.UpdatePropertiesFromXboxLiveUserPtr();
|
||||
}
|
||||
|
||||
public Windows.System.User WindowsSystemUser
|
||||
|
@ -63,20 +72,5 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
get { return (this.userImpl as UserImpl); }
|
||||
}
|
||||
|
||||
internal static void CleanupEventHandler()
|
||||
{
|
||||
foreach (var eh in signInDelegates)
|
||||
{
|
||||
InternalSignInCompleted -= eh;
|
||||
}
|
||||
signInDelegates.Clear();
|
||||
|
||||
foreach (var eh in signOutDelegates)
|
||||
{
|
||||
InternalSignOutCompleted -= eh;
|
||||
}
|
||||
signOutDelegates.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -100,7 +100,6 @@
|
|||
<Compile Include="Statistics\Manager\StatisticEvent.cs" />
|
||||
<Compile Include="Statistics\Manager\StatisticManager.cs" />
|
||||
<Compile Include="System\TitleCallableUI.cs" />
|
||||
<Compile Include="System\TokenRequestResult.cs" />
|
||||
<Compile Include="System\UserImpl.cs" />
|
||||
<Compile Include="Common\XboxLiveUser.cs" />
|
||||
<Compile Include="Common\XboxLiveAppConfiguration.cs" />
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Runtime.InteropServices;
|
||||
using Microsoft.Xbox.Services.Presence;
|
||||
using System;
|
||||
|
||||
public partial class SocialManager : ISocialManager
|
||||
|
@ -26,19 +25,14 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerAddLocalUser(user.Impl.XboxLiveUserPtr, extraDetailLevel, cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerAddLocalUser(user.Impl.XboxLiveUserPtr, extraDetailLevel, out cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
m_localUsers.Add(user);
|
||||
|
@ -48,19 +42,13 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
m_localUsers.Remove(user);
|
||||
|
@ -70,25 +58,18 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cGroupPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cGroupPtr;
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromFilters(user.Impl.XboxLiveUserPtr, presenceFilter, relationshipFilter, cGroupPtr, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromFilters(user.Impl.XboxLiveUserPtr, presenceFilter, relationshipFilter, out cGroupPtr, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Handles returned objects
|
||||
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(Marshal.ReadIntPtr(cGroupPtr));
|
||||
Marshal.FreeHGlobal(cGroupPtr);
|
||||
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(cGroupPtr);
|
||||
m_groups.Add(socialUserGroup);
|
||||
|
||||
return socialUserGroup;
|
||||
|
@ -100,41 +81,23 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
if (xboxUserIdList == null) throw new ArgumentNullException("xboxUserIdList");
|
||||
|
||||
// Allocates memory for parameters
|
||||
List<IntPtr> userIdPtrs = new List<IntPtr>();
|
||||
for (int i = 0; i < xboxUserIdList.Count; i++)
|
||||
{
|
||||
IntPtr cXuid = Marshal.StringToHGlobalAnsi(xboxUserIdList[i]);
|
||||
userIdPtrs.Add(cXuid);
|
||||
}
|
||||
IntPtr cUserIds = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>() * xboxUserIdList.Count);
|
||||
Marshal.Copy(userIdPtrs.ToArray(), 0, cUserIds, xboxUserIdList.Count);
|
||||
IntPtr cUserIds = MarshalingHelpers.StringListToHGlobalUtf8StringArray(xboxUserIdList);
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cGroupPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cGroupPtr;
|
||||
IntPtr cErrMessage;
|
||||
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromList(user.Impl.XboxLiveUserPtr, cUserIds, (uint)xboxUserIdList.Count, cGroupPtr, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromList(user.Impl.XboxLiveUserPtr, cUserIds, (uint)xboxUserIdList.Count, out cGroupPtr, out cErrMessage);
|
||||
|
||||
MarshalingHelpers.FreeHGlobalUtf8StringArray(cUserIds, xboxUserIdList.Count);
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Cleans up parameters
|
||||
foreach (IntPtr ptr in userIdPtrs)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
Marshal.FreeHGlobal(cUserIds);
|
||||
|
||||
// Handles returned objects
|
||||
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(Marshal.ReadIntPtr(cGroupPtr));
|
||||
Marshal.FreeHGlobal(cGroupPtr);
|
||||
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(cGroupPtr);
|
||||
m_groups.Add(socialUserGroup);
|
||||
|
||||
return socialUserGroup;
|
||||
|
@ -146,37 +109,20 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
if (users == null) throw new ArgumentNullException("users");
|
||||
|
||||
// Allocates memory for parameters
|
||||
List<IntPtr> userIdPtrs = new List<IntPtr>();
|
||||
for (int i = 0; i < users.Count; i++)
|
||||
{
|
||||
IntPtr cXuid = Marshal.StringToHGlobalUni(users[i]);
|
||||
userIdPtrs.Add(cXuid);
|
||||
}
|
||||
IntPtr cUserIds = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>() * users.Count);
|
||||
Marshal.Copy(userIdPtrs.ToArray(), 0, cUserIds, users.Count);
|
||||
IntPtr cUserIds = MarshalingHelpers.StringListToHGlobalUtf8StringArray(users);
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cErrMessage;
|
||||
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerUpdateSocialUserGroup(socialGroup.GetPtr(), cUserIds, (uint)users.Count, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringUni(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerUpdateSocialUserGroup(socialGroup.GetPtr(), cUserIds, (uint)users.Count, out cErrMessage);
|
||||
|
||||
MarshalingHelpers.FreeHGlobalUtf8StringArray(cUserIds, users.Count);
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Cleans up parameters
|
||||
foreach (IntPtr ptr in userIdPtrs)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
Marshal.FreeHGlobal(cUserIds);
|
||||
|
||||
// Does local work
|
||||
socialGroup.Refresh();
|
||||
}
|
||||
|
@ -185,19 +131,13 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
if (xboxSocialUserGroup == null) throw new ArgumentNullException("xboxSocialUserGroup");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerDestroySocialUserGroup(xboxSocialUserGroup.GetPtr(), cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerDestroySocialUserGroup(xboxSocialUserGroup.GetPtr(), out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Does local work
|
||||
|
@ -206,17 +146,11 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
|
||||
public IList<SocialEvent> DoWork()
|
||||
{
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cEventsCount = Marshal.AllocHGlobal(Marshal.SizeOf<Int32>());
|
||||
|
||||
UInt32 eventsCount;
|
||||
// Invokes the c method
|
||||
IntPtr eventsPtr = SocialManagerDoWork(cEventsCount);
|
||||
IntPtr eventsPtr = SocialManagerDoWork(out eventsCount);
|
||||
|
||||
// Does local work
|
||||
uint eventsCount = (uint)Marshal.ReadInt32(cEventsCount);
|
||||
Marshal.FreeHGlobal(cEventsCount);
|
||||
|
||||
List<SocialEvent> events = new List<SocialEvent>();
|
||||
|
||||
if (eventsCount > 0)
|
||||
|
@ -250,19 +184,13 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = SocialManagerSetRichPresencePollingStatus(user.Impl.XboxLiveUserPtr, shouldEnablePolling, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = SocialManagerSetRichPresencePollingStatus(user.Impl.XboxLiveUserPtr, shouldEnablePolling, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Does local work
|
||||
|
@ -271,28 +199,28 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
|
||||
// Marshaling
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerAddLocalUser(IntPtr user, SocialManagerExtraDetailLevel extraDetailLevel, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerAddLocalUser(IntPtr user, SocialManagerExtraDetailLevel extraDetailLevel, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerRemoveLocalUser(IntPtr user, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerRemoveLocalUser(IntPtr user, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerCreateSocialUserGroupFromFilters(IntPtr user, PresenceFilter presenceDetailFilter, RelationshipFilter filter, IntPtr returnGroup, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerCreateSocialUserGroupFromFilters(IntPtr user, PresenceFilter presenceDetailFilter, RelationshipFilter filter, out IntPtr returnGroup, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerCreateSocialUserGroupFromList(IntPtr group, IntPtr users, UInt32 usersCount, IntPtr returnGroup, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerCreateSocialUserGroupFromList(IntPtr group, IntPtr users, UInt32 usersCount, out IntPtr returnGroup, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerUpdateSocialUserGroup(IntPtr group, IntPtr users, UInt32 usersCount, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerUpdateSocialUserGroup(IntPtr group, IntPtr users, UInt32 usersCount, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerDestroySocialUserGroup(IntPtr group, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerDestroySocialUserGroup(IntPtr group, out IntPtr errMessage);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern IntPtr SocialManagerDoWork(IntPtr numOfEvents);
|
||||
private static extern IntPtr SocialManagerDoWork(out UInt32 numOfEvents);
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT SocialManagerSetRichPresencePollingStatus(IntPtr user, bool shouldEnablePolling, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT SocialManagerSetRichPresencePollingStatus(IntPtr user, bool shouldEnablePolling, out IntPtr errMessage);
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
TITLE_HISTORY cTitleHistory = Marshal.PtrToStructure<TITLE_HISTORY>(titleHistoryPtr);
|
||||
HasUserPlayed = cTitleHistory.UserHasPlayed;
|
||||
|
||||
// todo test
|
||||
LastTimeUserPlayed = DateTimeOffset.FromUnixTimeSeconds(cTitleHistory.LastTimeUserPlayed);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,24 +15,18 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
|
|||
private readonly List<XboxLiveUser> m_localUsers = new List<XboxLiveUser>();
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerAddLocalUser(IntPtr user, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerAddLocalUser(IntPtr user, out IntPtr errMessage);
|
||||
public void AddLocalUser(XboxLiveUser user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerAddLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerAddLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Does local work
|
||||
|
@ -40,24 +34,18 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
|
|||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerRemoveLocalUser(IntPtr user, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerRemoveLocalUser(IntPtr user, out IntPtr errMessage);
|
||||
public void RemoveLocalUser(XboxLiveUser user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Does local work
|
||||
|
@ -65,40 +53,29 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
|
|||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerRequestFlushToService(IntPtr user, bool isHighPriority, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerRequestFlushToService(IntPtr user, bool isHighPriority, out IntPtr errMessage);
|
||||
public void RequestFlushToService(XboxLiveUser user, bool isHighPriority = false)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerRequestFlushToService(user.Impl.XboxLiveUserPtr, isHighPriority, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerRequestFlushToService(user.Impl.XboxLiveUserPtr, isHighPriority, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern IntPtr StatsManagerDoWork(IntPtr numOfEvents);
|
||||
private static extern IntPtr StatsManagerDoWork(out Int32 numOfEvents);
|
||||
public IList<StatisticEvent> DoWork()
|
||||
{
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cEventsCount = Marshal.AllocHGlobal(Marshal.SizeOf<Int32>());
|
||||
|
||||
Int32 eventsCount;
|
||||
// Invokes the c method
|
||||
IntPtr eventsPtr = StatsManagerDoWork(cEventsCount);
|
||||
|
||||
// Does local work
|
||||
uint eventsCount = (uint)Marshal.ReadInt32(cEventsCount);
|
||||
Marshal.FreeHGlobal(cEventsCount);
|
||||
IntPtr eventsPtr = StatsManagerDoWork(out eventsCount);
|
||||
|
||||
List<StatisticEvent> events = new List<StatisticEvent>();
|
||||
|
||||
|
@ -123,176 +100,134 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
|
|||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticNumberData(IntPtr user, string statName, double value, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticNumberData(IntPtr user, string statName, double value, out IntPtr errMessage);
|
||||
public void SetStatisticNumberData(XboxLiveUser user, string statName, double value)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticNumberData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticNumberData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticIntegerData(IntPtr user, string statName, long value, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticIntegerData(IntPtr user, string statName, long value, out IntPtr errMessage);
|
||||
public void SetStatisticIntegerData(XboxLiveUser user, string statName, long value)
|
||||
{
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticIntegerData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticIntegerData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticStringData(IntPtr user, string statName, string value, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerSetStatisticStringData(IntPtr user, string statName, string value, out IntPtr errMessage);
|
||||
public void SetStatisticStringData(XboxLiveUser user, string statName, string value)
|
||||
{
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticStringData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerSetStatisticStringData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerDeleteStat(IntPtr user, string statName, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerDeleteStat(IntPtr user, string statName, out IntPtr errMessage);
|
||||
public void DeleteStatistic(XboxLiveUser user, string statName)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerDeleteStat(user.Impl.XboxLiveUserPtr, statName, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerDeleteStat(user.Impl.XboxLiveUserPtr, statName, out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerGetLeaderboard(IntPtr user, string statName, IntPtr query, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerGetLeaderboard(IntPtr user, string statName, IntPtr query, out IntPtr errMessage);
|
||||
public void GetLeaderboard(XboxLiveUser user, string statName, LeaderboardQuery query)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerGetLeaderboard(user.Impl.XboxLiveUserPtr, statName, query.GetPtr(), cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerGetLeaderboard(user.Impl.XboxLiveUserPtr, statName, query.GetPtr(), out cErrMessage);
|
||||
|
||||
if (errCode > 0)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerGetSocialLeaderboard(IntPtr user, string statName, string socialGroup, IntPtr query, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerGetSocialLeaderboard(IntPtr user, string statName, string socialGroup, IntPtr query, out IntPtr errMessage);
|
||||
public void GetSocialLeaderboard(XboxLiveUser user, string statName, string socialGroup, LeaderboardQuery query)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerGetSocialLeaderboard(user.Impl.XboxLiveUserPtr, statName, socialGroup, query.GetPtr(), cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerGetSocialLeaderboard(user.Impl.XboxLiveUserPtr, statName, socialGroup, query.GetPtr(), out cErrMessage);
|
||||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerGetStat(IntPtr user, IntPtr statName, IntPtr statValue, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerGetStat(IntPtr user, IntPtr statName, out IntPtr statValue, out IntPtr errMessage);
|
||||
public StatisticValue GetStatistic(XboxLiveUser user, string statName)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cStatValue = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cStatName = Marshal.StringToHGlobalAnsi(statName);
|
||||
IntPtr cStatValue;
|
||||
IntPtr cErrMessage;
|
||||
IntPtr cStatName = MarshalingHelpers.StringToHGlobalUtf8(statName);
|
||||
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerGetStat(user.Impl.XboxLiveUserPtr, cStatName, cStatValue, cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
Marshal.FreeHGlobal(cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerGetStat(user.Impl.XboxLiveUserPtr, cStatName, out cStatValue, out cErrMessage);
|
||||
|
||||
Marshal.FreeHGlobal(cStatName);
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Handles returned objects
|
||||
StatisticValue statValue = new StatisticValue(Marshal.ReadIntPtr(cStatValue));
|
||||
Marshal.FreeHGlobal(cStatValue);
|
||||
StatisticValue statValue = new StatisticValue(cStatValue);
|
||||
|
||||
return statValue;
|
||||
}
|
||||
|
||||
[DllImport(XboxLive.FlatCDllName)]
|
||||
private static extern XSAPI_RESULT StatsManagerGetStatNames(IntPtr user, IntPtr statNameList, IntPtr statNameListCount, IntPtr errMessage);
|
||||
private static extern XSAPI_RESULT StatsManagerGetStatNames(IntPtr user, out IntPtr statNameList, out UInt32 statNameListCount, out IntPtr errMessage);
|
||||
public IList<string> GetStatisticNames(XboxLiveUser user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
// Allocates memory for returned objects
|
||||
IntPtr cStatListPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cStatListCount = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
|
||||
|
||||
IntPtr cStatListPtr;
|
||||
UInt32 statListCount;
|
||||
IntPtr cErrMessage;
|
||||
// Invokes the c method
|
||||
XSAPI_RESULT errCode = StatsManagerGetStatNames(user.Impl.XboxLiveUserPtr, cStatListPtr, cStatListCount, cErrMessage);
|
||||
XSAPI_RESULT errCode = StatsManagerGetStatNames(user.Impl.XboxLiveUserPtr, out cStatListPtr, out statListCount, out cErrMessage);
|
||||
|
||||
// Handles error
|
||||
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
|
||||
|
@ -300,29 +235,9 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
|
|||
|
||||
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
// todo do something
|
||||
throw new XboxException(errCode, cErrMessage);
|
||||
}
|
||||
|
||||
// Handles returned objects
|
||||
uint statListCount = (uint)Marshal.ReadInt32(cStatListCount);
|
||||
Marshal.FreeHGlobal(cStatListCount);
|
||||
|
||||
List<string> statList = new List<string>();
|
||||
|
||||
if (statListCount > 0)
|
||||
{
|
||||
IntPtr cListPtr = Marshal.ReadIntPtr(cStatListPtr);
|
||||
IntPtr[] cStatList = new IntPtr[statListCount];
|
||||
Marshal.Copy(cListPtr, cStatList, 0, (int)statListCount);
|
||||
|
||||
for (uint i = 0; i < statListCount; i++)
|
||||
{
|
||||
statList.Add(Marshal.PtrToStringAnsi(cStatList[i]));
|
||||
}
|
||||
}
|
||||
Marshal.FreeHGlobal(cStatListPtr);
|
||||
|
||||
return statList;
|
||||
return MarshalingHelpers.Utf8StringArrayToStringList(cStatListPtr, statListCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using Windows.Security.Authentication.Web.Core;
|
||||
|
||||
internal class TokenRequestResult
|
||||
{
|
||||
public WebProviderError ResponseError { get; set; }
|
||||
|
||||
public WebTokenRequestStatus ResponseStatus { get; set; }
|
||||
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public WebProviderError ProviderError { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
|
||||
public string WebAccountId { get; set; }
|
||||
|
||||
public TokenRequestResult(WebTokenRequestResult result)
|
||||
{
|
||||
if (result != null)
|
||||
{
|
||||
this.ResponseStatus = result.ResponseStatus;
|
||||
this.ResponseError = result.ResponseError;
|
||||
|
||||
if (result.ResponseData != null && result.ResponseData.Count > 0)
|
||||
{
|
||||
var responseData = result.ResponseData.FirstOrDefault();
|
||||
|
||||
this.Properties = responseData.Properties;
|
||||
this.ProviderError = responseData.ProviderError;
|
||||
this.Token = responseData.Token;
|
||||
this.WebAccountId = responseData.WebAccount?.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
public string AgeGroup { get; private set; }
|
||||
public string Privileges { get; private set; }
|
||||
public string WebAccountId { get; private set; }
|
||||
public AuthConfig AuthConfig { get; private set; } // TODO remove this
|
||||
public User CreationContext { get; private set; }
|
||||
public IntPtr XboxLiveUserPtr { get; private set; }
|
||||
|
||||
|
@ -48,7 +47,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
{
|
||||
throw new XboxException(result);
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
|
@ -62,16 +60,7 @@ namespace Microsoft.Xbox.Services.System
|
|||
{
|
||||
signOutHandlerContext = AddSignOutCompletedHandler(OnSignOutCompleted);
|
||||
xboxLiveUserInstanceMap[XboxLiveUserPtr] = this;
|
||||
|
||||
// TODO: This config is broken.
|
||||
var appConfig = XboxLiveAppConfiguration.Instance;
|
||||
this.AuthConfig = new AuthConfig
|
||||
{
|
||||
Sandbox = appConfig.Sandbox,
|
||||
EnvironmentPrefix = appConfig.EnvironmentPrefix,
|
||||
Environment = appConfig.Environment,
|
||||
UseCompactTicket = appConfig.UseFirstPartyToken
|
||||
};
|
||||
var appConfig = XboxLiveAppConfiguration.SingletonInstance;
|
||||
}
|
||||
|
||||
~UserImpl()
|
||||
|
@ -177,9 +166,9 @@ namespace Microsoft.Xbox.Services.System
|
|||
}
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
public Task<GetTokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<TokenAndSignatureResult>();
|
||||
var tcs = new TaskCompletionSource<GetTokenAndSignatureResult>();
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
|
@ -196,7 +185,7 @@ namespace Microsoft.Xbox.Services.System
|
|||
}
|
||||
|
||||
int contextKey;
|
||||
var context = XsapiCallbackContext<UserImpl, TokenAndSignatureResult>.CreateContext(this, tcs, out contextKey);
|
||||
var context = XsapiCallbackContext<UserImpl, GetTokenAndSignatureResult>.CreateContext(this, tcs, out contextKey);
|
||||
context.PointersToFree = new List<IntPtr> { pHttpMethod, pUrl, pHeaders, pBody };
|
||||
|
||||
var result = XboxLiveUserGetTokenAndSignature(
|
||||
|
@ -223,12 +212,12 @@ namespace Microsoft.Xbox.Services.System
|
|||
{
|
||||
int contextKey = context.ToInt32();
|
||||
|
||||
XsapiCallbackContext<UserImpl, TokenAndSignatureResult> contextObject;
|
||||
if (XsapiCallbackContext<UserImpl, TokenAndSignatureResult>.TryRemove(contextKey, out contextObject))
|
||||
XsapiCallbackContext<UserImpl, GetTokenAndSignatureResult> contextObject;
|
||||
if (XsapiCallbackContext<UserImpl, GetTokenAndSignatureResult>.TryRemove(contextKey, out contextObject))
|
||||
{
|
||||
if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
contextObject.TaskCompletionSource.SetResult(new TokenAndSignatureResult
|
||||
contextObject.TaskCompletionSource.SetResult(new GetTokenAndSignatureResult
|
||||
{
|
||||
WebAccountId = MarshalingHelpers.Utf8ToString(payload.WebAccountId),
|
||||
Privileges = MarshalingHelpers.Utf8ToString(payload.Privileges),
|
||||
|
@ -237,7 +226,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
XboxUserId = MarshalingHelpers.Utf8ToString(payload.XboxUserId),
|
||||
Signature = MarshalingHelpers.Utf8ToString(payload.Signature),
|
||||
Token = MarshalingHelpers.Utf8ToString(payload.Token)
|
||||
//TokenRequestResultStatus = tokenResult.ResponseStatus // TODO
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -333,7 +321,7 @@ namespace Microsoft.Xbox.Services.System
|
|||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct XSAPI_SIGN_IN_RESULT
|
||||
{
|
||||
{
|
||||
public SignInStatus status;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,10 @@
|
|||
namespace Microsoft.Xbox.Services.UWP.UnitTests
|
||||
{
|
||||
using global::System;
|
||||
using Windows.System;
|
||||
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
|
||||
using Microsoft.Xbox.Services.System;
|
||||
using global::System.Linq;
|
||||
using Moq;
|
||||
using global::System.Threading.Tasks;
|
||||
using UITestMethod = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.UITestMethodAttribute;
|
||||
using Windows.Security.Authentication.Web.Core;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Threading;
|
||||
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
|
||||
using Windows.System;
|
||||
|
||||
[TestClass]
|
||||
public class UserTest
|
||||
|
@ -30,28 +24,9 @@ namespace Microsoft.Xbox.Services.UWP.UnitTests
|
|||
private const int mockErrorcode = 9999;
|
||||
private const string mockErrorMessage = "mock error message";
|
||||
|
||||
private TokenRequestResult CreateSuccessTokenResponse()
|
||||
{
|
||||
var result = new TokenRequestResult(null);
|
||||
result.ResponseStatus = WebTokenRequestStatus.Success;
|
||||
result.Token = mockToken;
|
||||
result.WebAccountId = mockWebAccountId;
|
||||
result.Properties = new Dictionary<string, string>();
|
||||
result.Properties.Add("XboxUserId", mockXuid);
|
||||
result.Properties.Add("Gamertag", mockGamerTag);
|
||||
result.Properties.Add("AgeGroup", mockAgeGroup);
|
||||
result.Properties.Add("Environment", mockEnvironment);
|
||||
result.Properties.Add("Sandbox", mockSandbox);
|
||||
result.Properties.Add("Signature", mockSignature);
|
||||
result.Properties.Add("Privileges", mockPrivileges);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
XboxLiveUser.CleanupEventHandler();
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
|
@ -71,156 +46,5 @@ namespace Microsoft.Xbox.Services.UWP.UnitTests
|
|||
var xbluser = new XboxLiveUser(systemUser);
|
||||
Assert.AreEqual(systemUser.NonRoamableId, xbluser.WindowsSystemUser.NonRoamableId);
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSigninSilentlySuccess()
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
|
||||
AutoResetEvent signinEvent = new AutoResetEvent(false);
|
||||
XboxLiveUser.SignInCompleted += (Object o, SignInCompletedEventArgs args) =>
|
||||
{
|
||||
Assert.AreEqual(args.User, user);
|
||||
signinEvent.Set();
|
||||
};
|
||||
var response = CreateSuccessTokenResponse();
|
||||
|
||||
// Create xbl user with system user
|
||||
var silentResult = await user.SignInSilentlyAsync();
|
||||
Assert.AreEqual(silentResult.Status, SignInStatus.Success);
|
||||
|
||||
Assert.IsTrue(user.IsSignedIn);
|
||||
Assert.AreEqual(user.Gamertag, mockGamerTag);
|
||||
Assert.AreEqual(user.XboxUserId, mockXuid);
|
||||
Assert.AreEqual(user.AgeGroup, mockAgeGroup);
|
||||
Assert.AreEqual(user.Privileges, mockPrivileges);
|
||||
Assert.AreEqual(user.WebAccountId, mockWebAccountId);
|
||||
|
||||
Assert.IsTrue(signinEvent.WaitOne(100), "wait signin event time out");
|
||||
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSigninWithUiSuccess()
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
|
||||
AutoResetEvent signinEvent = new AutoResetEvent(false);
|
||||
XboxLiveUser.SignInCompleted += ((Object o, SignInCompletedEventArgs args) =>
|
||||
{
|
||||
Assert.AreEqual(args.User, user);
|
||||
signinEvent.Set();
|
||||
});
|
||||
|
||||
var response = CreateSuccessTokenResponse();
|
||||
|
||||
var signinResult = await user.SignInAsync();
|
||||
Assert.AreEqual(signinResult.Status, SignInStatus.Success);
|
||||
Assert.IsTrue(user.IsSignedIn);
|
||||
Assert.AreEqual(user.Gamertag, mockGamerTag);
|
||||
Assert.AreEqual(user.XboxUserId, mockXuid);
|
||||
Assert.AreEqual(user.AgeGroup, mockAgeGroup);
|
||||
Assert.AreEqual(user.Privileges, mockPrivileges);
|
||||
Assert.AreEqual(user.WebAccountId, mockWebAccountId);
|
||||
|
||||
Assert.IsTrue(signinEvent.WaitOne(100), "wait signin event time out");
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSigninSilentlyUserInteractionRequired()
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
var result = new TokenRequestResult(null);
|
||||
result.ResponseStatus = WebTokenRequestStatus.UserInteractionRequired;
|
||||
|
||||
var signinResult = await user.SignInSilentlyAsync();
|
||||
Assert.AreEqual(signinResult.Status, SignInStatus.UserInteractionRequired);
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSigninUIUserCancel()
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
var result = new TokenRequestResult(null);
|
||||
result.ResponseStatus = WebTokenRequestStatus.UserCancel;
|
||||
|
||||
var signinResult = await user.SignInAsync();
|
||||
Assert.AreEqual(signinResult.Status, SignInStatus.UserCancel);
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSigninProviderError()
|
||||
// provider error
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
var result = new TokenRequestResult(null);
|
||||
result.ResponseStatus = WebTokenRequestStatus.ProviderError;
|
||||
result.ResponseError = new WebProviderError(mockErrorcode, mockErrorMessage);
|
||||
|
||||
// ProviderError will convert to exception
|
||||
try
|
||||
{
|
||||
var silentResult = await user.SignInSilentlyAsync();
|
||||
}
|
||||
catch (XboxException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.HResult, mockErrorcode);
|
||||
Assert.IsFalse(string.IsNullOrEmpty(ex.Message));
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("No exception was thrown.");
|
||||
}
|
||||
|
||||
[TestCategory("XboxLiveUser")]
|
||||
[TestMethod]
|
||||
public async Task UserSignOut()
|
||||
// provider error
|
||||
{
|
||||
var user = new XboxLiveUser();
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
|
||||
AutoResetEvent signoutEvent = new AutoResetEvent(false);
|
||||
XboxLiveUser.SignOutCompleted += ((Object o, SignOutCompletedEventArgs args) =>
|
||||
{
|
||||
Assert.AreEqual(args.User, user);
|
||||
signoutEvent.Set();
|
||||
});
|
||||
|
||||
var successResponse = CreateSuccessTokenResponse();
|
||||
var errorResponse = new TokenRequestResult(null);
|
||||
errorResponse.ResponseStatus = WebTokenRequestStatus.UserInteractionRequired;
|
||||
|
||||
var silentResult = await user.SignInSilentlyAsync();
|
||||
Assert.AreEqual(silentResult.Status, SignInStatus.Success);
|
||||
Assert.IsTrue(user.IsSignedIn);
|
||||
|
||||
try
|
||||
{
|
||||
var token = await user.GetTokenAndSignatureAsync("GET", "", "");
|
||||
}
|
||||
catch(XboxException ex)
|
||||
{
|
||||
Assert.IsFalse(string.IsNullOrEmpty(ex.Message));
|
||||
Assert.IsFalse(user.IsSignedIn);
|
||||
|
||||
Assert.IsTrue(signoutEvent.WaitOne(100), "wait signout event time out");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("No exception was thrown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Xbox.Services.UnitTests
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Diagnostics;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Xbox.Services.Shared;
|
||||
|
||||
[TestClass]
|
||||
public class CallBufferTimerTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task BasicCallback()
|
||||
{
|
||||
bool completed = false;
|
||||
|
||||
CallBufferTimer<object> timer = new CallBufferTimer<object>(TimeSpan.FromSeconds(1));
|
||||
timer.Completed += (sender, o) => { completed = true; };
|
||||
|
||||
var timerTask = timer.Fire(new List<object> { new object() });
|
||||
|
||||
var result = await Task.WhenAny(timerTask, Task.Delay(TimeSpan.FromSeconds(2)));
|
||||
if (result != timerTask)
|
||||
{
|
||||
// This means the delay task completed.
|
||||
Assert.Fail("Timer was never called.");
|
||||
}
|
||||
|
||||
Assert.IsTrue(completed);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ThrottledCallback()
|
||||
{
|
||||
int completedCount = 0;
|
||||
CallBufferTimer<int> timer = new CallBufferTimer<int>(TimeSpan.FromSeconds(1));
|
||||
timer.Completed += (sender, o) =>
|
||||
{
|
||||
string batchedElements = string.Join(", ", o.Elements.Select(e => e.ToString()));
|
||||
Debug.WriteLine($"Batched request being made at {DateTime.UtcNow:h:mm:ss.fff} with elements {batchedElements}");
|
||||
|
||||
Interlocked.Increment(ref completedCount);
|
||||
};
|
||||
|
||||
List<Task> timerTasks = Enumerable.Range(1, 10).Select(i => timer.Fire(new[] { i }.ToList())).ToList();
|
||||
|
||||
Task delayTask = Task.Delay(TimeSpan.FromSeconds(2));
|
||||
timerTasks.Add(delayTask);
|
||||
|
||||
var result = await Task.WhenAny(timerTasks);
|
||||
if (result == delayTask)
|
||||
{
|
||||
// This means the delay task completed.
|
||||
Assert.Fail("Timer was never called.");
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, completedCount);
|
||||
|
||||
await Task.WhenAll(timerTasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public async Task QueuedThrottledCallback()
|
||||
{
|
||||
int completedCount = 0;
|
||||
CallBufferTimer<int> timer = new CallBufferTimer<int>(TimeSpan.FromMilliseconds(250));
|
||||
timer.Completed += (sender, o) =>
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
|
||||
string batchedElements = string.Join(", ", o.Elements.Select(e => e.ToString()));
|
||||
Debug.WriteLine($"Batched request being made at {DateTime.UtcNow:h:mm:ss.fff} with elements {batchedElements}");
|
||||
|
||||
Interlocked.Increment(ref completedCount);
|
||||
};
|
||||
|
||||
// Create a first batch of 10. We don't care when these finish, so let the tasks go.
|
||||
List<Task> batch1Tasks = Enumerable.Range(1, 5).Select(i => timer.Fire(new[] { i }.ToList())).ToList();
|
||||
|
||||
// Make sure the first batch has started.
|
||||
await Task.Delay(251);
|
||||
|
||||
// Start a second batch after the first one is running.
|
||||
List<Task> timerTasks = Enumerable.Range(6, 5).Select(i => timer.Fire(new[] { i }.ToList())).ToList();
|
||||
|
||||
Task delayTask = Task.Delay(TimeSpan.FromSeconds(2));
|
||||
timerTasks.Add(delayTask);
|
||||
|
||||
var result = await Task.WhenAny(timerTasks);
|
||||
if (result == delayTask)
|
||||
{
|
||||
// This means the delay task completed.
|
||||
Assert.Fail("Second batch was never triggered.");
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Completed count: {completedCount}");
|
||||
Assert.AreEqual(completedCount, 2, "completedCount == 2");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a call to fire will be immediately (or nearly immediately) executed if
|
||||
/// no call has been made in the past "period" amount of time.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public async Task ExecuteImmediatelyIfPastPeriod()
|
||||
{
|
||||
int completedCount = 0;
|
||||
CallBufferTimer<int> timer = new CallBufferTimer<int>(TimeSpan.FromMilliseconds(50));
|
||||
timer.Completed += (sender, o) =>
|
||||
{
|
||||
string batchedElements = string.Join(", ", o.Elements.Select(e => e.ToString()));
|
||||
Debug.WriteLine($"Batched request being made at {DateTime.UtcNow:h:mm:ss.fff} with elements [{batchedElements}]");
|
||||
|
||||
Interlocked.Increment(ref completedCount);
|
||||
};
|
||||
|
||||
var timerTask = timer.Fire(new List<int> { 1 });
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
Task delayTask = Task.Delay(TimeSpan.FromSeconds(2));
|
||||
|
||||
var result = await Task.WhenAny(timerTask, delayTask);
|
||||
if (result == delayTask)
|
||||
{
|
||||
// This means the delay task completed.
|
||||
Assert.Fail("Second batch was never triggered.");
|
||||
}
|
||||
|
||||
Assert.IsTrue(timerTask.IsCompleted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that if you add an element to the buffer while an existing call is queued
|
||||
/// it get's executed with that batch as opposed to the next.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task AddWhileQueued()
|
||||
{
|
||||
int completedCount = 0;
|
||||
CallBufferTimer<int> timer = new CallBufferTimer<int>(TimeSpan.FromMilliseconds(1000));
|
||||
timer.Completed += (sender, o) =>
|
||||
{
|
||||
string batchedElements = string.Join(", ", o.Elements.Select(e => e.ToString()));
|
||||
Debug.WriteLine($"Batched request being made at {DateTime.UtcNow:h:mm:ss.fff} with elements [{batchedElements}]");
|
||||
|
||||
Interlocked.Increment(ref completedCount);
|
||||
};
|
||||
|
||||
Debug.WriteLine($"Now: {DateTime.UtcNow:O}");
|
||||
|
||||
// Execute and wait for a single call
|
||||
await timer.Fire(new List<int> { 1 });
|
||||
|
||||
// Fire another event which will queue up a new timer.
|
||||
var timerTask1 = timer.Fire(new List<int> { 2 });
|
||||
|
||||
await Task.Delay(200);
|
||||
|
||||
var timerTask2 = timer.Fire(new List<int> { 3 });
|
||||
|
||||
Assert.AreEqual(timerTask1, timerTask2);
|
||||
|
||||
await timerTask2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Xbox.Services.UnitTests.Leaderboards
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Xbox.Services.Leaderboard;
|
||||
|
||||
[TestClass]
|
||||
public class LeaderboardTests : TestBase
|
||||
{
|
||||
private LeaderboardService leaderboardService;
|
||||
|
||||
[TestInitialize]
|
||||
public override void TestInitialize()
|
||||
{
|
||||
base.TestInitialize();
|
||||
MockXboxLiveData.Load(Environment.CurrentDirectory + "\\Leaderboards\\MockDataForLeaderboardTests.json");
|
||||
this.leaderboardService = new LeaderboardService();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
XboxLive.Instance.Dispose();
|
||||
}
|
||||
|
||||
private static void VerifyLeaderboardColumn(LeaderboardColumn column, JObject columnToVerify)
|
||||
{
|
||||
Assert.AreNotEqual(column, null, "LeaderboardColumn was null.");
|
||||
Assert.AreEqual(column.StatisticName, columnToVerify["statName"].ToString());
|
||||
Assert.AreEqual(column.StatisticType.ToString(), columnToVerify["type"].ToString());
|
||||
}
|
||||
|
||||
private static void VerifyLeaderboardRow(LeaderboardRow row, JObject rowToVerify)
|
||||
{
|
||||
Assert.AreNotEqual(row, null, "LeaderboardRow was null.");
|
||||
|
||||
Assert.AreEqual(row.Gamertag, rowToVerify["gamertag"].ToString());
|
||||
Assert.AreEqual(row.XboxUserId, rowToVerify["xuid"].ToString());
|
||||
Assert.AreEqual(row.Percentile, (double)rowToVerify["percentile"]);
|
||||
Assert.AreEqual(row.Rank, (int)rowToVerify["rank"]);
|
||||
|
||||
// TODO Add checks for values
|
||||
}
|
||||
|
||||
private static void VerifyLeaderboardResult(LeaderboardResult result, JObject resultToVerify)
|
||||
{
|
||||
Assert.AreNotEqual(result, null, "LeaderboardResult was null.");
|
||||
|
||||
JObject leaderboardInfoJson = JObject.Parse(resultToVerify["leaderboardInfo"].ToString());
|
||||
Assert.AreEqual(result.TotalRowCount, (uint)leaderboardInfoJson["totalCount"]);
|
||||
|
||||
JObject jsonColumn = JObject.Parse(leaderboardInfoJson["columnDefinition"].ToString());
|
||||
VerifyLeaderboardColumn(result.Columns[0], jsonColumn);
|
||||
|
||||
JArray jsonRows = (JArray)(resultToVerify)["userList"];
|
||||
int index = 0;
|
||||
foreach (var row in jsonRows)
|
||||
{
|
||||
VerifyLeaderboardRow(result.Rows[index++], (JObject)row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
{
|
||||
"defaultLeaderboardData": {
|
||||
"Request" : {
|
||||
"method": "GET",
|
||||
"serverName": "https://leaderboards.xboxlive.com",
|
||||
"pathQueryFragment": "/scids/00000000-0000-0000-0000-0000694f5acb/leaderboards/stat(Jumps)?maxItems=100"
|
||||
},
|
||||
"Response" : {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"pagingInfo": {
|
||||
"continuationToken": "6"
|
||||
},
|
||||
"leaderboardInfo": {
|
||||
"totalCount": 38,
|
||||
"columnDefinition": {
|
||||
"statName": "Jumps",
|
||||
"type": "Integer"
|
||||
}
|
||||
},
|
||||
"userList": [
|
||||
{
|
||||
"gamertag": "NSC FaceRocker",
|
||||
"xuid": "2533275015216241",
|
||||
"percentile": 0.9954,
|
||||
"rank": 1,
|
||||
"globalrank": 1,
|
||||
"value": "3660",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "isspmarkbou",
|
||||
"xuid": "2533275024657260",
|
||||
"percentile": 0.9908,
|
||||
"rank": 2,
|
||||
"globalrank": 2,
|
||||
"value": "2208",
|
||||
"valuemetadata": "{\"HasSkull\": false, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "UnloosedLeech",
|
||||
"xuid": "2535449359478292",
|
||||
"percentile": 0.9862,
|
||||
"rank": 3,
|
||||
"globalrank": 3,
|
||||
"value": "1064",
|
||||
"valuemetadata": "{\"HasSkull\": null, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "MSFT JEFFSHI 00",
|
||||
"xuid": "2814662167029838",
|
||||
"percentile": 0.9817,
|
||||
"rank": 4,
|
||||
"globalrank": 4,
|
||||
"value": "783",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "ProfittMan",
|
||||
"xuid": "2533274998970959",
|
||||
"percentile": 0.9771,
|
||||
"rank": 5,
|
||||
"globalrank": 5,
|
||||
"value": "535",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultLeaderboardDataWithContinuationToken": {
|
||||
"Request" : {
|
||||
"method": "GET",
|
||||
"serverName": "https://leaderboards.xboxlive.com",
|
||||
"pathQueryFragment": "/scids/00000000-0000-0000-0000-0000694f5acb/leaderboards/stat(Jumps)?maxItems=100&continuationToken=6"
|
||||
},
|
||||
"Response" : {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"pagingInfo": null,
|
||||
"leaderboardInfo": {
|
||||
"totalCount": 38,
|
||||
"columnDefinition": {
|
||||
"statName": "EnemyDefeats",
|
||||
"type": "Integer"
|
||||
}
|
||||
},
|
||||
"userList": [
|
||||
{
|
||||
"gamertag": "NSC FaceRocker",
|
||||
"xuid": "2533275015216241",
|
||||
"percentile": 0.9954,
|
||||
"rank": 1,
|
||||
"globalrank": 1,
|
||||
"value": "3660",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "isspmarkbou",
|
||||
"xuid": "2533275024657260",
|
||||
"percentile": 0.9908,
|
||||
"rank": 2,
|
||||
"globalrank": 2,
|
||||
"value": "2208",
|
||||
"valuemetadata": "{\"HasSkull\": false, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "UnloosedLeech",
|
||||
"xuid": "2535449359478292",
|
||||
"percentile": 0.9862,
|
||||
"rank": 3,
|
||||
"globalrank": 3,
|
||||
"value": "1064",
|
||||
"valuemetadata": "{\"HasSkull\": null, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "MSFT JEFFSHI 00",
|
||||
"xuid": "2814662167029838",
|
||||
"percentile": 0.9817,
|
||||
"rank": 4,
|
||||
"globalrank": 4,
|
||||
"value": "783",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
},
|
||||
{
|
||||
"gamertag": "ProfittMan",
|
||||
"xuid": "2533274998970959",
|
||||
"percentile": 0.9771,
|
||||
"rank": 5,
|
||||
"globalrank": 5,
|
||||
"value": "535",
|
||||
"valuemetadata": "{\"HasSkull\": true, \"Kills\": 11, \"Level\": \"Hardcake\", \"Empty\": null}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,10 +56,6 @@
|
|||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="CallBufferTimerTests.cs" />
|
||||
<Compile Include="Leaderboards\LeaderboardTests.cs" />
|
||||
<Compile Include="Privacy\PrivacyTests.cs" />
|
||||
<Compile Include="Social\SocialUserGroupTests.cs" />
|
||||
<Compile Include="Social\SocialManagerTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Stats\StatsManagerTests.cs" />
|
||||
|
@ -73,22 +69,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Leaderboards\MockDataForLeaderboardTests.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="TitleStorage\TitleStorageUT.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="packages.config" />
|
||||
<Content Include="Privacy\MockDataForPrivacyTests.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Social\SocialUserGroupUT.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Social\SocialManagerUT.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="XboxServices.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
{
|
||||
"defaultCheckPermissionsResponse": {
|
||||
"Request" : {
|
||||
"method": "GET",
|
||||
"serverName": "https://privacy.xboxlive.com",
|
||||
"pathQueryFragment": "/users/xuid(2814662072777140)/permission/validate?setting=ViewTargetVideoHistory&target=xuid(2814680291986301)"
|
||||
},
|
||||
"Response" : {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"isAllowed":false,
|
||||
"reasons":[
|
||||
{
|
||||
"reason":"NotAllowed"
|
||||
},
|
||||
{
|
||||
"reason":"BlockListRestrictsTarget"
|
||||
},
|
||||
{
|
||||
"reason":"MuteListRestrictsTarget"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultCheckMultiplePermissionsResponse": {
|
||||
"Request" : {
|
||||
"method": "POST",
|
||||
"serverName": "https://privacy.xboxlive.com",
|
||||
"pathQueryFragment": "/users/xuid(2814662072777140)/permission/validate"
|
||||
},
|
||||
"Response" : {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"responses": [{
|
||||
"user": {
|
||||
"xuid": "2814680291986301"
|
||||
},
|
||||
"permissions": [{
|
||||
"isAllowed": false,
|
||||
"reasons": [{
|
||||
"reason": "NotAllowed"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"isAllowed": false,
|
||||
"reasons": [{
|
||||
"reason": "NotAllowed"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"isAllowed": true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"xuid": "2814634309691161"
|
||||
},
|
||||
"permissions": [{
|
||||
"isAllowed": false,
|
||||
"reasons": [{
|
||||
"reason": "NotAllowed"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"isAllowed": false,
|
||||
"reasons": [{
|
||||
"reason": "NotAllowed"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"isAllowed": true
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Xbox.Services.UnitTests.Leaderboards
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Xbox.Services.Privacy;
|
||||
|
||||
[TestClass]
|
||||
public class PrivacyTests : TestBase
|
||||
{
|
||||
[TestInitialize]
|
||||
public override void TestInitialize()
|
||||
{
|
||||
base.TestInitialize();
|
||||
MockXboxLiveData.Load(Environment.CurrentDirectory + "\\Privacy\\MockDataForPrivacyTests.json");
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void VerifyPermissionCheckResult(PermissionCheckResult result, JObject resultToVerify)
|
||||
{
|
||||
var isAllowed = resultToVerify.SelectToken("isAllowed").Value<bool>();
|
||||
Assert.AreEqual(result.IsAllowed, isAllowed);
|
||||
|
||||
int index = 0;
|
||||
JArray jsonReasons = (JArray)(resultToVerify)["reasons"];
|
||||
if (jsonReasons != null)
|
||||
{
|
||||
foreach (var reason in jsonReasons)
|
||||
{
|
||||
Assert.AreEqual(result.Reasons[index].Reason, reason["reason"].ToString());
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VerifyMultiplePermissionsCheckResult(List<MultiplePermissionsCheckResult> result, JObject resultToVerify)
|
||||
{
|
||||
int multiplePermIndex = 0;
|
||||
JArray jsonResponses = (JArray)(resultToVerify)["responses"];
|
||||
foreach (var response in jsonResponses)
|
||||
{
|
||||
Assert.AreEqual(result[multiplePermIndex].XboxUserId, response["user"]["xuid"].ToString());
|
||||
|
||||
JArray jsonPermissions = (JArray)(response)["permissions"];
|
||||
int index = 0;
|
||||
foreach (var permission in jsonPermissions)
|
||||
{
|
||||
VerifyPermissionCheckResult(result[multiplePermIndex].Items[index], (JObject)permission);
|
||||
++index;
|
||||
}
|
||||
|
||||
++multiplePermIndex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CheckPermissionWithTargetUserAsync()
|
||||
{
|
||||
PermissionCheckResult result = await this.user.Services.PrivacyService.CheckPermissionWithTargetUserAsync(PermissionIdConstants.ViewTargetVideoHistory, "2814680291986301");
|
||||
MockXboxLiveData.MockRequestData mockRequestData = MockXboxLiveData.MockResponses["defaultCheckPermissionsResponse"];
|
||||
JObject responseJson = JObject.Parse(mockRequestData.Response.ResponseBodyString);
|
||||
Assert.AreEqual("GET", mockRequestData.Request.Method);
|
||||
Assert.AreEqual("https://privacy.xboxlive.com/users/xuid(2814662072777140)/permission/validate?setting=ViewTargetVideoHistory&target=xuid(2814680291986301)", mockRequestData.Request.Url);
|
||||
VerifyPermissionCheckResult(result, responseJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CheckMultiplePermissionsWithMultipleTargetUsersAsync()
|
||||
{
|
||||
List<string> permissionIds = new List<string>();
|
||||
permissionIds.Add(PermissionIdConstants.ViewTargetVideoHistory);
|
||||
permissionIds.Add(PermissionIdConstants.ViewTargetMusicStatus);
|
||||
permissionIds.Add(PermissionIdConstants.ViewTargetGameHistory);
|
||||
|
||||
List<string> xuids = new List<string>();
|
||||
xuids.Add("2814680291986301");
|
||||
xuids.Add("2814634309691161");
|
||||
|
||||
List<MultiplePermissionsCheckResult> result = await this.user.Services.PrivacyService.CheckMultiplePermissionsWithMultipleTargetUsersAsync(permissionIds, xuids);
|
||||
MockXboxLiveData.MockRequestData mockRequestData = MockXboxLiveData.MockResponses["defaultCheckMultiplePermissionsResponse"];
|
||||
JObject responseJson = JObject.Parse(mockRequestData.Response.ResponseBodyString);
|
||||
Assert.AreEqual("POST", mockRequestData.Request.Method);
|
||||
Assert.AreEqual("https://privacy.xboxlive.com/users/xuid(2814662072777140)/permission/validate", mockRequestData.Request.Url);
|
||||
VerifyMultiplePermissionsCheckResult(result, responseJson);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ namespace Microsoft.Xbox.Services.UnitTests.Social
|
|||
public override void TestInitialize()
|
||||
{
|
||||
base.TestInitialize();
|
||||
MockXboxLiveData.Load(Environment.CurrentDirectory + "\\Social\\SocialManagerUT.json");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
{
|
||||
"GettingProfile": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/me/people/xuids(2814662072777140)/decoration/presenceDetail"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [
|
||||
{
|
||||
"xuid": "2814662072777140",
|
||||
"isFavorite": false,
|
||||
"isFollowingCaller": false,
|
||||
"isFollowedByCaller": false,
|
||||
"isIdentityShared": false,
|
||||
"addedDateTimeUtc": null,
|
||||
"displayName": "2 Dev 183714711",
|
||||
"realName": "",
|
||||
"displayPicRaw": "http://images-eds.xboxlive.com/image?url=z951ykn43p4FqWbbFvR2Ec.8vbDhj8G2Xe7JngaTToBrrCmIEEXHC9UNrdJ6P7KIU5Sj_1hNZHeOVzbgzVj2gl0huLzRktrOPIt7LWZyuaghGltBhJkDROP7NOeAebn4&format=png",
|
||||
"useAvatar": false,
|
||||
"gamertag": "2 Dev 183714711",
|
||||
"gamerScore": "0",
|
||||
"xboxOneRep": "GoodPlayer",
|
||||
"presenceState": "Offline",
|
||||
"presenceText": "Offline",
|
||||
"presenceDevices": null,
|
||||
"isBroadcasting": false,
|
||||
"isCloaked": null,
|
||||
"suggestion": null,
|
||||
"recommendation": null,
|
||||
"titleHistory": null,
|
||||
"multiplayerSummary": null,
|
||||
"recentPlayer": null,
|
||||
"follower": null,
|
||||
"preferredColor": null,
|
||||
"presenceDetails": [ ],
|
||||
"titlePresence": null,
|
||||
"titleSummaries": null,
|
||||
"presenceTitleIds": null,
|
||||
"detail": null,
|
||||
"communityManagerTitles": null,
|
||||
"socialManager": null,
|
||||
"broadcast": null,
|
||||
"tournamentSummary": null
|
||||
}
|
||||
],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettingSocial": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/xuid(2814662072777140)/people/social"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [ ],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettingProfileWithTitleHistory": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/me/people/xuids(2814662072777140)/decoration/titlehistory(1766808267),preferredcolor,presenceDetail"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [
|
||||
{
|
||||
"xuid": "2814662072777140",
|
||||
"isFavorite": false,
|
||||
"isFollowingCaller": false,
|
||||
"isFollowedByCaller": false,
|
||||
"isIdentityShared": false,
|
||||
"addedDateTimeUtc": null,
|
||||
"displayName": "2 Dev 183714711",
|
||||
"realName": "",
|
||||
"displayPicRaw": "http://images-eds.xboxlive.com/image?url=z951ykn43p4FqWbbFvR2Ec.8vbDhj8G2Xe7JngaTToBrrCmIEEXHC9UNrdJ6P7KIU5Sj_1hNZHeOVzbgzVj2gl0huLzRktrOPIt7LWZyuaghGltBhJkDROP7NOeAebn4&format=png",
|
||||
"useAvatar": false,
|
||||
"gamertag": "2 Dev 183714711",
|
||||
"gamerScore": "0",
|
||||
"xboxOneRep": "GoodPlayer",
|
||||
"presenceState": "Offline",
|
||||
"presenceText": "Offline",
|
||||
"presenceDevices": null,
|
||||
"isBroadcasting": false,
|
||||
"isCloaked": null,
|
||||
"suggestion": null,
|
||||
"recommendation": null,
|
||||
"titleHistory": null,
|
||||
"multiplayerSummary": null,
|
||||
"recentPlayer": null,
|
||||
"follower": null,
|
||||
"preferredColor": {
|
||||
"primaryColor": "107c10",
|
||||
"secondaryColor": "102b14",
|
||||
"tertiaryColor": "155715"
|
||||
},
|
||||
"presenceDetails": [ ],
|
||||
"titlePresence": null,
|
||||
"titleSummaries": null,
|
||||
"presenceTitleIds": null,
|
||||
"detail": null,
|
||||
"communityManagerTitles": null,
|
||||
"socialManager": null,
|
||||
"broadcast": null,
|
||||
"tournamentSummary": null
|
||||
}
|
||||
],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettingSocialWithTitleHistory": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/xuid(2814662072777140)/people/social/decoration/titlehistory(1766808267),preferredcolor,presenceDetail"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [ ],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services.UnitTests.Social
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Xbox.Services.Social.Manager;
|
||||
using Microsoft.Xbox.Services.System;
|
||||
|
||||
[TestClass]
|
||||
public class SocialUserGroupUnitTests
|
||||
{
|
||||
private XboxLiveUser user;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
this.user = new XboxLiveUser();
|
||||
MockXboxLiveData.Load(Environment.CurrentDirectory + "\\Social\\SocialUserGroupUT.json");
|
||||
SocialManager.Instance.AddLocalUser(this.user, SocialManagerExtraDetailLevel.PreferredColorLevel);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocialGroupWithSelfFromSocialManager()
|
||||
{
|
||||
var group = SocialManager.Instance.CreateSocialUserGroupFromList(this.user, new List<string> { this.user.XboxUserId });
|
||||
Assert.IsNotNull(group);
|
||||
|
||||
DoWorkUntil(() => group.Count == 1);
|
||||
|
||||
Assert.AreEqual(this.user.XboxUserId, group.First().XboxUserId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocialGroupWithFilterOnlineFriendsFromSocialManager()
|
||||
{
|
||||
var group = SocialManager.Instance.CreateSocialUserGroupFromFilters(this.user, PresenceFilter.AllOnline, RelationshipFilter.Friends);
|
||||
Assert.IsNotNull(group);
|
||||
|
||||
DoWorkUntil(() => group.Count > 0);
|
||||
|
||||
Assert.IsTrue(group.Count > 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocialGroupWithFilterOnlineFavoritesFromSocialManager()
|
||||
{
|
||||
var group = SocialManager.Instance.CreateSocialUserGroupFromFilters(this.user, PresenceFilter.AllOnline, RelationshipFilter.Favorite);
|
||||
Assert.IsNotNull(group);
|
||||
|
||||
DoWorkUntil(() => group.Count > 0);
|
||||
|
||||
Assert.IsTrue(group.Count > 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocialGroupWithFilterOfflineFavoritesFromSocialManager()
|
||||
{
|
||||
var group = SocialManager.Instance.CreateSocialUserGroupFromFilters(this.user, PresenceFilter.AllOffline, RelationshipFilter.Favorite);
|
||||
Assert.IsNotNull(group);
|
||||
|
||||
DoWorkUntil(() => group.Count > 0);
|
||||
|
||||
Assert.IsTrue(group.Count > 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocialGroupWithOthers()
|
||||
{
|
||||
}
|
||||
|
||||
private static Task DoWorkUntil(Func<bool> predicate)
|
||||
{
|
||||
return DoWorkUntil(predicate, TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
private static async Task DoWorkUntil(Func<bool> predicate, TimeSpan maxDuration)
|
||||
{
|
||||
DateTime workUntil = DateTime.UtcNow + maxDuration;
|
||||
|
||||
do
|
||||
{
|
||||
IList<SocialEvent> events = SocialManager.Instance.DoWork();
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(100));
|
||||
}
|
||||
while (!predicate() && DateTime.UtcNow < workUntil);
|
||||
|
||||
if (!predicate())
|
||||
{
|
||||
Assert.Fail("Request did not complete as expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"GettingProfile": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/xuid(2814662072777140)/people/social/decoration/preferredcolor,presenceDetail"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [ ],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettingSocial": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://peoplehub.xboxlive.com",
|
||||
"pathQueryFragment": "/users/me/people/xuids(2814662072777140)/decoration/preferredcolor,presenceDetail"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"people": [
|
||||
{
|
||||
"xuid": "2814662072777140",
|
||||
"isFavorite": false,
|
||||
"isFollowingCaller": false,
|
||||
"isFollowedByCaller": false,
|
||||
"isIdentityShared": false,
|
||||
"addedDateTimeUtc": null,
|
||||
"displayName": "2 Dev 183714711",
|
||||
"realName": "",
|
||||
"displayPicRaw": "http://images-eds.xboxlive.com/image?url=z951ykn43p4FqWbbFvR2Ec.8vbDhj8G2Xe7JngaTToBrrCmIEEXHC9UNrdJ6P7KIU5Sj_1hNZHeOVzbgzVj2gl0huLzRktrOPIt7LWZyuaghGltBhJkDROP7NOeAebn4&format=png",
|
||||
"useAvatar": false,
|
||||
"gamertag": "2 Dev 183714711",
|
||||
"gamerScore": "0",
|
||||
"xboxOneRep": "GoodPlayer",
|
||||
"presenceState": "Offline",
|
||||
"presenceText": "Offline",
|
||||
"presenceDevices": null,
|
||||
"isBroadcasting": false,
|
||||
"isCloaked": null,
|
||||
"suggestion": null,
|
||||
"recommendation": null,
|
||||
"titleHistory": null,
|
||||
"multiplayerSummary": null,
|
||||
"recentPlayer": null,
|
||||
"follower": null,
|
||||
"preferredColor": {
|
||||
"primaryColor": "107c10",
|
||||
"secondaryColor": "102b14",
|
||||
"tertiaryColor": "155715"
|
||||
},
|
||||
"presenceDetails": [ ],
|
||||
"titlePresence": null,
|
||||
"titleSummaries": null,
|
||||
"presenceTitleIds": null,
|
||||
"detail": null,
|
||||
"communityManagerTitles": null,
|
||||
"socialManager": null,
|
||||
"broadcast": null,
|
||||
"tournamentSummary": null
|
||||
}
|
||||
],
|
||||
"recommendationSummary": null,
|
||||
"friendFinderState": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
{
|
||||
"GlobalStorageGetQuota": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/global/scids/00000000-0000-0000-0000-0000694f5acb"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"quotaInfo": {
|
||||
"usedBytes": 605,
|
||||
"quotaBytes": 268435456
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TrustedPlatformGetQuota": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/trustedplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"quotaInfo": {
|
||||
"usedBytes": 605,
|
||||
"quotaBytes": 268435456
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformGetQuota": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"quotaInfo": {
|
||||
"usedBytes": 605,
|
||||
"quotaBytes": 268435456
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformUploadBlob": {
|
||||
"Request": {
|
||||
"method": "PUT",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/queststatus/quest01.json,json",
|
||||
"body": {
|
||||
"QuestName": "Quest 01",
|
||||
"CharactersInvolved": [
|
||||
"Character 01",
|
||||
"Character 02",
|
||||
"Character 03"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 201,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformDeleteBlob": {
|
||||
"Request": {
|
||||
"method": "DELETE",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/queststatus/quest01.json,json"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformUploadBinary01": {
|
||||
"Request": {
|
||||
"method": "PUT",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/file.bin,binary?finalBlock=True"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"continuationToken": "40b2d28a-da60-4c80-b772-3208a1512bd2-1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformUploadBinary02": {
|
||||
"Request": {
|
||||
"method": "PUT",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/file.bin,binary?continuationToken=40b2d28a-da60-4c80-b772-3208a1512bd2-1&finalBlock=True"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformGetBlobMetadata": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/queststatus"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"blobs": [
|
||||
{
|
||||
"fileName": "queststatus/quest01.json,json",
|
||||
"etag": "0x8D47D2671F4407E",
|
||||
"size": 122
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest5.json,json",
|
||||
"etag": "0x8D47C5A027989C3",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest6.json,json",
|
||||
"etag": "0x8D47C5A02AC0C43",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest7.json,json",
|
||||
"etag": "0x8D47C5A02D28094",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest8.json,json",
|
||||
"etag": "0x8D47C5A02F8A6AF",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest9.json,json",
|
||||
"etag": "0x8D47C5A03207A91",
|
||||
"size": 121
|
||||
}
|
||||
],
|
||||
"pagingInfo": {
|
||||
"totalItems": 6,
|
||||
"continuationToken": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformGetBlobMetadata2": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/queststatus"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"blobs": [
|
||||
{
|
||||
"fileName": "queststatus/quest01.json,json",
|
||||
"etag": "0x8D47D2671F4407E",
|
||||
"size": 122
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest5.json,json",
|
||||
"etag": "0x8D47C5A027989C3",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest6.json,json",
|
||||
"etag": "0x8D47C5A02AC0C43",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest7.json,json",
|
||||
"etag": "0x8D47C5A02D28094",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest8.json,json",
|
||||
"etag": "0x8D47C5A02F8A6AF",
|
||||
"size": 121
|
||||
},
|
||||
{
|
||||
"fileName": "queststatus/quest9.json,json",
|
||||
"etag": "0x8D47C5A03207A91",
|
||||
"size": 121
|
||||
}
|
||||
],
|
||||
"pagingInfo": {
|
||||
"totalItems": 6,
|
||||
"continuationToken": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UniversalPlatformDownloadBlob": {
|
||||
"Request": {
|
||||
"method": "GET",
|
||||
"serverName": "https://titlestorage.xboxlive.com",
|
||||
"pathQueryFragment": "/universalplatform/users/xuid(2814662072777140)/scids/00000000-0000-0000-0000-0000694f5acb/data/queststatus/quest01.json,json"
|
||||
},
|
||||
"Response": {
|
||||
"httpStatus": 200,
|
||||
"bodyType": 2,
|
||||
"body": {
|
||||
"QuestName": "Quest 01",
|
||||
"CharactersInvolved": [
|
||||
"Character 01",
|
||||
"Character 02",
|
||||
"Character 03"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,10 +10,5 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public static bool UseMockHttp
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,10 +4,30 @@
|
|||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using Newtonsoft.Json;
|
||||
using global::System.IO;
|
||||
|
||||
public partial class XboxLiveAppConfiguration
|
||||
{
|
||||
public string PublisherId { get; set; }
|
||||
|
||||
public string PublisherDisplayName { get; set; }
|
||||
|
||||
public string PackageIdentityName { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public string AppId { get; set; }
|
||||
|
||||
public string ProductFamilyName { get; set; }
|
||||
|
||||
public bool XboxLiveCreatorsTitle { get; set; }
|
||||
|
||||
private static XboxLiveAppConfiguration Load()
|
||||
{
|
||||
return XboxLiveAppConfiguration.Load(FileName);
|
||||
}
|
||||
|
||||
public static XboxLiveAppConfiguration Load(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
|
@ -21,7 +41,7 @@ namespace Microsoft.Xbox.Services
|
|||
throw new XboxException(string.Format("Xbox Live app configeration file '{0}' was empty.", path));
|
||||
}
|
||||
|
||||
return JsonSerialization.FromJson<XboxLiveAppConfiguration>(content);
|
||||
return JsonConvert.DeserializeObject<XboxLiveAppConfiguration>(content);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.Xbox.Services.Leaderboard
|
||||
{
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
|
||||
using System;
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.Xbox.Services.Leaderboard
|
||||
{
|
||||
using global::System;
|
||||
|
||||
class LeaderboardQueryUnityEditorImpl : ILeaderboardQueryImpl
|
||||
{
|
||||
public IntPtr GetPtr() { return IntPtr.Zero; }
|
||||
|
|
|
@ -16,7 +16,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
public string AgeGroup { get; set; }
|
||||
public string Privileges { get; set; }
|
||||
public string WebAccountId { get; set; }
|
||||
public AuthConfig AuthConfig { get; set; }
|
||||
|
||||
private static int numberOfInstances;
|
||||
private static Random random = new Random();
|
||||
|
@ -36,11 +35,11 @@ namespace Microsoft.Xbox.Services.System
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
public Task<GetTokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh)
|
||||
{
|
||||
if (XboxLive.UseMockServices)
|
||||
{
|
||||
return Task.FromResult(new TokenAndSignatureResult
|
||||
return Task.FromResult(new GetTokenAndSignatureResult
|
||||
{
|
||||
Gamertag = this.Gamertag,
|
||||
XboxUserId = this.XboxUserId,
|
||||
|
|
|
@ -1,33 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
public class HttpCallRequestMessage
|
||||
{
|
||||
public HttpRequestMessageType GetHttpRequestMessageType { get; private set; }
|
||||
|
||||
public HttpRequestMessageType GetHttpRequestMessageType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Byte[] RequestMessageVector
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string RequestMessageString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public Byte[] RequestMessageVector { get; private set; }
|
||||
|
||||
public string RequestMessageString { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
public enum HttpCallResponseBodyType : uint
|
||||
{
|
||||
StringBody,
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
public static class HttpMethod
|
||||
{
|
||||
public const string Get = "GET";
|
||||
public const string Put = "PUT";
|
||||
public const string Post = "POST";
|
||||
public const string Delete = "DELETE";
|
||||
public const string Patch = "PATCH";
|
||||
public const string Options = "OPTIONS";
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
public class HttpRetryAfterApiState
|
||||
{
|
||||
public DateTime RetryAfterTime { get; set; }
|
||||
public Exception Exception { get; set; }
|
||||
public XboxLiveHttpResponse HttpCallResponse { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
|
||||
public class HttpRetryAfterManager
|
||||
{
|
||||
private static readonly object instanceLock = new object();
|
||||
private static HttpRetryAfterManager instance;
|
||||
private readonly Dictionary<XboxLiveAPIName, HttpRetryAfterApiState> apiStateMap = new Dictionary<XboxLiveAPIName, HttpRetryAfterApiState>();
|
||||
|
||||
public static HttpRetryAfterManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new HttpRetryAfterManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetState(
|
||||
XboxLiveAPIName xboxLiveApi,
|
||||
HttpRetryAfterApiState state
|
||||
)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
this.apiStateMap[xboxLiveApi] = state;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearState(
|
||||
XboxLiveAPIName xboxLiveApi
|
||||
)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
this.apiStateMap.Remove(xboxLiveApi);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool GetState(
|
||||
XboxLiveAPIName xboxLiveApi,
|
||||
out HttpRetryAfterApiState returnValue
|
||||
)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
return this.apiStateMap.TryGetValue(xboxLiveApi, out returnValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
public interface IXboxLiveUser
|
||||
internal interface IXboxLiveUser
|
||||
{
|
||||
string WebAccountId { get; }
|
||||
|
||||
|
@ -29,10 +29,10 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
Task<SignInResult> SignInSilentlyAsync();
|
||||
|
||||
Task<TokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers);
|
||||
Task<GetTokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers);
|
||||
|
||||
Task<TokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers, string body);
|
||||
Task<GetTokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers, string body);
|
||||
|
||||
Task<TokenAndSignatureResult> GetTokenAndSignatureArrayAsync(string httpMethod, string url, string headers, byte[] body);
|
||||
Task<GetTokenAndSignatureResult> GetTokenAndSignatureArrayAsync(string httpMethod, string url, string headers, byte[] body);
|
||||
}
|
||||
}
|
|
@ -7,11 +7,11 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
public class SignInCompletedEventArgs : EventArgs
|
||||
{
|
||||
public SignInCompletedEventArgs(IXboxLiveUser user)
|
||||
public SignInCompletedEventArgs(XboxLiveUser user)
|
||||
{
|
||||
this.User = user;
|
||||
}
|
||||
|
||||
public IXboxLiveUser User { get; private set; }
|
||||
public XboxLiveUser User { get; private set; }
|
||||
}
|
||||
}
|
|
@ -7,12 +7,11 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
public class SignOutCompletedEventArgs : EventArgs
|
||||
{
|
||||
public SignOutCompletedEventArgs(IXboxLiveUser user)
|
||||
public SignOutCompletedEventArgs(XboxLiveUser user)
|
||||
{
|
||||
this.User = user;
|
||||
}
|
||||
|
||||
// TODO change this to XboxLiveUser instead of IXboxLive user to match WinRT projections
|
||||
public IXboxLiveUser User { get; private set; }
|
||||
public XboxLiveUser User { get; private set; }
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ using Windows.Security.Authentication.Web.Core;
|
|||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
public class TokenAndSignatureResult
|
||||
public class GetTokenAndSignatureResult
|
||||
{
|
||||
public string WebAccountId { get; set; }
|
||||
|
||||
|
@ -25,10 +25,5 @@ namespace Microsoft.Xbox.Services
|
|||
public string Signature { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
|
||||
internal string Reserved { get; set; }
|
||||
#if WINDOWS_UWP
|
||||
internal WebTokenRequestStatus TokenRequestResultStatus { get; set; }
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -30,6 +30,11 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
}
|
||||
|
||||
internal XboxException(XSAPI_RESULT result, IntPtr errorMessagePtr)
|
||||
: base(string.Format("Xbox Services flat C API return error code {0} with message \"{1}\"", result.ToString("g"), MarshalingHelpers.Utf8ToString(errorMessagePtr)))
|
||||
{
|
||||
}
|
||||
|
||||
internal XboxException(XSAPI_RESULT_INFO resultInfo)
|
||||
: base (string.Format("Xbox Services flat C API return error code {0} with message \"{1}\"", resultInfo.errorCode.ToString("g"), MarshalingHelpers.Utf8ToString(resultInfo.errorMessage)))
|
||||
{
|
||||
|
|
|
@ -5,9 +5,7 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
using global::System;
|
||||
using global::System.IO;
|
||||
using global::System.ComponentModel;
|
||||
using global::System.Runtime.InteropServices;
|
||||
using Microsoft.Xbox.Services.Presence;
|
||||
using Microsoft.Xbox.Services.Social.Manager;
|
||||
using Microsoft.Xbox.Services.Statistics.Manager;
|
||||
using Microsoft.Xbox.Services.System;
|
||||
|
@ -16,7 +14,6 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
private bool disposed;
|
||||
private static XboxLive instance;
|
||||
private XboxLiveSettings settings;
|
||||
private IStatisticManager statsManager;
|
||||
private ISocialManager socialManager;
|
||||
|
||||
|
@ -32,17 +29,8 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
private XboxLive()
|
||||
{
|
||||
this.settings = new XboxLiveSettings();
|
||||
|
||||
try
|
||||
{
|
||||
this.appConfig = XboxLiveAppConfiguration.Instance;
|
||||
}
|
||||
catch (FileLoadException)
|
||||
{
|
||||
this.appConfig = null;
|
||||
}
|
||||
|
||||
#if WINDOWS_UWP
|
||||
var result = XBLGlobalInitialize();
|
||||
if (result != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
|
@ -50,6 +38,14 @@ namespace Microsoft.Xbox.Services
|
|||
throw new XboxException(result);
|
||||
}
|
||||
#endif
|
||||
// TODO flat C APIs for settings
|
||||
//this.Settings = null;
|
||||
this.appConfig = XboxLiveAppConfiguration.SingletonInstance;
|
||||
}
|
||||
catch (FileLoadException)
|
||||
{
|
||||
this.appConfig = null;
|
||||
}
|
||||
}
|
||||
|
||||
~XboxLive()
|
||||
|
@ -104,15 +100,14 @@ namespace Microsoft.Xbox.Services
|
|||
}
|
||||
}
|
||||
|
||||
public XboxLiveSettings Settings
|
||||
{
|
||||
get { return Instance.settings; }
|
||||
set { Instance.settings = value; }
|
||||
}
|
||||
//public XboxLiveContextSettings Settings { get; private set; }
|
||||
|
||||
public XboxLiveAppConfiguration AppConfig
|
||||
{
|
||||
get { return Instance.appConfig; }
|
||||
get
|
||||
{
|
||||
return Instance.appConfig;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
|
@ -134,7 +129,7 @@ namespace Microsoft.Xbox.Services
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public static Int64 DefaultTaskGroupId
|
||||
internal static Int64 DefaultTaskGroupId
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
public enum XboxLiveAPIName : uint
|
||||
{
|
||||
Unspecified = 0,
|
||||
AllocateCluster,
|
||||
AllocateClusterInline,
|
||||
AllocateSessionHost,
|
||||
BrowseCatalogBundlesHelper,
|
||||
BrowseCatalogHelper,
|
||||
CheckMultiplePermissionsWithMultipleTargetUsers,
|
||||
CheckPermissionWithTargetUser,
|
||||
ClearActivity,
|
||||
ClearSearchHandle,
|
||||
ConsumeInventoryItem,
|
||||
CreateMatchTicket,
|
||||
DeleteBlob,
|
||||
DeleteMatchTicket,
|
||||
DownloadBlob,
|
||||
GetAchievement,
|
||||
GetAchievements,
|
||||
GetActivitiesForSocialGroup,
|
||||
GetActivitiesForUsers,
|
||||
GetAvoidOrMuteList,
|
||||
GetBlobMetadata,
|
||||
GetBroadcasts,
|
||||
GetCatalogItemDetails,
|
||||
GetConfiguration,
|
||||
GetCurrentSession,
|
||||
GetCurrentSessionByHandle,
|
||||
GetGameClips,
|
||||
GetGameServerMetadata,
|
||||
GetHopperStatistics,
|
||||
GetInventoryItem,
|
||||
GetInventoryItems,
|
||||
GetLeaderboardForSocialGroupInternal,
|
||||
GetLeaderboardInternal,
|
||||
GetMatchTicketDetails,
|
||||
GetMultipleUserStatisticsForMultipleServiceConfigurations,
|
||||
GetPresence,
|
||||
GetPresenceForMultipleUsers,
|
||||
GetPresenceForSocialGroup,
|
||||
GetQualityOfServiceServers,
|
||||
GetQuota,
|
||||
GetQuotaForSessionStorage,
|
||||
GetSearchHandles,
|
||||
GetSessionHostAllocationStatus,
|
||||
GetSessions,
|
||||
GetSingleUserStatistics,
|
||||
GetSocialGraph,
|
||||
GetSocialRelationships,
|
||||
GetStatsValueDocument,
|
||||
GetTicketStatus,
|
||||
GetTournaments,
|
||||
GetTournamentDetails,
|
||||
GetTeams,
|
||||
GetTeamDetails,
|
||||
GetUserProfiles,
|
||||
GetProfileInfo,
|
||||
GetUserProfilesForSocialGroup,
|
||||
RegisterTeam,
|
||||
SendInvites,
|
||||
SetActivity,
|
||||
SetPresenceHelper,
|
||||
SetSearchHandle,
|
||||
SetTransferHandle,
|
||||
SubmitBatchReputationFeedback,
|
||||
SubmitReputationFeedback,
|
||||
SubscribeToNotifications,
|
||||
UpdateAchievement,
|
||||
UpdateStatsValueDocument,
|
||||
UploadBlob,
|
||||
VerifyStrings,
|
||||
WriteSessionUsingSubpath,
|
||||
XboxOnePinsAddItem,
|
||||
XboxOnePinsContainsItem,
|
||||
XboxOnePinsRemoveItem
|
||||
};
|
||||
}
|
||||
|
|
@ -4,8 +4,9 @@
|
|||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
#if UNITY_EDITOR
|
||||
using global::Newtonsoft.Json;
|
||||
#endif
|
||||
|
||||
public partial class XboxLiveAppConfiguration
|
||||
{
|
||||
|
@ -14,45 +15,10 @@ namespace Microsoft.Xbox.Services
|
|||
private static readonly object instanceLock = new object();
|
||||
private static XboxLiveAppConfiguration instance;
|
||||
|
||||
public static XboxLiveAppConfiguration Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private XboxLiveAppConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
public string PublisherId { get; set; }
|
||||
|
||||
public string PublisherDisplayName { get; set; }
|
||||
|
||||
public string PackageIdentityName { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public string AppId { get; set; }
|
||||
|
||||
public string ProductFamilyName { get; set; }
|
||||
|
||||
internal string EnvironmentPrefix { get; set; }
|
||||
|
||||
internal bool UseFirstPartyToken { get; set; }
|
||||
|
||||
public string PrimaryServiceConfigId { get; set; }
|
||||
#if UNITY_EDITOR
|
||||
[JsonProperty("PrimaryServiceConfigId")]
|
||||
#endif
|
||||
public string ServiceConfigurationId { get; set; }
|
||||
|
||||
public uint TitleId { get; set; }
|
||||
|
||||
|
@ -60,30 +26,34 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
public string Environment { get; set; }
|
||||
|
||||
public bool XboxLiveCreatorsTitle { get; set; }
|
||||
|
||||
public string GetEndpointForService(string serviceName, string protocol = "https")
|
||||
public static XboxLiveAppConfiguration SingletonInstance
|
||||
{
|
||||
return string.Format("{0}://{1}{2}.xboxlive.com", protocol, serviceName, string.IsNullOrEmpty(this.Environment) ? string.Empty : ("." + this.Environment));
|
||||
}
|
||||
|
||||
public static XboxLiveAppConfiguration Load()
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Attempt to load it from a file
|
||||
return Load(FileName);
|
||||
if (instance == null)
|
||||
{
|
||||
instance = XboxLiveAppConfiguration.Load();
|
||||
}
|
||||
catch (Exception e)
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// If we're unable to load the file for some reason, we can just use an empty file
|
||||
// if mock data is enable.
|
||||
if (XboxLive.UseMockServices || XboxLive.UseMockHttp)
|
||||
if (XboxLive.UseMockServices)
|
||||
{
|
||||
return new XboxLiveAppConfiguration();
|
||||
}
|
||||
|
||||
throw new XboxException(string.Format("Unable to find or load Xbox Live configuration. Make sure a properly configured {0} exists.", FileName), e);
|
||||
throw new XboxException(string.Format("Unable to find or load Xbox Live configuration. Make sure a properly configured Xboxservices.config exists."), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
|
@ -12,5 +8,4 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
ThisCodeNeedsToBeChangedToFollowBestPractices = 0,
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
|
@ -12,5 +8,4 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
ThisCodeNeedsToBeChangedToAvoidThrottling = 0,
|
||||
}
|
||||
|
||||
}
|
|
@ -1,639 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Diagnostics;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Globalization;
|
||||
using global::System.IO;
|
||||
using global::System.Net;
|
||||
using global::System.Reflection;
|
||||
using global::System.Runtime.InteropServices;
|
||||
using global::System.Text;
|
||||
using global::System.Threading;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
public class XboxLiveHttpRequest
|
||||
{
|
||||
private const string AuthorizationHeaderName = "Authorization";
|
||||
private const string SignatureHeaderName = "Signature";
|
||||
private const string RangeHeaderName = "Range";
|
||||
private const string ContentLengthHeaderName = "Content-Length";
|
||||
private const double DefaultHttpTimeoutSeconds = 30.0;
|
||||
private const double MinHttpTimeoutSeconds = 5.0;
|
||||
private const int HttpStatusCodeTooManyRequests = 429;
|
||||
private const double MaxDelayTimeInSec = 60.0;
|
||||
private const int MinDelayForHttpInternalErrorInSec = 10;
|
||||
private static string userAgentVersion;
|
||||
|
||||
internal XboxLiveHttpRequest(string method, string serverName, string pathQueryFragment)
|
||||
{
|
||||
this.iterationNumber = 0;
|
||||
this.Method = method;
|
||||
this.Url = serverName + pathQueryFragment;
|
||||
this.contextSettings = XboxLive.Instance.Settings;
|
||||
this.webRequest = (HttpWebRequest)WebRequest.Create(new Uri(this.Url));
|
||||
this.webRequest.Method = method;
|
||||
this.ResponseBodyType = HttpCallResponseBodyType.StringBody;
|
||||
this.RetryAllowed = true;
|
||||
|
||||
this.SetCustomHeader("Accept-Language", CultureInfo.CurrentUICulture + "," + CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
|
||||
#if WINDOWS_UWP
|
||||
this.SetCustomHeader("Accept", "*/*");
|
||||
#else
|
||||
this.webRequest.Accept = "*/*";
|
||||
#endif
|
||||
this.SetCustomHeader("Cache-Control", "no-cache");
|
||||
this.ContentType = "application/json; charset=utf-8";
|
||||
}
|
||||
|
||||
internal readonly XboxLiveSettings contextSettings;
|
||||
internal HttpWebRequest webRequest;
|
||||
internal readonly Dictionary<string, string> customHeaders = new Dictionary<string, string>();
|
||||
internal bool hasPerformedRetryOn401 { get; set; }
|
||||
internal uint iterationNumber { get; set; }
|
||||
internal DateTime firstCallStartTime { get; set; }
|
||||
internal TimeSpan delayBeforeRetry { get; set; }
|
||||
|
||||
public bool LongHttpCall { get; set; }
|
||||
public string Method { get; private set; }
|
||||
public string Url { get; private set; }
|
||||
public string ContractVersion { get; set; }
|
||||
public bool RetryAllowed { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public string RequestBody { get; set; }
|
||||
public HttpCallResponseBodyType ResponseBodyType { get; set; }
|
||||
public XboxLiveUser User { get; private set; }
|
||||
public XboxLiveAPIName XboxLiveAPI { get; set; }
|
||||
public string CallerContext { get; set; }
|
||||
|
||||
private string Headers
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
bool isFirstVal = true;
|
||||
foreach (var header in this.customHeaders)
|
||||
{
|
||||
if (isFirstVal)
|
||||
{
|
||||
isFirstVal = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendFormat("{0}: {1}", header.Key, header.Value);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public Task<XboxLiveHttpResponse> GetResponseWithAuth(XboxLiveUser user)
|
||||
{
|
||||
TaskCompletionSource<XboxLiveHttpResponse> taskCompletionSource = new TaskCompletionSource<XboxLiveHttpResponse>();
|
||||
this.User = user;
|
||||
|
||||
user.GetTokenAndSignatureAsync(this.Method, this.Url, this.Headers).ContinueWith(
|
||||
tokenTask =>
|
||||
{
|
||||
if (tokenTask.IsFaulted)
|
||||
{
|
||||
taskCompletionSource.SetException(tokenTask.Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.SetAuthHeaders(tokenTask.Result);
|
||||
this.SetRequestHeaders();
|
||||
this.InternalGetResponse().ContinueWith(getResponseTask =>
|
||||
{
|
||||
if (getResponseTask.IsFaulted)
|
||||
{
|
||||
taskCompletionSource.SetException(getResponseTask.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletionSource.SetResult(getResponseTask.Result);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
taskCompletionSource.SetException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
private void SetAuthHeaders(TokenAndSignatureResult result)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
this.SetCustomHeader(AuthorizationHeaderName, string.Format("XBL3.0 x={0};{1}", result.XboxUserHash, result.Token));
|
||||
#else
|
||||
this.SetCustomHeader(AuthorizationHeaderName, string.Format("{0}", result.Token));
|
||||
#endif
|
||||
this.SetCustomHeader(SignatureHeaderName, result.Signature);
|
||||
}
|
||||
|
||||
private void SetRequestHeaders()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(this.ContractVersion))
|
||||
{
|
||||
this.SetCustomHeader("x-xbl-contract-version", this.ContractVersion);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> customHeader in this.customHeaders)
|
||||
{
|
||||
this.webRequest.Headers[customHeader.Key] = customHeader.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Task<XboxLiveHttpResponse> GetResponseWithoutAuth()
|
||||
{
|
||||
this.SetRequestHeaders();
|
||||
return this.InternalGetResponse();
|
||||
}
|
||||
|
||||
private void HandleThrottledCalls(XboxLiveHttpResponse httpCallResponse)
|
||||
{
|
||||
if (string.Equals(XboxLiveAppConfiguration.Instance.Sandbox, "RETAIL", StringComparison.Ordinal) ||
|
||||
this.contextSettings.AreAssertsForThrottlingInDevSandboxesDisabled)
|
||||
return;
|
||||
|
||||
#if DEBUG
|
||||
string msg;
|
||||
msg = "Xbox Live service call to " + httpCallResponse.Url.ToString() + " was throttled\r\n";
|
||||
msg += httpCallResponse.RequestBody;
|
||||
msg += "\r\n";
|
||||
msg += "You can temporarily disable the assert by calling\r\n";
|
||||
msg += "XboxLive.Instance.Settings.DisableAssertsForXboxLiveThrottlingInDevSandboxes()\r\n";
|
||||
msg += "Note that this will only disable this assert. You will still be throttled in all sandboxes.\r\n";
|
||||
Debug.WriteLine(msg);
|
||||
#endif
|
||||
|
||||
throw new XboxException("Xbox Live service call was throttled. See Output for more detail");
|
||||
}
|
||||
|
||||
private Task<XboxLiveHttpResponse> InternalGetResponse()
|
||||
{
|
||||
DateTime requestStartTime = DateTime.UtcNow;
|
||||
if (this.iterationNumber == 0)
|
||||
{
|
||||
this.firstCallStartTime = requestStartTime;
|
||||
}
|
||||
this.iterationNumber++;
|
||||
|
||||
HttpRetryAfterApiState apiState;
|
||||
if (HttpRetryAfterManager.Instance.GetState(this.XboxLiveAPI, out apiState))
|
||||
{
|
||||
if (this.ShouldFastFail(apiState, requestStartTime))
|
||||
{
|
||||
return this.HandleFastFail(apiState);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRetryAfterManager.Instance.ClearState(this.XboxLiveAPI);
|
||||
}
|
||||
}
|
||||
|
||||
this.SetUserAgent();
|
||||
|
||||
TaskCompletionSource<XboxLiveHttpResponse> taskCompletionSource = new TaskCompletionSource<XboxLiveHttpResponse>();
|
||||
|
||||
this.WriteRequestBodyAsync().ContinueWith(writeBodyTask =>
|
||||
{
|
||||
// The explicit cast in the next method should not be necessary, but Visual Studio is complaining
|
||||
// that the call is ambiguous. This removes that in-editor error.
|
||||
Task.Factory.FromAsync(this.webRequest.BeginGetResponse, (Func<IAsyncResult, WebResponse>)this.webRequest.EndGetResponse, null)
|
||||
.ContinueWith(getResponseTask =>
|
||||
{
|
||||
var httpWebResponse = ExtractHttpWebResponse(getResponseTask);
|
||||
int httpStatusCode = 0;
|
||||
bool networkFailure = false;
|
||||
if (httpWebResponse != null)
|
||||
{
|
||||
httpStatusCode = (int)httpWebResponse.StatusCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// classify as network failure if there's no HTTP status code and didn't get response
|
||||
networkFailure = getResponseTask.IsFaulted || getResponseTask.IsCanceled;
|
||||
}
|
||||
|
||||
var httpCallResponse = new XboxLiveHttpResponse(
|
||||
httpStatusCode,
|
||||
networkFailure,
|
||||
httpWebResponse,
|
||||
DateTime.UtcNow,
|
||||
requestStartTime,
|
||||
this.User != null ? this.User.XboxUserId : "",
|
||||
this.contextSettings,
|
||||
this.Url,
|
||||
this.XboxLiveAPI,
|
||||
this.Method,
|
||||
this.RequestBody,
|
||||
this.ResponseBodyType
|
||||
);
|
||||
|
||||
if (this.ShouldRetry(httpCallResponse))
|
||||
{
|
||||
// Wait and retry call
|
||||
this.RecordServiceResult(httpCallResponse, getResponseTask.Exception);
|
||||
this.RouteServiceCall(httpCallResponse);
|
||||
Sleep(this.delayBeforeRetry);
|
||||
this.webRequest = CloneHttpWebRequest(this.webRequest);
|
||||
this.InternalGetResponse().ContinueWith(retryGetResponseTask =>
|
||||
{
|
||||
if (retryGetResponseTask.IsFaulted)
|
||||
{
|
||||
taskCompletionSource.SetException(retryGetResponseTask.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletionSource.SetResult(retryGetResponseTask.Result);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (!networkFailure) // Got HTTP status code
|
||||
{
|
||||
// HTTP 429: TOO MANY REQUESTS errors should return a JSON debug payload
|
||||
// describing the details about why the call was throttled
|
||||
this.RecordServiceResult(httpCallResponse, getResponseTask.Exception);
|
||||
this.RouteServiceCall(httpCallResponse);
|
||||
|
||||
if (httpCallResponse.HttpStatus == HttpStatusCodeTooManyRequests)
|
||||
{
|
||||
this.HandleThrottledCalls(httpCallResponse);
|
||||
}
|
||||
|
||||
if (getResponseTask.IsFaulted)
|
||||
{
|
||||
taskCompletionSource.SetException(getResponseTask.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletionSource.SetResult(httpCallResponse);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle network errors
|
||||
|
||||
// HandleResponseError(); // TODO: extract error from JSON
|
||||
this.RecordServiceResult(httpCallResponse, getResponseTask.Exception);
|
||||
this.RouteServiceCall(httpCallResponse);
|
||||
taskCompletionSource.SetException(getResponseTask.Exception);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
private bool ShouldFastFail(
|
||||
HttpRetryAfterApiState apiState,
|
||||
DateTime currentTime
|
||||
)
|
||||
{
|
||||
if (apiState.Exception == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeSpan remainingTimeBeforeRetryAfter = apiState.RetryAfterTime - currentTime;
|
||||
if (remainingTimeBeforeRetryAfter.Ticks <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime timeoutTime = this.firstCallStartTime + this.contextSettings.HttpTimeoutWindow;
|
||||
|
||||
// If the Retry-After will happen first, just wait till Retry-After is done, and don't fast fail
|
||||
if (apiState.RetryAfterTime < timeoutTime)
|
||||
{
|
||||
Sleep(remainingTimeBeforeRetryAfter);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private Task<XboxLiveHttpResponse> HandleFastFail(HttpRetryAfterApiState apiState)
|
||||
{
|
||||
XboxLiveHttpResponse httpCallResponse = apiState.HttpCallResponse;
|
||||
this.RouteServiceCall(httpCallResponse);
|
||||
|
||||
TaskCompletionSource<XboxLiveHttpResponse> taskCompletionSource = new TaskCompletionSource<XboxLiveHttpResponse>();
|
||||
taskCompletionSource.SetException(apiState.Exception);
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
private void SetUserAgent()
|
||||
{
|
||||
const string userAgentType = "XboxServicesAPICSharp";
|
||||
lock (XboxLive.Instance)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userAgentVersion))
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
userAgentVersion = typeof(XboxLiveHttpRequest).Assembly.GetName().Version.ToString();
|
||||
#else
|
||||
userAgentVersion = typeof(XboxLiveHttpRequest).GetTypeInfo().Assembly.GetName().Version.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
string userAgent = userAgentType + "/" + userAgentVersion;
|
||||
if (!string.IsNullOrEmpty(this.CallerContext))
|
||||
{
|
||||
userAgent += " " + this.CallerContext;
|
||||
}
|
||||
this.SetCustomHeader("UserAgent", userAgent);
|
||||
}
|
||||
|
||||
private bool ShouldRetry(XboxLiveHttpResponse httpCallResponse)
|
||||
{
|
||||
int httpStatus = httpCallResponse.HttpStatus;
|
||||
|
||||
if (!this.RetryAllowed &&
|
||||
!(httpStatus == (int)HttpStatusCode.Unauthorized && this.User != null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((httpStatus == (int)HttpStatusCode.Unauthorized && !this.hasPerformedRetryOn401) ||
|
||||
httpStatus == (int)HttpStatusCode.RequestTimeout ||
|
||||
httpStatus == HttpStatusCodeTooManyRequests ||
|
||||
httpStatus == (int)HttpStatusCode.InternalServerError ||
|
||||
httpStatus == (int)HttpStatusCode.BadGateway ||
|
||||
httpStatus == (int)HttpStatusCode.ServiceUnavailable ||
|
||||
httpStatus == (int)HttpStatusCode.GatewayTimeout ||
|
||||
httpCallResponse.NetworkFailure
|
||||
)
|
||||
{
|
||||
TimeSpan retryAfter = httpCallResponse.RetryAfter;
|
||||
|
||||
// Compute how much time left before hitting the HttpTimeoutWindow setting.
|
||||
TimeSpan timeElapsedSinceFirstCall = httpCallResponse.ResponseReceivedTime - this.firstCallStartTime;
|
||||
TimeSpan remainingTimeBeforeTimeout = this.contextSettings.HttpTimeoutWindow - timeElapsedSinceFirstCall;
|
||||
if (remainingTimeBeforeTimeout.TotalSeconds <= MinHttpTimeoutSeconds) // Need at least 5 seconds to bother making a call
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Based on the retry iteration, delay 2,4,8,16,etc seconds by default between retries
|
||||
// Jitter the response between the current and next delay based on system clock
|
||||
// Max wait time is 1 minute
|
||||
double secondsToWaitMin = Math.Pow(this.contextSettings.HttpRetryDelay.TotalSeconds, this.iterationNumber);
|
||||
double secondsToWaitMax = Math.Pow(this.contextSettings.HttpRetryDelay.TotalSeconds, this.iterationNumber + 1);
|
||||
double secondsToWaitDelta = secondsToWaitMax - secondsToWaitMin;
|
||||
DateTime responseDate = httpCallResponse.ResponseReceivedTime;
|
||||
double randTime =
|
||||
(httpCallResponse.ResponseReceivedTime.Minute * 60.0 * 1000.0) +
|
||||
(httpCallResponse.ResponseReceivedTime.Second * 1000.0) +
|
||||
httpCallResponse.ResponseReceivedTime.Millisecond;
|
||||
double lerpScaler = (randTime % 10000) / 10000.0; // from 0 to 1 based on clock
|
||||
|
||||
if (XboxLive.UseMockHttp)
|
||||
{
|
||||
lerpScaler = 0; // make tests deterministic
|
||||
}
|
||||
|
||||
double secondsToWaitUncapped = secondsToWaitMin + secondsToWaitDelta * lerpScaler; // lerp between min & max wait
|
||||
double secondsToWait = Math.Min(secondsToWaitUncapped, MaxDelayTimeInSec); // cap max wait to 1 min
|
||||
TimeSpan waitTime = TimeSpan.FromSeconds(secondsToWait);
|
||||
if (retryAfter.TotalMilliseconds > 0)
|
||||
{
|
||||
// Use either the waitTime or Retry-After header, whichever is bigger
|
||||
this.delayBeforeRetry = (waitTime > retryAfter) ? waitTime : retryAfter;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.delayBeforeRetry = waitTime;
|
||||
}
|
||||
|
||||
if (remainingTimeBeforeTimeout < this.delayBeforeRetry + TimeSpan.FromSeconds(MinHttpTimeoutSeconds))
|
||||
{
|
||||
// Don't bother retrying when out of time
|
||||
return false;
|
||||
}
|
||||
|
||||
if (httpStatus == (int)HttpStatusCode.InternalServerError)
|
||||
{
|
||||
// For 500 - Internal Error, wait at least 10 seconds before retrying.
|
||||
TimeSpan minDelayForHttpInternalError = TimeSpan.FromSeconds(MinDelayForHttpInternalErrorInSec);
|
||||
if (this.delayBeforeRetry < minDelayForHttpInternalError)
|
||||
{
|
||||
this.delayBeforeRetry = minDelayForHttpInternalError;
|
||||
}
|
||||
}
|
||||
else if (httpStatus == (int)HttpStatusCode.Unauthorized)
|
||||
{
|
||||
return this.HandleUnauthorizedError();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HandleUnauthorizedError()
|
||||
{
|
||||
if (this.User != null) // if this is null, it does not need a valid token anyways
|
||||
{
|
||||
try
|
||||
{
|
||||
Task task = this.User.RefreshToken();
|
||||
task.Wait();
|
||||
this.hasPerformedRetryOn401 = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false; // if getting a new token failed, then we need to just return the 401 upwards
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.hasPerformedRetryOn401 = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If a request body has been provided, this will write it to the stream. If there is no request body a completed task
|
||||
/// will be returned.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents to request body write work.</returns>
|
||||
/// <remarks>This is used to make request chaining a little bit easier.</remarks>
|
||||
private Task WriteRequestBodyAsync()
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.RequestBody))
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
this.webRequest.ContentType = this.ContentType;
|
||||
|
||||
#if !WINDOWS_UWP
|
||||
this.webRequest.ContentLength = this.RequestBody.Length;
|
||||
#else
|
||||
this.webRequest.Headers[ContentLengthHeaderName] = this.RequestBody.Length.ToString();
|
||||
#endif
|
||||
|
||||
// The explicit cast in the next method should not be necessary, but Visual Studio is complaining
|
||||
// that the call is ambiguous. This removes that in-editor error.
|
||||
return Task.Factory.FromAsync(this.webRequest.BeginGetRequestStream, (Func<IAsyncResult, Stream>)this.webRequest.EndGetRequestStream, null)
|
||||
.ContinueWith(t =>
|
||||
{
|
||||
using (Stream body = t.Result)
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(body))
|
||||
{
|
||||
sw.Write(this.RequestBody);
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetCustomHeader(string headerName, string headerValue)
|
||||
{
|
||||
if (!this.customHeaders.ContainsKey(headerName))
|
||||
{
|
||||
this.customHeaders.Add(headerName, headerValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.customHeaders[headerName] = headerValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static XboxLiveHttpRequest Create(string httpMethod, string serverName, string pathQueryFragment)
|
||||
{
|
||||
return XboxLive.UseMockHttp ?
|
||||
new MockXboxLiveHttpRequest(httpMethod, serverName, pathQueryFragment) :
|
||||
new XboxLiveHttpRequest(httpMethod, serverName, pathQueryFragment);
|
||||
}
|
||||
|
||||
public void SetRangeHeader(uint startByte, uint endByte)
|
||||
{
|
||||
var byteRange = "bytes=" + startByte + "-" + endByte;
|
||||
#if !WINDOWS_UWP
|
||||
this.webRequest.AddRange((int)startByte, (int)endByte);
|
||||
#else
|
||||
this.webRequest.Headers[RangeHeaderName] = byteRange;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a query string out of a list of parameters
|
||||
/// </summary>
|
||||
/// <param name="paramDictionary">List of Parameters to be added to the query</param>
|
||||
/// <returns>a query string that should be appended to the request</returns>
|
||||
public static string GetQueryFromParams(Dictionary<string, string> paramDictionary)
|
||||
{
|
||||
var queryString = new StringBuilder();
|
||||
if (paramDictionary.Count > 0)
|
||||
{
|
||||
queryString.Append("?");
|
||||
const string queryDelimiter = "&";
|
||||
var firstParameter = true;
|
||||
foreach (var paramPair in paramDictionary)
|
||||
{
|
||||
if (firstParameter)
|
||||
firstParameter = false;
|
||||
else
|
||||
queryString.Append(queryDelimiter);
|
||||
|
||||
queryString.Append(string.Format("{0}={1}", paramPair.Key, paramPair.Value));
|
||||
}
|
||||
}
|
||||
|
||||
return queryString.ToString();
|
||||
}
|
||||
|
||||
private void RecordServiceResult(XboxLiveHttpResponse httpCallResponse, Exception exception)
|
||||
{
|
||||
// Only remember result if there was an error and there was a Retry-After header
|
||||
if (this.XboxLiveAPI != XboxLiveAPIName.Unspecified &&
|
||||
httpCallResponse.HttpStatus >= 400 //&&
|
||||
//httpCallResponse.RetryAfter.TotalSeconds > 0
|
||||
)
|
||||
{
|
||||
DateTime currentTime = DateTime.UtcNow;
|
||||
HttpRetryAfterApiState state = new HttpRetryAfterApiState();
|
||||
state.RetryAfterTime = currentTime + httpCallResponse.RetryAfter;
|
||||
state.HttpCallResponse = httpCallResponse;
|
||||
state.Exception = exception;
|
||||
HttpRetryAfterManager.Instance.SetState(this.XboxLiveAPI, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void RouteServiceCall(XboxLiveHttpResponse httpCallResponse)
|
||||
{
|
||||
// TODO: port route logic
|
||||
}
|
||||
|
||||
public static void Sleep(TimeSpan timeSpan)
|
||||
{
|
||||
// WinRT doesn't have Thread.Sleep, so using ManualResetEvent
|
||||
new ManualResetEvent(false).WaitOne(timeSpan);
|
||||
}
|
||||
|
||||
private HttpWebResponse ExtractHttpWebResponse(Task<WebResponse> getResponseTask)
|
||||
{
|
||||
if (getResponseTask.IsFaulted && getResponseTask.Exception != null)
|
||||
{
|
||||
if (getResponseTask.Exception.InnerException is WebException)
|
||||
{
|
||||
WebException e = (WebException)getResponseTask.Exception.InnerException;
|
||||
if (e.Response is HttpWebResponse)
|
||||
{
|
||||
HttpWebResponse w = (HttpWebResponse)e.Response;
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (HttpWebResponse)getResponseTask.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpWebRequest CloneHttpWebRequest(HttpWebRequest original)
|
||||
{
|
||||
HttpWebRequest clone = (HttpWebRequest)WebRequest.Create(original.RequestUri.AbsoluteUri);
|
||||
PropertyInfo[] properties = original.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
if (property.Name != "ContentLength" && property.Name != "Headers")
|
||||
{
|
||||
object value = property.GetValue(original, null);
|
||||
if (property.CanWrite)
|
||||
{
|
||||
property.SetValue(clone, value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var item in original.Headers.AllKeys)
|
||||
{
|
||||
clone.Headers[item] = original.Headers[item];
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.IO;
|
||||
using global::System.Net;
|
||||
using global::System.Text;
|
||||
|
||||
public class XboxLiveHttpResponse
|
||||
{
|
||||
public const string RetryAfterHeader = "Retry-After";
|
||||
public const int RetryAfterCapInSeconds = 15;
|
||||
public const string ETagHeader = "ETag";
|
||||
public const string DateHeader = "Date";
|
||||
|
||||
public TimeSpan RetryAfter { get; private set; }
|
||||
|
||||
public DateTime ResponseReceivedTime { get; private set; }
|
||||
|
||||
public DateTime RequestStartTime { get; private set; }
|
||||
|
||||
public string ETag { get; private set; }
|
||||
|
||||
public string ResponseDate { get; private set; }
|
||||
|
||||
public string ErrorMessage { get; private set; }
|
||||
|
||||
public int ErrorCode { get; private set; }
|
||||
|
||||
public int HttpStatus { get; private set; }
|
||||
|
||||
public Dictionary<string, string> Headers { get; private set; }
|
||||
|
||||
public byte[] ResponseBodyVector { get; private set; }
|
||||
|
||||
public string ResponseBodyString { get; private set; }
|
||||
|
||||
public HttpWebResponse response { get; private set; }
|
||||
|
||||
public string XboxUserId { get; private set; }
|
||||
|
||||
public XboxLiveSettings ContextSettings { get; private set; }
|
||||
|
||||
public string Url { get; private set; }
|
||||
|
||||
public XboxLiveAPIName XboxLiveAPI { get; private set; }
|
||||
|
||||
public string Method { get; private set; }
|
||||
|
||||
public string RequestBody { get; private set; }
|
||||
|
||||
public HttpCallResponseBodyType ResponseBodyType { get; private set; }
|
||||
|
||||
public bool NetworkFailure { get; private set; }
|
||||
|
||||
internal XboxLiveHttpResponse()
|
||||
{
|
||||
}
|
||||
|
||||
internal XboxLiveHttpResponse(
|
||||
int httpStatusCode,
|
||||
bool networkFailure,
|
||||
HttpWebResponse response,
|
||||
DateTime responseReceivedTime,
|
||||
DateTime requestStartTime,
|
||||
string xboxUserId,
|
||||
XboxLiveSettings contextSettings,
|
||||
string url,
|
||||
XboxLiveAPIName xboxLiveAPI,
|
||||
string method,
|
||||
string requestBody,
|
||||
HttpCallResponseBodyType responseBodyType
|
||||
)
|
||||
{
|
||||
this.HttpStatus = httpStatusCode;
|
||||
this.NetworkFailure = networkFailure;
|
||||
this.response = response;
|
||||
this.ResponseReceivedTime = responseReceivedTime;
|
||||
this.RequestStartTime = requestStartTime;
|
||||
this.XboxUserId = xboxUserId;
|
||||
this.ContextSettings = contextSettings;
|
||||
this.Url = url;
|
||||
this.XboxLiveAPI = xboxLiveAPI;
|
||||
this.Method = method;
|
||||
this.RequestBody = requestBody;
|
||||
this.ResponseBodyType = responseBodyType;
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
using (Stream body = response.GetResponseStream())
|
||||
{
|
||||
this.Initialize((int)response.StatusCode, body, response.ContentLength, "utf-8", response.Headers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void Initialize(int httpStatus, Stream body, long contentLength, string characterSet, WebHeaderCollection headers)
|
||||
{
|
||||
if (this.HttpStatus == 0)
|
||||
{
|
||||
this.HttpStatus = httpStatus;
|
||||
}
|
||||
this.Headers = new Dictionary<string, string>();
|
||||
|
||||
int vectorSize = contentLength > int.MaxValue ? int.MaxValue : (int)contentLength;
|
||||
this.ResponseBodyVector = new byte[vectorSize];
|
||||
if (contentLength > 0)
|
||||
{
|
||||
int totalBytesRead = 0;
|
||||
do
|
||||
{
|
||||
int bytesRead = body.Read(this.ResponseBodyVector, totalBytesRead, this.ResponseBodyVector.Length - totalBytesRead);
|
||||
|
||||
// This means we're at the end of the stream.
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
throw new ArgumentException(string.Format("Expected body stream to contain {0} bytes but only read {1} bytes.", contentLength, totalBytesRead), "body");
|
||||
}
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
}
|
||||
while (totalBytesRead < contentLength);
|
||||
|
||||
|
||||
if (this.ResponseBodyType != HttpCallResponseBodyType.VectorBody)
|
||||
{
|
||||
Encoding encoding;
|
||||
switch (characterSet.ToLower())
|
||||
{
|
||||
case "utf-8":
|
||||
encoding = Encoding.UTF8;
|
||||
break;
|
||||
case "ascii":
|
||||
encoding = Encoding.ASCII;
|
||||
break;
|
||||
default:
|
||||
encoding = Encoding.UTF8;
|
||||
break;
|
||||
}
|
||||
|
||||
this.ResponseBodyString = encoding.GetString(this.ResponseBodyVector);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < headers.Count; ++i)
|
||||
{
|
||||
var key = headers.AllKeys[i];
|
||||
this.Headers.Add(key, headers[key]);
|
||||
}
|
||||
|
||||
string retryAfterInSeconds;
|
||||
this.Headers.TryGetValue(RetryAfterHeader, out retryAfterInSeconds);
|
||||
if (!string.IsNullOrEmpty(retryAfterInSeconds))
|
||||
{
|
||||
int numRetryAfterInSeconds = 0;
|
||||
int.TryParse(retryAfterInSeconds, out numRetryAfterInSeconds);
|
||||
numRetryAfterInSeconds = Math.Min(numRetryAfterInSeconds, RetryAfterCapInSeconds);
|
||||
this.RetryAfter = TimeSpan.FromSeconds(numRetryAfterInSeconds);
|
||||
}
|
||||
|
||||
string value = string.Empty;
|
||||
this.Headers.TryGetValue(ETagHeader, out value);
|
||||
this.ETag = value;
|
||||
|
||||
value = string.Empty;
|
||||
this.Headers.TryGetValue(DateHeader, out value);
|
||||
this.ResponseDate = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
public class XboxLiveLogCallEventArgs : EventArgs
|
||||
{
|
||||
public string Message { get; private set; }
|
||||
|
||||
public string Message
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public XboxServicesDiagnosticsTraceLevel Level
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string Category { get; private set; }
|
||||
|
||||
public XboxServicesDiagnosticsTraceLevel Level { get; private set; }
|
||||
}
|
||||
}
|
|
@ -16,11 +16,7 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
public XboxLiveServices(XboxLiveUser user)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// TODO Implement mock title storage service for unity editor
|
||||
this.TitleStorageService = null;
|
||||
this.PrivacyService = null;
|
||||
#else
|
||||
#if WINDOWS_UWP
|
||||
IntPtr xboxLiveContext;
|
||||
var xsapiResult = XboxLiveContextCreate(user.PCXboxLiveUser, out xboxLiveContext);
|
||||
|
||||
|
@ -32,6 +28,10 @@ namespace Microsoft.Xbox.Services
|
|||
|
||||
this.TitleStorageService = new TitleStorageService(XboxLiveContextPtr);
|
||||
this.PrivacyService = new PrivacyService(XboxLiveContextPtr);
|
||||
#else
|
||||
// TODO MockServices and/or MockHttp
|
||||
this.TitleStorageService = null;
|
||||
this.PrivacyService = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -5,22 +5,16 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
using global::System;
|
||||
|
||||
public class XboxLiveSettings
|
||||
public class XboxLiveContextSettings
|
||||
{
|
||||
private const int DefaultHttpTimeoutWindowInSeconds = 20;
|
||||
private const int DefaultLongHttpTimeoutInSeconds = 5 * 60;
|
||||
private const int DefaultRetryDelayInSeconds = 2;
|
||||
|
||||
public XboxLiveSettings()
|
||||
public XboxLiveContextSettings()
|
||||
{
|
||||
this.DiagnosticsTraceLevel = XboxServicesDiagnosticsTraceLevel.Off;
|
||||
this.HttpTimeoutWindow = TimeSpan.FromSeconds(DefaultHttpTimeoutWindowInSeconds);
|
||||
this.LongHttpTimeout = TimeSpan.FromSeconds(DefaultLongHttpTimeoutInSeconds);
|
||||
this.HttpRetryDelay = TimeSpan.FromSeconds(DefaultRetryDelayInSeconds);
|
||||
}
|
||||
|
||||
public bool UseCoreDispatcherForEventRouting { get; set; }
|
||||
|
||||
public TimeSpan HttpTimeout { get; set; }
|
||||
|
||||
public TimeSpan HttpTimeoutWindow { get; set; }
|
||||
|
||||
public TimeSpan HttpRetryDelay { get; set; }
|
||||
|
@ -39,15 +33,15 @@ namespace Microsoft.Xbox.Services
|
|||
}
|
||||
}
|
||||
|
||||
//public TimeSpan WebsocketTimeoutWindow { get; set; }
|
||||
public TimeSpan WebsocketTimeoutWindow { get; set; }
|
||||
|
||||
//public event EventHandler<XboxLiveLogCallEventArgs> LogCallRouted;
|
||||
public event EventHandler<XboxLiveLogCallEventArgs> LogCallRouted;
|
||||
|
||||
//public bool EnableServiceCallRoutedEvents { get; set; }
|
||||
public bool EnableServiceCallRoutedEvents { get; set; }
|
||||
|
||||
//public void DisableAssertsForMaximumNumberOfWebsocketsActivated(XboxLiveContextRecommendedSetting setting)
|
||||
//{
|
||||
// throw new NotImplementedException();
|
||||
//}
|
||||
public void DisableAssertsForMaximumNumberOfWebsocketsActivated(XboxLiveContextRecommendedSetting setting)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,10 +4,8 @@
|
|||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Text;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Xbox.Services.System;
|
||||
|
||||
public partial class XboxLiveUser : IXboxLiveUser
|
||||
|
@ -17,37 +15,8 @@ namespace Microsoft.Xbox.Services
|
|||
private readonly IUserImpl userImpl;
|
||||
private XboxLiveServices xboxLiveServices;
|
||||
|
||||
private static event EventHandler<SignInCompletedEventArgs> InternalSignInCompleted;
|
||||
private static List<EventHandler<SignInCompletedEventArgs>> signInDelegates = new List<EventHandler<SignInCompletedEventArgs>>();
|
||||
public static event EventHandler<SignInCompletedEventArgs> SignInCompleted
|
||||
{
|
||||
add
|
||||
{
|
||||
InternalSignInCompleted += value;
|
||||
signInDelegates.Add(value);
|
||||
}
|
||||
remove
|
||||
{
|
||||
InternalSignInCompleted -= value;
|
||||
signInDelegates.Remove(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static event EventHandler<SignOutCompletedEventArgs> InternalSignOutCompleted;
|
||||
private static List<EventHandler<SignOutCompletedEventArgs>> signOutDelegates = new List<EventHandler<SignOutCompletedEventArgs>>();
|
||||
public static event EventHandler<SignOutCompletedEventArgs> SignOutCompleted
|
||||
{
|
||||
add
|
||||
{
|
||||
InternalSignOutCompleted += value;
|
||||
signOutDelegates.Add(value);
|
||||
}
|
||||
remove
|
||||
{
|
||||
InternalSignOutCompleted -= value;
|
||||
signOutDelegates.Remove(value);
|
||||
}
|
||||
}
|
||||
public static event EventHandler<SignInCompletedEventArgs> SignInCompleted;
|
||||
public static event EventHandler<SignOutCompletedEventArgs> SignOutCompleted;
|
||||
|
||||
public string WebAccountId
|
||||
{
|
||||
|
@ -136,36 +105,19 @@ namespace Microsoft.Xbox.Services
|
|||
return this.userImpl.SignInImpl(false, false);
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers)
|
||||
public Task<GetTokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers)
|
||||
{
|
||||
return this.GetTokenAndSignatureArrayAsync(httpMethod, url, headers, null);
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers, string body)
|
||||
public Task<GetTokenAndSignatureResult> GetTokenAndSignatureAsync(string httpMethod, string url, string headers, string body)
|
||||
{
|
||||
return this.GetTokenAndSignatureArrayAsync(httpMethod, url, headers, body == null ? null : Encoding.UTF8.GetBytes(body));
|
||||
}
|
||||
|
||||
public Task<TokenAndSignatureResult> GetTokenAndSignatureArrayAsync(string httpMethod, string url, string headers, byte[] body)
|
||||
public Task<GetTokenAndSignatureResult> GetTokenAndSignatureArrayAsync(string httpMethod, string url, string headers, byte[] body)
|
||||
{
|
||||
return this.userImpl.InternalGetTokenAndSignatureAsync(httpMethod, url, headers, body, false, false);
|
||||
}
|
||||
|
||||
public Task RefreshToken()
|
||||
{
|
||||
return this.userImpl.InternalGetTokenAndSignatureAsync("GET", this.userImpl.AuthConfig.XboxLiveEndpoint, null, null, false, true);
|
||||
}
|
||||
|
||||
protected static void OnSignInCompleted(IXboxLiveUser user)
|
||||
{
|
||||
var handler = InternalSignInCompleted;
|
||||
if (handler != null) handler(null, new SignInCompletedEventArgs(user));
|
||||
}
|
||||
|
||||
protected static void OnSignOutCompleted(IXboxLiveUser user)
|
||||
{
|
||||
var handler = InternalSignOutCompleted;
|
||||
if (handler != null) handler(null, new SignOutCompletedEventArgs(user));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,111 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
|
||||
public class XboxServiceCallRoutedEventArgs : EventArgs
|
||||
{
|
||||
|
||||
public string XboxUserId
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string XboxUserId { get; private set; }
|
||||
|
||||
public TimeSpan ElapsedCallTime
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public TimeSpan ElapsedCallTime { get; private set; }
|
||||
|
||||
public DateTimeOffset ResponseTimeUTC
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public DateTimeOffset ResponseTimeUTC { get; private set; }
|
||||
|
||||
public DateTimeOffset RequestTimeUTC
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public DateTimeOffset RequestTimeUTC { get; private set; }
|
||||
|
||||
public string FullResponseToString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string FullResponseToString { get; private set; }
|
||||
|
||||
public uint HttpStatus
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public uint HttpStatus { get; private set; }
|
||||
|
||||
public string Signature
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string Signature { get; private set; }
|
||||
|
||||
public string Token
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string Token { get; private set; }
|
||||
|
||||
public string ETag
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string ETag { get; private set; }
|
||||
|
||||
public string ResponseBody
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string ResponseBody { get; private set;}
|
||||
|
||||
public string ResponseHeaders
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string ResponseHeaders { get; private set; }
|
||||
|
||||
public uint ResponseCount
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public uint ResponseCount { get; private set; }
|
||||
|
||||
public HttpCallRequestMessage RequestBody
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public HttpCallRequestMessage RequestBody { get; private set; }
|
||||
|
||||
public string RequestHeaders
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string RequestHeaders { get; private set; }
|
||||
|
||||
public Uri Url
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string HttpMethod
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public Uri Url { get; private set; }
|
||||
|
||||
public string HttpMethod { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
|
@ -16,5 +12,4 @@ namespace Microsoft.Xbox.Services
|
|||
Info = 3,
|
||||
Verbose = 4,
|
||||
}
|
||||
|
||||
}
|
|
@ -4,138 +4,17 @@
|
|||
namespace Microsoft.Xbox.Services.Leaderboard
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Text;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
public class LeaderboardService : ILeaderboardService
|
||||
{
|
||||
private const string leaderboardApiContract = "4";
|
||||
|
||||
private static readonly Uri leaderboardsBaseUri = new Uri("https://leaderboards.xboxlive.com");
|
||||
|
||||
private readonly XboxLiveAppConfiguration appConfig;
|
||||
|
||||
internal LeaderboardService()
|
||||
{
|
||||
this.appConfig = XboxLive.Instance.AppConfig;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<LeaderboardResult> GetLeaderboardAsync(XboxLiveUser user, LeaderboardQuery query)
|
||||
{
|
||||
string skipToXboxUserId = null;
|
||||
if (query.SkipResultToMe)
|
||||
{
|
||||
skipToXboxUserId = user.XboxUserId;
|
||||
}
|
||||
|
||||
string requestPath = "";
|
||||
//if (string.IsNullOrEmpty(query.SocialGroup))
|
||||
//{
|
||||
// requestPath = CreateLeaderboardUrlPath(this.appConfig.PrimaryServiceConfigId, query.StatName, query.MaxItems, skipToXboxUserId, query.SkipResultToRank, query.ContinuationToken);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// requestPath = CreateSocialLeaderboardUrlPath(this.appConfig.PrimaryServiceConfigId, query.StatName, user.XboxUserId, query.MaxItems, skipToXboxUserId, query.SkipResultToRank, query.ContinuationToken, query.SocialGroup);
|
||||
//}
|
||||
|
||||
XboxLiveHttpRequest request = XboxLiveHttpRequest.Create(HttpMethod.Get, leaderboardsBaseUri.ToString(), requestPath);
|
||||
request.ContractVersion = leaderboardApiContract;
|
||||
request.XboxLiveAPI = XboxLiveAPIName.GetLeaderboardInternal;
|
||||
return request.GetResponseWithAuth(user)
|
||||
.ContinueWith(
|
||||
responseTask =>
|
||||
{
|
||||
return this.HandleLeaderboardResponse(responseTask, query);
|
||||
});
|
||||
}
|
||||
|
||||
internal LeaderboardResult HandleLeaderboardResponse(Task<XboxLiveHttpResponse> responseTask, LeaderboardQuery query)
|
||||
{
|
||||
XboxLiveHttpResponse response = responseTask.Result;
|
||||
|
||||
if (response.HttpStatus != 200)
|
||||
{
|
||||
throw new XboxException("Leaderboard request failed with " + response.HttpStatus);
|
||||
}
|
||||
|
||||
LeaderboardResponse lbResponse = JsonSerialization.FromJson<LeaderboardResponse>(response.ResponseBodyString);
|
||||
|
||||
IList<LeaderboardColumn> columns = new List<LeaderboardColumn> { lbResponse.LeaderboardInfo.Column };
|
||||
|
||||
IList<LeaderboardRow> rows = new List<LeaderboardRow>();
|
||||
foreach (LeaderboardRowResponse row in lbResponse.Rows)
|
||||
{
|
||||
LeaderboardRow newRow = new LeaderboardRow
|
||||
{
|
||||
Gamertag = row.Gamertag,
|
||||
Percentile = row.Percentile,
|
||||
Rank = (uint)row.Rank,
|
||||
XboxUserId = row.XboxUserId,
|
||||
Values = row.Value != null ? new List<string> { row.Value } : row.Values,
|
||||
};
|
||||
rows.Add(newRow);
|
||||
}
|
||||
|
||||
LeaderboardQuery nextQuery = new LeaderboardQuery(query, lbResponse.PagingInfo != null ? lbResponse.PagingInfo.ContinuationToken : null);
|
||||
LeaderboardResult result = new LeaderboardResult(rows, columns, lbResponse.LeaderboardInfo.TotalCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string CreateLeaderboardUrlPath(string serviceConfigurationId, string statName, uint maxItems, string skipToXboxUserId, uint skipToRank, string continuationToken)
|
||||
{
|
||||
StringBuilder requestPath = new StringBuilder();
|
||||
requestPath.AppendFormat("scids/{0}/leaderboards/stat({1})?", serviceConfigurationId, statName);
|
||||
AppendQueryParameters(requestPath, maxItems, skipToXboxUserId, skipToRank, continuationToken);
|
||||
|
||||
return requestPath.ToString();
|
||||
}
|
||||
|
||||
private static string CreateSocialLeaderboardUrlPath(string serviceConfigurationId, string statName, string xuid, uint maxItems, string skipToXboxUserId, uint skipToRank, string continuationToken, string socialGroup)
|
||||
{
|
||||
StringBuilder requestPath = new StringBuilder();
|
||||
requestPath.AppendFormat("users/xuid({0})/scids/{1}/stats/{2}/people/{3}?", xuid, serviceConfigurationId, statName, socialGroup);
|
||||
AppendQueryParameters(requestPath, maxItems, skipToXboxUserId, skipToRank, continuationToken);
|
||||
|
||||
return requestPath.ToString();
|
||||
}
|
||||
|
||||
private static void AppendQueryParameters(StringBuilder queryString, uint maxItems, string skipToXboxUserId, uint skipToRank, string continuationToken)
|
||||
{
|
||||
if (maxItems > 0)
|
||||
{
|
||||
AppendQueryParameter(queryString, "maxItems", maxItems);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(skipToXboxUserId) && skipToRank > 0)
|
||||
{
|
||||
throw new ArgumentException("Cannot provide both user and rank to skip to.");
|
||||
}
|
||||
|
||||
if (continuationToken != null)
|
||||
{
|
||||
AppendQueryParameter(queryString, "continuationToken", continuationToken);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(skipToXboxUserId))
|
||||
{
|
||||
AppendQueryParameter(queryString, "skipToUser", skipToXboxUserId);
|
||||
}
|
||||
else if (skipToRank > 0)
|
||||
{
|
||||
AppendQueryParameter(queryString, "skipToRank", skipToRank);
|
||||
}
|
||||
|
||||
// Remove the trailing query string bit
|
||||
queryString.Remove(queryString.Length - 1, 1);
|
||||
}
|
||||
|
||||
private static void AppendQueryParameter(StringBuilder builder, string parameterName, object parameterValue)
|
||||
{
|
||||
builder.Append(parameterName);
|
||||
builder.Append("=");
|
||||
builder.Append(parameterValue);
|
||||
builder.Append("&");
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Microsoft.Xbox.Services.Leaderboard
|
||||
{
|
||||
using global::Newtonsoft.Json;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading.Tasks;
|
||||
|
@ -20,7 +21,7 @@ namespace Microsoft.Xbox.Services.Leaderboard
|
|||
|
||||
internal LeaderboardResult CreateLeaderboardResponse(LeaderboardQuery query)
|
||||
{
|
||||
LeaderboardResponse lbResponse = JsonSerialization.FromJson<LeaderboardResponse>(@"{""pagingInfo"":null,""leaderboardInfo"":{""totalCount"":10,""columnDefinition"":{""statName"":""EnemysDefeated"",""type"":""Double""}},""userList"":[{""gamertag"":""Fake User 1"",""xuid"":""1111111111111111"",""percentile"":0.1,""rank"":1,""globalrank"":10,""value"":""1000"",""valuemetadata"":null},{""gamertag"":""Fake User 2"",""xuid"":""2222222222222222"",""percentile"":0.2,""rank"":2,""globalrank"":20,""value"":""900"",""valuemetadata"":null},{""gamertag"":""Fake User 3"",""xuid"":""3333333333333333"",""percentile"":0.3,""rank"":3,""globalrank"":30,""value"":""800"",""valuemetadata"":null},{""gamertag"":""Fake User 4"",""xuid"":""4444444444444444"",""percentile"":0.4,""rank"":4,""globalrank"":40,""value"":""700"",""valuemetadata"":null},{""gamertag"":""Fake User 5"",""xuid"":""5555555555555555"",""percentile"":0.5,""rank"":5,""globalrank"":50,""value"":""600"",""valuemetadata"":null},{""gamertag"":""Fake User 6"",""xuid"":""6666666666666666"",""percentile"":0.6,""rank"":6,""globalrank"":60,""value"":""500"",""valuemetadata"":null},{""gamertag"":""Fake User 7"",""xuid"":""7777777777777777"",""percentile"":0.7,""rank"":7,""globalrank"":70,""value"":""400"",""valuemetadata"":null},{""gamertag"":""Fake User 8"",""xuid"":""8888888888888888"",""percentile"":0.8,""rank"":8,""globalrank"":80,""value"":""300"",""valuemetadata"":null},{""gamertag"":""Fake User 9"",""xuid"":""9999999999999999"",""percentile"":0.9,""rank"":9,""globalrank"":90,""value"":""200"",""valuemetadata"":null},{""gamertag"":""Fake User 10"",""xuid"":""1010101010101010"",""percentile"":1.0,""rank"":10,""globalrank"":100,""value"":""100"",""valuemetadata"":null},]}");
|
||||
LeaderboardResponse lbResponse = JsonConvert.DeserializeObject<LeaderboardResponse>(@"{""pagingInfo"":null,""leaderboardInfo"":{""totalCount"":10,""columnDefinition"":{""statName"":""EnemysDefeated"",""type"":""Double""}},""userList"":[{""gamertag"":""Fake User 1"",""xuid"":""1111111111111111"",""percentile"":0.1,""rank"":1,""globalrank"":10,""value"":""1000"",""valuemetadata"":null},{""gamertag"":""Fake User 2"",""xuid"":""2222222222222222"",""percentile"":0.2,""rank"":2,""globalrank"":20,""value"":""900"",""valuemetadata"":null},{""gamertag"":""Fake User 3"",""xuid"":""3333333333333333"",""percentile"":0.3,""rank"":3,""globalrank"":30,""value"":""800"",""valuemetadata"":null},{""gamertag"":""Fake User 4"",""xuid"":""4444444444444444"",""percentile"":0.4,""rank"":4,""globalrank"":40,""value"":""700"",""valuemetadata"":null},{""gamertag"":""Fake User 5"",""xuid"":""5555555555555555"",""percentile"":0.5,""rank"":5,""globalrank"":50,""value"":""600"",""valuemetadata"":null},{""gamertag"":""Fake User 6"",""xuid"":""6666666666666666"",""percentile"":0.6,""rank"":6,""globalrank"":60,""value"":""500"",""valuemetadata"":null},{""gamertag"":""Fake User 7"",""xuid"":""7777777777777777"",""percentile"":0.7,""rank"":7,""globalrank"":70,""value"":""400"",""valuemetadata"":null},{""gamertag"":""Fake User 8"",""xuid"":""8888888888888888"",""percentile"":0.8,""rank"":8,""globalrank"":80,""value"":""300"",""valuemetadata"":null},{""gamertag"":""Fake User 9"",""xuid"":""9999999999999999"",""percentile"":0.9,""rank"":9,""globalrank"":90,""value"":""200"",""valuemetadata"":null},{""gamertag"":""Fake User 10"",""xuid"":""1010101010101010"",""percentile"":1.0,""rank"":10,""globalrank"":100,""value"":""100"",""valuemetadata"":null},]}");
|
||||
|
||||
IList<LeaderboardColumn> columns = new List<LeaderboardColumn> { lbResponse.LeaderboardInfo.Column };
|
||||
|
||||
|
@ -34,7 +35,7 @@ namespace Microsoft.Xbox.Services.Leaderboard
|
|||
Values = row.Value != null ? new List<string> { row.Value } : row.Values
|
||||
}).ToList();
|
||||
|
||||
// Create a result with an 'empty' next query so that it won't have paiging.
|
||||
// Create a result with an 'empty' next query so that it won't have paging.
|
||||
LeaderboardResult result = new LeaderboardResult(rows, columns, lbResponse.LeaderboardInfo.TotalCount);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,8 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementTitleAssociation.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpCallRequestMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpCallResponseBodyType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpMethod.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpRequestMessageType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpRetryAfterApiState.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpRetryAfterManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpCallResponseBodyType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\IXboxLiveUser.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\ServiceCallLoggingConfig.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\SignInCompletedEventArgs.cs" />
|
||||
|
@ -39,12 +36,9 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Common\TokenAndSignatureResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxException.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLive.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveAPIName.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveAppConfiguration.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveContextRecommendedSetting.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveContextThrottleSetting.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveHttpRequest.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveHttpResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveLogCallEventArgs.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveServices.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveSettings.cs" />
|
||||
|
@ -79,16 +73,19 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)GameServerPlatform\QualityOfServiceServer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardQueryImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardResultImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQueryImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResultImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardStatType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardResultImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Privacy\IPrivacyService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Privacy\Models\PrivacySettingsRequest.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Shared\IXboxWebsocketClient.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\ISocialManagerPresenceRecord.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\IXboxSocialUserGroup.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\SocialManagerPresenceRecord.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\ProfileService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\IStatisticManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\LeaderboardResultEventArgs.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\MockStatisticManager.cs" />
|
||||
|
@ -98,31 +95,24 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticEventType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticValue.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\AuthConfig.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\IUserImpl.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\MarshallingHelpers.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveCallbackContext.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveServicesSettings.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XsapiCallbackContext.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XsapiResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\ITitleStorageService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\SortOrder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQuery.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardColumn.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardRow.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\CreateMatchTicketResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\HopperStatisticsResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchmakingService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchTicketDetailsResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\PreserveSessionMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\TicketStatus.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Mock\MockXboxLiveData.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Mock\MockXboxLiveHttpRequest.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Mock\MockXboxLiveHttpResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Mock\XboxLiveHttpRequestEqualityComparer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\FindMatchCompletedEventArgs.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\HostChangedEventArgs.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\Joinability.cs" />
|
||||
|
@ -195,7 +185,6 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionError.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionErrorEventArgs.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionState.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Shared\CallBufferTimer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\ISocialManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\MockSocialManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\PreferredColor.cs" />
|
||||
|
@ -214,7 +203,6 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\XboxSocialUserGroup.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsRequest.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsResponse.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\ProfileService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackItem.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationService.cs" />
|
||||
|
@ -228,13 +216,9 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Social\XboxSocialRelationshipResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Social\XboxUserProfile.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\GamingPrivilege.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\JsonSerialization.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\StringService.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\VerifyStringResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\VerifyStringResultCode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveServicesSettings.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxSystemFactory.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)System\XboxUserIdEqualityComparer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobMetadata.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobMetadataResult.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobResult.cs" />
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.IO;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
public static class MockXboxLiveData
|
||||
{
|
||||
public static Dictionary<string, MockRequestData> MockResponses { get; set; }
|
||||
|
||||
static MockXboxLiveData()
|
||||
{
|
||||
MockResponses = new Dictionary<string, MockRequestData>();
|
||||
}
|
||||
|
||||
public static void Load(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string rawData = File.ReadAllText(path);
|
||||
MockResponses = JsonConvert.DeserializeObject<Dictionary<string, MockRequestData>>(rawData);
|
||||
}
|
||||
|
||||
public static XboxLiveHttpResponse GetMockResponse(XboxLiveHttpRequest request)
|
||||
{
|
||||
XboxLiveHttpRequestEqualityComparer comparer = new XboxLiveHttpRequestEqualityComparer();
|
||||
foreach (var mockData in MockResponses.Values)
|
||||
{
|
||||
if (comparer.Equals(request, mockData.Request))
|
||||
{
|
||||
return mockData.Response;
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, string> headers = new Dictionary<string, string>
|
||||
{
|
||||
{ "X-XblCorrelationId", Guid.NewGuid().ToString() },
|
||||
{ "Date", DateTime.UtcNow.ToString("R") },
|
||||
};
|
||||
|
||||
return new MockXboxLiveHttpResponse(404, headers);
|
||||
}
|
||||
|
||||
public class MockRequestData
|
||||
{
|
||||
public MockXboxLiveHttpRequest Request { get; set; }
|
||||
public MockXboxLiveHttpResponse Response { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Diagnostics;
|
||||
using global::System.IO;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
public class MockXboxLiveHttpRequest : XboxLiveHttpRequest
|
||||
{
|
||||
public static string MockDataPath;
|
||||
|
||||
public MockXboxLiveHttpRequest(string method, string serverName, string pathQueryFragment) : base(method, serverName, pathQueryFragment)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<XboxLiveHttpResponse> GetResponseWithoutAuth()
|
||||
{
|
||||
// Save the mock data out for testing.
|
||||
string requestData = JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
|
||||
string outputDir = @"C:\Temp\MockData";
|
||||
if(!Directory.Exists(outputDir))
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
}
|
||||
|
||||
string outputPath = Path.Combine(outputDir, "data.txt");
|
||||
using (var stream = this.GetWriteStream(outputPath))
|
||||
{
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
writer.Write(requestData);
|
||||
}
|
||||
}
|
||||
return Task.FromResult(MockXboxLiveData.GetMockResponse(this));
|
||||
}
|
||||
|
||||
// This is used because there are times when multiple requests are issued at the same time
|
||||
// As a result the output file becomes locked for the first request resulting in the other
|
||||
// requests being unable to edit the file.
|
||||
private FileStream GetWriteStream(string path, int timeoutMs = 1000)
|
||||
{
|
||||
var time = Stopwatch.StartNew();
|
||||
while (time.ElapsedMilliseconds < timeoutMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FileStream(path, FileMode.Append, FileAccess.Write);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
throw new TimeoutException(string.Format("Failed to get a write handle to {0} within {1} ms.", path, timeoutMs));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.IO;
|
||||
using global::System.Net;
|
||||
using global::System.Text;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public class MockXboxLiveHttpResponse : XboxLiveHttpResponse
|
||||
{
|
||||
public MockXboxLiveHttpResponse(int httpStatus) : this(httpStatus, null, null, new Dictionary<string, string>())
|
||||
{
|
||||
}
|
||||
|
||||
public MockXboxLiveHttpResponse(int httpStatus, Dictionary<string, string> headers) : this(httpStatus, null, null, headers)
|
||||
{
|
||||
}
|
||||
|
||||
[JsonConstructor]
|
||||
public MockXboxLiveHttpResponse(int httpStatus, JObject body, string characterSet = null, Dictionary<string, string> headers = null)
|
||||
{
|
||||
string bodyJson = JsonConvert.SerializeObject(body);
|
||||
byte[] bodyBytes = Encoding.UTF8.GetBytes(bodyJson ?? "");
|
||||
Stream bodyStream = new MemoryStream(bodyBytes);
|
||||
|
||||
WebHeaderCollection webHeaders = new WebHeaderCollection();
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> header in headers)
|
||||
{
|
||||
webHeaders[header.Key] = header.Value;
|
||||
}
|
||||
}
|
||||
|
||||
this.Initialize(httpStatus, bodyStream, bodyStream.Length, characterSet ?? "utf-8", webHeaders);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
|
||||
public sealed class XboxLiveHttpRequestEqualityComparer : IEqualityComparer<XboxLiveHttpRequest>
|
||||
{
|
||||
public static List<string> IgnoredHeaders = new List<string>
|
||||
{
|
||||
"Authorization"
|
||||
};
|
||||
|
||||
public bool Equals(XboxLiveHttpRequest x, XboxLiveHttpRequest y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (ReferenceEquals(x, null)) return false;
|
||||
if (ReferenceEquals(y, null)) return false;
|
||||
if (x.GetType() != y.GetType()) return false;
|
||||
return string.Equals(x.Method, y.Method)
|
||||
&& string.Equals(x.Url, y.Url);
|
||||
}
|
||||
|
||||
private static bool CheckHeadersAreEqual(IDictionary<string, string> x, IDictionary<string, string> y)
|
||||
{
|
||||
if (x.Count != y.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.Keys.Where(key => !IgnoredHeaders.Contains(key)).All(key => x[key] == y[key]);
|
||||
}
|
||||
|
||||
public int GetHashCode(XboxLiveHttpRequest obj)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = obj.Method.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ obj.Url.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
/// Get the list of Xbox Live Ids the calling user should avoid during multiplayer matchmaking.
|
||||
/// </summary>
|
||||
/// <returns>A collection of XboxUserIds that correspond to the calling user's avoid list.</returns>
|
||||
Task<IList<string>> GetAvoidListAsync();
|
||||
Task<IReadOnlyList<string>> GetAvoidListAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Check a single permission with a single target user.
|
||||
|
@ -33,15 +33,15 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
/// See Microsoft::Xbox::Services::Privacy::PermissionIdConstants for the latest options.</param>
|
||||
/// <param name="targetXboxUserIds">The collection of target Xbox user IDs to check permissions against.</param>
|
||||
/// <returns>A collection of <see cref="PermissionCheckResult"/> objects containing results of the target xbox user ids.</returns>
|
||||
Task<List<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync(
|
||||
IList<string> permissionIds,
|
||||
IList<string> targetXboxUserIds
|
||||
Task<IReadOnlyList<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync(
|
||||
IReadOnlyList<string> permissionIds,
|
||||
IReadOnlyList<string> targetXboxUserIds
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of Xbox Live Ids that the calling user should not hear (mute) during multiplayer matchmaking.
|
||||
/// </summary>
|
||||
/// <returns>The collection of Xbox user IDs that represent the mute list for a user.</returns>
|
||||
Task<IList<string>> GetMuteListAsync();
|
||||
Task<IReadOnlyList<string>> GetMuteListAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
|
||||
public class MultiplePermissionsCheckResult
|
||||
{
|
||||
public IList<PermissionCheckResult> Items { get; private set; }
|
||||
public IReadOnlyList<PermissionCheckResult> Items { get; private set; }
|
||||
|
||||
public string XboxUserId { get; private set; }
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
|
||||
XboxUserId = MarshalingHelpers.Utf8ToString(multiplePermissionsStruct.xboxUserId);
|
||||
|
||||
Items = new List<PermissionCheckResult>((int)multiplePermissionsStruct.itemsCount);
|
||||
var items = new List<PermissionCheckResult>((int)multiplePermissionsStruct.itemsCount);
|
||||
|
||||
int size = MarshalingHelpers.SizeOf<XSAPI_PRIVACY_PERMISSION_CHECK_RESULT>();
|
||||
IntPtr permissionStructPtr = multiplePermissionsStruct.items;
|
||||
|
@ -28,9 +28,10 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
for (ulong i = 0; i < multiplePermissionsStruct.itemsCount; ++i)
|
||||
{
|
||||
var permissionCheckResultStruct = MarshalingHelpers.PtrToStructure<XSAPI_PRIVACY_PERMISSION_CHECK_RESULT>(permissionStructPtr);
|
||||
Items.Add(new PermissionCheckResult(permissionCheckResultStruct));
|
||||
items.Add(new PermissionCheckResult(permissionCheckResultStruct));
|
||||
permissionStructPtr = permissionStructPtr.Increment(size);
|
||||
}
|
||||
Items = items;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
|
||||
public class PermissionCheckResult
|
||||
{
|
||||
public IList<PermissionDenyReason> Reasons { get; private set; }
|
||||
public IReadOnlyList<PermissionDenyReason> DenyReasons { get; private set; }
|
||||
|
||||
public string PermissionRequested { get; private set; }
|
||||
|
||||
|
@ -27,17 +27,17 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
IsAllowed = permissionCheckResultStruct.isAllowed;
|
||||
PermissionRequested = MarshalingHelpers.Utf8ToString(permissionCheckResultStruct.permissionRequested);
|
||||
|
||||
Reasons = new List<PermissionDenyReason>((int)permissionCheckResultStruct.denyReasonsCount);
|
||||
var denyReasons = new List<PermissionDenyReason>((int)permissionCheckResultStruct.denyReasonsCount);
|
||||
|
||||
int size = MarshalingHelpers.SizeOf<XSAPI_PRIVACY_PERMISSION_DENY_REASON>();
|
||||
IntPtr denyReasonPtr = permissionCheckResultStruct.denyReasons;
|
||||
|
||||
for (ulong i = 0; i < permissionCheckResultStruct.denyReasonsCount; ++i)
|
||||
{
|
||||
Reasons.Add(new PermissionDenyReason(denyReasonPtr));
|
||||
denyReasons.Add(new PermissionDenyReason(denyReasonPtr));
|
||||
denyReasonPtr = denyReasonPtr.Increment(size);
|
||||
}
|
||||
|
||||
DenyReasons = denyReasons;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
this.pCXboxLiveContext = pCXboxLiveContext;
|
||||
}
|
||||
|
||||
public Task<IList<string>> GetAvoidListAsync()
|
||||
public Task<IReadOnlyList<string>> GetAvoidListAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<IList<string>>();
|
||||
var tcs = new TaskCompletionSource<IReadOnlyList<string>>();
|
||||
Task.Run(() =>
|
||||
{
|
||||
int contextKey = XsapiCallbackContext<object, IList<string>>.CreateContext(null, tcs);
|
||||
int contextKey = XsapiCallbackContext<object, IReadOnlyList<string>>.CreateContext(null, tcs);
|
||||
|
||||
var xsapiResult = PrivacyGetAvoidList(this.pCXboxLiveContext, GetPrivacyUserListComplete, (IntPtr)contextKey, XboxLive.DefaultTaskGroupId);
|
||||
if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
|
@ -35,12 +35,12 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task<IList<string>> GetMuteListAsync()
|
||||
public Task<IReadOnlyList<string>> GetMuteListAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<IList<string>>();
|
||||
var tcs = new TaskCompletionSource<IReadOnlyList<string>>();
|
||||
Task.Run(() =>
|
||||
{
|
||||
int contextKey = XsapiCallbackContext<object, IList<string>>.CreateContext(null, tcs);
|
||||
int contextKey = XsapiCallbackContext<object, IReadOnlyList<string>>.CreateContext(null, tcs);
|
||||
|
||||
var xsapiResult = PrivacyGetMuteList(this.pCXboxLiveContext, GetPrivacyUserListComplete, (IntPtr)contextKey, XboxLive.DefaultTaskGroupId);
|
||||
if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
|
@ -58,7 +58,7 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
{
|
||||
if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK)
|
||||
{
|
||||
context.TaskCompletionSource.SetResult(MarshalingHelpers.Utf8StringArrayToStringList(xboxUserIdList, (int)count));
|
||||
context.TaskCompletionSource.SetResult(MarshalingHelpers.Utf8StringArrayToStringList(xboxUserIdList, count));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -109,15 +109,15 @@ namespace Microsoft.Xbox.Services.Privacy
|
|||
}
|
||||
}
|
||||
|
||||
public Task<List<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync(IList<string> permissionIds, IList<string> targetXboxUserIds)
|
||||
public Task<IReadOnlyList<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync(IReadOnlyList<string> permissionIds, IReadOnlyList<string> targetXboxUserIds)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<List<MultiplePermissionsCheckResult>>();
|
||||
var tcs = new TaskCompletionSource<IReadOnlyList<MultiplePermissionsCheckResult>>();
|
||||
Task.Run(() =>
|
||||
{
|
||||
var permissionIdsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(permissionIds);
|
||||
var xuidsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(targetXboxUserIds);
|
||||
|
||||
int contextKey = XsapiCallbackContext<CheckMultiplePermissionsContext, List<MultiplePermissionsCheckResult>>.CreateContext(
|
||||
int contextKey = XsapiCallbackContext<CheckMultiplePermissionsContext, IReadOnlyList<MultiplePermissionsCheckResult>>.CreateContext(
|
||||
new CheckMultiplePermissionsContext
|
||||
{
|
||||
permissionIdsArray = permissionIdsArray,
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Xbox.Services.Shared
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
internal class CallBufferEventArgs<T> : EventArgs
|
||||
{
|
||||
public CallBufferEventArgs(List<T> elements)
|
||||
{
|
||||
this.Elements = elements;
|
||||
}
|
||||
|
||||
public List<T> Elements { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper class to throttle calls and buffer call data. One or more calls made to <see cref="Fire"/> will be
|
||||
/// batched together and passed as a single
|
||||
/// </summary>
|
||||
internal class CallBufferTimer<T>
|
||||
{
|
||||
private readonly TimeSpan period;
|
||||
private DateTime previousTime;
|
||||
|
||||
private readonly object elementBufferLock = new object();
|
||||
private readonly HashSet<T> elementBuffer;
|
||||
private TaskCompletionSource<bool> currentCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// A lock around the current call to prevent multiple callers
|
||||
/// </summary>
|
||||
private readonly object callLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// A task that represents the current call in progress.
|
||||
/// </summary>
|
||||
private Task inProgressTask = Task.FromResult(true);
|
||||
|
||||
public event EventHandler<CallBufferEventArgs<T>> Completed;
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="CallBufferTimer{T}"/>
|
||||
/// </summary>
|
||||
/// <param name="period">The minimum duration between triggers of the <see cref="Completed"/> event.</param>
|
||||
/// <param name="comparer">If not null, overrides the comparer used to compare elements in the buffer.</param>
|
||||
public CallBufferTimer(TimeSpan period, IEqualityComparer<T> comparer = null)
|
||||
{
|
||||
this.period = period;
|
||||
this.elementBuffer = new HashSet<T>(comparer);
|
||||
}
|
||||
|
||||
public Task Fire(IList<T> elements)
|
||||
{
|
||||
if (elements == null)
|
||||
{
|
||||
throw new ArgumentNullException("elements");
|
||||
}
|
||||
|
||||
if (elements.Count == 0)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
TaskCompletionSource<bool> tcs;
|
||||
lock (this.elementBufferLock)
|
||||
{
|
||||
foreach (T user in elements)
|
||||
{
|
||||
this.elementBuffer.Add(user);
|
||||
}
|
||||
// Grab the TCS associated with this buffer. This will complete
|
||||
// when all the elements in this buffer have been sent.
|
||||
tcs = this.currentCompletionSource;
|
||||
}
|
||||
|
||||
this.FireHelper();
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
private void FireHelper()
|
||||
{
|
||||
// If there's a call in progress, it will queue up a new
|
||||
// task once it's done so we can just return.
|
||||
if (!this.inProgressTask.IsCompleted) return;
|
||||
|
||||
TaskCompletionSource<bool> inProgressCompletionSource;
|
||||
|
||||
// Prevent multiple people from initiating calls at the same time.
|
||||
lock (this.callLock)
|
||||
{
|
||||
if (!this.inProgressTask.IsCompleted) return;
|
||||
|
||||
// Grab the current completion source, and mark it as in-progress by
|
||||
// setting it's task as the current in progress task. Note that we
|
||||
// are not swapping out the completion source yet, which means that
|
||||
// people can continue to queue elements into this buffer until we
|
||||
// actually execute this call.
|
||||
inProgressCompletionSource = this.currentCompletionSource;
|
||||
this.inProgressTask = inProgressCompletionSource.Task;
|
||||
}
|
||||
|
||||
// Determine if we need to delay at all.
|
||||
TimeSpan callDelay = this.period - (DateTime.Now - this.previousTime);
|
||||
if (callDelay < TimeSpan.Zero) callDelay = TimeSpan.Zero;
|
||||
|
||||
// Yes, we will 'delay' for zero time in some cases, but without await
|
||||
// it would be much uglier to handle both cases explicitly.
|
||||
Task.Delay(callDelay).ContinueWith(continuationAction =>
|
||||
{
|
||||
if (continuationAction.IsFaulted)
|
||||
{
|
||||
inProgressCompletionSource.SetException(continuationAction.Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the current buffer and TCS out and replace them with new ones.
|
||||
// Anyone who attempts to add stuff to the buffer after this point will
|
||||
// get a new TCS and as a result will wait until the next call occurs.
|
||||
List<T> elements;
|
||||
lock (this.elementBufferLock)
|
||||
{
|
||||
inProgressCompletionSource = this.currentCompletionSource;
|
||||
this.currentCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
elements = this.elementBuffer.ToList();
|
||||
this.elementBuffer.Clear();
|
||||
}
|
||||
|
||||
this.inProgressTask = inProgressCompletionSource.Task;
|
||||
|
||||
if (elements.Count == 0)
|
||||
{
|
||||
// No elements to request so complete immediately
|
||||
inProgressCompletionSource.SetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.previousTime = DateTime.Now;
|
||||
|
||||
this.OnCompleted(new CallBufferEventArgs<T>(elements));
|
||||
inProgressCompletionSource.SetResult(true);
|
||||
|
||||
if (this.elementBuffer.Count > 0)
|
||||
{
|
||||
this.FireHelper();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
inProgressCompletionSource.SetException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void OnCompleted(CallBufferEventArgs<T> e)
|
||||
{
|
||||
var handler = this.Completed;
|
||||
if (handler != null) handler(this, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xbox.Services.System;
|
||||
|
||||
namespace Microsoft.Xbox.Services.Shared
|
||||
{
|
||||
interface IXboxWebsocketClient : IDisposable
|
||||
{
|
||||
Task<object> Connect(
|
||||
XboxLiveUser xblUser,
|
||||
string uri,
|
||||
string subprotocol);
|
||||
|
||||
void Send(string message, Action<bool> onSendComplete);
|
||||
|
||||
void Close();
|
||||
}
|
||||
}
|
|
@ -163,7 +163,7 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
{
|
||||
new SocialManagerPresenceTitleRecord
|
||||
{
|
||||
TitleId = XboxLiveAppConfiguration.Instance.TitleId,
|
||||
TitleId = XboxLiveAppConfiguration.SingletonInstance.TitleId,
|
||||
IsTitleActive = true,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,6 +35,5 @@ namespace Microsoft.Xbox.Services.Social.Manager
|
|||
return m_instance;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -9,101 +9,21 @@ namespace Microsoft.Xbox.Services.Social
|
|||
|
||||
public class ProfileService
|
||||
{
|
||||
private readonly string profileEndpoint;
|
||||
|
||||
protected XboxLiveAppConfiguration config;
|
||||
|
||||
internal ProfileService()
|
||||
{
|
||||
this.config = XboxLive.Instance.AppConfig;
|
||||
this.profileEndpoint = this.config.GetEndpointForService("profile");
|
||||
}
|
||||
|
||||
public Task<XboxUserProfile> GetUserProfileAsync(XboxLiveUser user, string xboxUserId)
|
||||
public Task<XboxUserProfile> GetUserProfileAsync(string xboxUserId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xboxUserId))
|
||||
{
|
||||
throw new ArgumentException("invalid xboxUserId", "xboxUserId");
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
List<string> profiles = new List<string> { xboxUserId };
|
||||
|
||||
return this.GetUserProfilesAsync(user, profiles).ContinueWith(task => task.Result[0]);
|
||||
public Task<IReadOnlyList<XboxUserProfile>> GetUserProfilesAsync(IReadOnlyList<string> xboxUserIds)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<XboxUserProfile>> GetUserProfilesAsync(XboxLiveUser user, List<string> xboxUserIds)
|
||||
{
|
||||
if (xboxUserIds == null)
|
||||
{
|
||||
throw new ArgumentNullException("xboxUserIds");
|
||||
}
|
||||
if (xboxUserIds.Count == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("xboxUserIds", "Empty list of user ids");
|
||||
}
|
||||
|
||||
if (XboxLive.UseMockServices)
|
||||
{
|
||||
Random rand = new Random();
|
||||
List<XboxUserProfile> outputUsers = new List<XboxUserProfile>(xboxUserIds.Count);
|
||||
foreach (string xuid in xboxUserIds)
|
||||
{
|
||||
// generate a fake dev gamertag
|
||||
string gamertag = "2 dev " + rand.Next(10000);
|
||||
XboxUserProfile profile = new XboxUserProfile()
|
||||
{
|
||||
XboxUserId = xuid,
|
||||
ApplicationDisplayName = gamertag,
|
||||
ApplicationDisplayPictureResizeUri = new Uri("http://images-eds.xboxlive.com/image?url=z951ykn43p4FqWbbFvR2Ec.8vbDhj8G2Xe7JngaTToBrrCmIEEXHC9UNrdJ6P7KI4AAOijCgOA3.jozKovAH98vieJP1ResWJCw2dp82QtambLRqzQbSIiqrCug0AvP4&format=png"),
|
||||
GameDisplayName = gamertag,
|
||||
GameDisplayPictureResizeUri = new Uri("http://images-eds.xboxlive.com/image?url=z951ykn43p4FqWbbFvR2Ec.8vbDhj8G2Xe7JngaTToBrrCmIEEXHC9UNrdJ6P7KI4AAOijCgOA3.jozKovAH98vieJP1ResWJCw2dp82QtambLRqzQbSIiqrCug0AvP4&format=png"),
|
||||
Gamerscore = rand.Next(250000).ToString(),
|
||||
Gamertag = gamertag
|
||||
};
|
||||
|
||||
outputUsers.Add(profile);
|
||||
}
|
||||
|
||||
return Task.FromResult(outputUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
XboxLiveHttpRequest req = XboxLiveHttpRequest.Create(HttpMethod.Post, profileEndpoint, "/users/batch/profile/settings");
|
||||
|
||||
req.ContractVersion = "2";
|
||||
req.ContentType = "application/json; charset=utf-8";
|
||||
Models.ProfileSettingsRequest reqBodyObject = new Models.ProfileSettingsRequest(xboxUserIds, true);
|
||||
req.RequestBody = JsonSerialization.ToJson(reqBodyObject);
|
||||
req.XboxLiveAPI = XboxLiveAPIName.GetUserProfiles;
|
||||
return req.GetResponseWithAuth(user).ContinueWith(task =>
|
||||
{
|
||||
XboxLiveHttpResponse response = task.Result;
|
||||
Models.ProfileSettingsResponse responseBody = new Models.ProfileSettingsResponse();
|
||||
responseBody = JsonSerialization.FromJson<Models.ProfileSettingsResponse>(response.ResponseBodyString);
|
||||
|
||||
List<XboxUserProfile> outputUsers = new List<XboxUserProfile>();
|
||||
foreach (Models.ProfileUser entry in responseBody.profileUsers)
|
||||
{
|
||||
XboxUserProfile profile = new XboxUserProfile()
|
||||
{
|
||||
XboxUserId = entry.id,
|
||||
Gamertag = entry.Gamertag(),
|
||||
GameDisplayName = entry.GameDisplayName(),
|
||||
GameDisplayPictureResizeUri = new Uri(entry.GameDisplayPic()),
|
||||
ApplicationDisplayName = entry.AppDisplayName(),
|
||||
ApplicationDisplayPictureResizeUri = new Uri(entry.AppDisplayPic()),
|
||||
Gamerscore = entry.Gamerscore()
|
||||
};
|
||||
|
||||
outputUsers.Add(profile);
|
||||
}
|
||||
|
||||
return outputUsers;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Task<List<XboxUserProfile>> GetUserProfilesForSocialGroupAsync(string socialGroup)
|
||||
public Task<IReadOnlyList<XboxUserProfile>> GetUserProfilesForSocialGroupAsync(string socialGroup)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
internal class AuthConfig
|
||||
{
|
||||
public string Sandbox { get; set; }
|
||||
public string XboxLiveRelyingParty { get; set; }
|
||||
public string EnvironmentPrefix { get; set; }
|
||||
public string Environment { get; set; }
|
||||
public bool UseCompactTicket { get; set; }
|
||||
public string XboxLiveEndpoint { get; set; }
|
||||
public string RPSTicketService { get; set; }
|
||||
public string RPSTicketPolicy { get; set; }
|
||||
public string UserTokenSiteName { get; set; }
|
||||
public AuthConfig()
|
||||
{
|
||||
XboxLiveEndpoint = "https://xboxlive.com";
|
||||
XboxLiveRelyingParty = "https://auth.xboxlive.com";
|
||||
UserTokenSiteName = GetEndpointPath("user.auth", "", Environment, false);
|
||||
RPSTicketPolicy = UseCompactTicket ? "MBI_SSL" : "DELEGATION";
|
||||
RPSTicketService = UseCompactTicket ? UserTokenSiteName : "xbl.signin xbl.friends";
|
||||
}
|
||||
|
||||
public static string GetEndpointPath(string serviceName, string EnvironmentPrefix, string Environment, bool appendProtocol = true)
|
||||
{
|
||||
string endpointPath = "";
|
||||
if(appendProtocol)
|
||||
{
|
||||
endpointPath += "https://";
|
||||
}
|
||||
endpointPath += EnvironmentPrefix + serviceName + Environment + ".xboxlive.com";
|
||||
return endpointPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
|
@ -33,5 +29,4 @@ namespace Microsoft.Xbox.Services.System
|
|||
MultiplayerSessions = 254,
|
||||
AddFriend = 255,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,16 +14,14 @@ namespace Microsoft.Xbox.Services.System
|
|||
string AgeGroup { get; }
|
||||
string Privileges { get; }
|
||||
string WebAccountId { get; }
|
||||
AuthConfig AuthConfig { get; }
|
||||
#if WINDOWS_UWP
|
||||
Windows.System.User CreationContext { get; }
|
||||
#endif
|
||||
#if !UNITY_EDITOR
|
||||
IntPtr XboxLiveUserPtr { get; }
|
||||
#endif
|
||||
|
||||
Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh);
|
||||
|
||||
Task<TokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh);
|
||||
Task<GetTokenAndSignatureResult> InternalGetTokenAndSignatureAsync(string httpMethod, string url, string headers, byte[] body, bool promptForCredentialsIfNeeded, bool forceRefresh);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
internal static class JsonSerialization
|
||||
{
|
||||
internal static T FromJson<T>(string jsonInput)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(jsonInput);
|
||||
}
|
||||
|
||||
internal static string ToJson<T>(T input)
|
||||
{
|
||||
return JsonConvert.SerializeObject(input);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ namespace Microsoft.Xbox.Services
|
|||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Runtime.InteropServices;
|
||||
using global::System.Text;
|
||||
|
||||
|
@ -51,9 +52,9 @@ namespace Microsoft.Xbox.Services
|
|||
/// <param name="arrayPtr">Pointer to the C-style string array</param>
|
||||
/// <param name="length">Number of strings in the array</param>
|
||||
/// <returns></returns>
|
||||
internal static IList<string> Utf8StringArrayToStringList(IntPtr arrayPtr, int length)
|
||||
internal static IList<string> Utf8StringArrayToStringList(IntPtr arrayPtr, uint length)
|
||||
{
|
||||
var list = new List<string>(length);
|
||||
var list = new List<string>((int)length);
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
string str = MarshalingHelpers.Utf8ToString(Marshal.ReadIntPtr(arrayPtr));
|
||||
|
@ -69,9 +70,9 @@ namespace Microsoft.Xbox.Services
|
|||
/// </summary>
|
||||
/// <param name="strings">The array of string to allocate</param>
|
||||
/// <returns>An IntPtr to the first Utf8String pointer</returns>
|
||||
internal static IntPtr StringListToHGlobalUtf8StringArray(IList<string> strings)
|
||||
internal static IntPtr StringListToHGlobalUtf8StringArray(IEnumerable<string> strings)
|
||||
{
|
||||
var firstString = Marshal.AllocHGlobal(IntPtr.Size * strings.Count);
|
||||
var firstString = Marshal.AllocHGlobal(IntPtr.Size * strings.Count());
|
||||
int offset = 0;
|
||||
foreach (var str in strings)
|
||||
{
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
public class StringService
|
||||
{
|
||||
|
||||
public Task<VerifyStringResult> VerifyStringAsync(string stringToVerify)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
public class VerifyStringResult
|
||||
{
|
||||
|
||||
public string FirstOffendingSubstring
|
||||
{
|
||||
get;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
|
@ -15,5 +11,4 @@ namespace Microsoft.Xbox.Services.System
|
|||
TooLong = 2,
|
||||
UnknownError = 3,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@ namespace Microsoft.Xbox.Services.System
|
|||
|
||||
public static XboxLiveServicesSettings SingletonInstance { get; private set; }
|
||||
|
||||
//public event EventHandler<XboxLiveLogCallEventArgs> LogCallRouted;
|
||||
public event EventHandler<XboxLiveLogCallEventArgs> LogCallRouted;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Xbox.Services;
|
||||
using Microsoft.Xbox.Services.Shared;
|
||||
|
||||
namespace Microsoft.Xbox.Services.System
|
||||
{
|
||||
class XboxSystemFactory
|
||||
{
|
||||
private static XboxSystemFactory factory;
|
||||
public static XboxSystemFactory GetSingletonInstance()
|
||||
{
|
||||
if(factory == null)
|
||||
{
|
||||
factory = new XboxSystemFactory();
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
private XboxSystemFactory()
|
||||
{
|
||||
}
|
||||
|
||||
public IXboxWebsocketClient CreateWebsocketClient()
|
||||
{
|
||||
#if WINDOWS_UWP
|
||||
return null;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
namespace Microsoft.Xbox.Services
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xbox.Services.Social.Manager;
|
||||
|
||||
/// <summary>
|
||||
/// An equality comparer that only uses the XUID property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used in a variety of places in order to perform dictionary lookups efficiently.
|
||||
/// </remarks>
|
||||
public sealed class XboxUserIdEqualityComparer : IEqualityComparer<XboxLiveUser>
|
||||
{
|
||||
public bool Equals(XboxLiveUser x, XboxLiveUser y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (ReferenceEquals(x, null)) return false;
|
||||
if (ReferenceEquals(y, null)) return false;
|
||||
if (x.GetType() != y.GetType()) return false;
|
||||
return string.Equals(x.XboxUserId, y.XboxUserId);
|
||||
}
|
||||
|
||||
public int GetHashCode(XboxLiveUser obj)
|
||||
{
|
||||
return obj.XboxUserId.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An equality comparer that only uses the XUID property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used in a variety of places in order to perform dictionary lookups efficiently.
|
||||
/// </remarks>
|
||||
public sealed class XboxSocialUserIdEqualityComparer : IEqualityComparer<XboxSocialUser>
|
||||
{
|
||||
private static XboxSocialUserIdEqualityComparer instance;
|
||||
private static readonly object instanceLock = new object();
|
||||
|
||||
public static XboxSocialUserIdEqualityComparer Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new XboxSocialUserIdEqualityComparer();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Equals(XboxSocialUser x, XboxSocialUser y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (ReferenceEquals(x, null)) return false;
|
||||
if (ReferenceEquals(y, null)) return false;
|
||||
if (x.GetType() != y.GetType()) return false;
|
||||
return string.Equals(x.XboxUserId, y.XboxUserId);
|
||||
}
|
||||
|
||||
public int GetHashCode(XboxSocialUser obj)
|
||||
{
|
||||
return obj.XboxUserId.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
namespace Microsoft.Xbox.Services.Shared.TitleStorage
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.Xbox.Services.Shared.TitleStorage
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Xbox.Services.TitleStorage;
|
||||
|
||||
/// <summary>
|
||||
|
@ -72,7 +75,7 @@
|
|||
/// <param name="etagMatchCondition">The ETag match condition used to determine if the blob data should be uploaded.</param>
|
||||
/// <param name="preferredDownloadBlockSize">The preferred upload block size in bytes for binary blobs. </param>
|
||||
/// <returns>An instance of the <see cref="TitleStorageBlobMetadata"/> class with updated ETag and Length Properties.</returns>
|
||||
Task<TitleStorageBlobMetadata> UploadBlobAsync(TitleStorageBlobMetadata blobMetadata, List<byte> blobBuffer, TitleStorageETagMatchCondition etagMatchCondition, uint preferredUploadBlockSize);
|
||||
Task<TitleStorageBlobMetadata> UploadBlobAsync(TitleStorageBlobMetadata blobMetadata, IReadOnlyList<byte> blobBuffer, TitleStorageETagMatchCondition etagMatchCondition, uint preferredUploadBlockSize);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
/// <summary>
|
||||
/// [optional] Timestamp assigned by the client.
|
||||
/// </summary>
|
||||
public DateTimeOffset? ClientTimeStamp { get; private set; }
|
||||
public DateTimeOffset ClientTimeStamp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// ETag for the file used in read and write requests.
|
||||
|
@ -157,13 +157,22 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
var displayName = MarshalingHelpers.StringToHGlobalUtf8(this.DisplayName);
|
||||
var etag = MarshalingHelpers.StringToHGlobalUtf8(this.ETag);
|
||||
|
||||
TitleStorageCreateBlobMetadata(scid, StorageType, path, BlobType, xuid, displayName, etag, IntPtr.Zero, /*TODO client timestamp*/ out metadataPtr);
|
||||
IntPtr clientTimePtr = IntPtr.Zero;
|
||||
if (this.ClientTimeStamp != null)
|
||||
{
|
||||
var clientTime = this.ClientTimeStamp.ToUnixTimeMilliseconds();
|
||||
clientTimePtr = Marshal.AllocHGlobal(MarshalingHelpers.SizeOf<UInt64>());
|
||||
Marshal.WriteInt64(clientTimePtr, clientTime);
|
||||
}
|
||||
|
||||
TitleStorageCreateBlobMetadata(scid, StorageType, path, BlobType, xuid, displayName, etag, clientTimePtr, out metadataPtr);
|
||||
|
||||
Marshal.FreeHGlobal(scid);
|
||||
Marshal.FreeHGlobal(path);
|
||||
Marshal.FreeHGlobal(xuid);
|
||||
Marshal.FreeHGlobal(displayName);
|
||||
Marshal.FreeHGlobal(etag);
|
||||
Marshal.FreeHGlobal(clientTimePtr);
|
||||
}
|
||||
|
||||
internal void Refresh()
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
|
||||
namespace Microsoft.Xbox.Services.TitleStorage
|
||||
{
|
||||
using global::System;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
//
|
||||
namespace Microsoft.Xbox.Services.TitleStorage
|
||||
{
|
||||
using global::System.Runtime.InteropServices;
|
||||
using global::System;
|
||||
using global::System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// Blob data returned from the cloud.
|
||||
|
|
|
@ -28,6 +28,15 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
/// </summary>
|
||||
public TitleStorageType StorageType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the user associated with the storage area
|
||||
/// </summary>
|
||||
public string XboxUserId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The service configuration ID to get the quota from
|
||||
/// </summary>
|
||||
public string ServiceConfigurationId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialze a TitleStorageQuota from the corresponding C object
|
||||
|
@ -37,6 +46,8 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
QuotaBytes = quotaStruct.QuotaBytes;
|
||||
UsedBytes = quotaStruct.UsedBytes;
|
||||
StorageType = quotaStruct.storageType;
|
||||
XboxUserId = MarshalingHelpers.Utf8ToString(quotaStruct.XboxUserId);
|
||||
ServiceConfigurationId = MarshalingHelpers.Utf8ToString(quotaStruct.ServiceConfigurationId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Runtime.InteropServices;
|
||||
using global::System.Threading.Tasks;
|
||||
using Microsoft.Xbox.Services.Shared.TitleStorage;
|
||||
|
@ -38,7 +39,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
var tcs = new TaskCompletionSource<TitleStorageQuota>();
|
||||
Task.Run(() =>
|
||||
{
|
||||
var scid = MarshalingHelpers.StringToHGlobalUtf8(XboxLive.Instance.AppConfig.PrimaryServiceConfigId);
|
||||
var scid = MarshalingHelpers.StringToHGlobalUtf8(XboxLive.Instance.AppConfig.ServiceConfigurationId);
|
||||
|
||||
int contextKey;
|
||||
var context = XsapiCallbackContext<object, TitleStorageQuota>.CreateContext(null, tcs, out contextKey);
|
||||
|
@ -246,7 +247,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
/// <param name="etagMatchCondition">The ETag match condition used to determine if the blob data should be uploaded.</param>
|
||||
/// <param name="preferredDownloadBlockSize">The preferred upload block size in bytes for binary blobs. </param>
|
||||
/// <returns>An instance of the <see cref="TitleStorageBlobMetadata"/> class with updated ETag and Length Properties.</returns>
|
||||
public Task<TitleStorageBlobMetadata> UploadBlobAsync(TitleStorageBlobMetadata blobMetadata, List<byte> blobBuffer, TitleStorageETagMatchCondition etagMatchCondition, uint preferredUploadBlockSize)
|
||||
public Task<TitleStorageBlobMetadata> UploadBlobAsync(TitleStorageBlobMetadata blobMetadata, IReadOnlyList<byte> blobBuffer, TitleStorageETagMatchCondition etagMatchCondition, uint preferredUploadBlockSize)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<TitleStorageBlobMetadata>();
|
||||
Task.Run(() =>
|
||||
|
@ -255,7 +256,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
|
|||
var context = XsapiCallbackContext<TitleStorageBlobMetadata, TitleStorageBlobMetadata>.CreateContext(blobMetadata, tcs, out contextKey);
|
||||
|
||||
var buffer = Marshal.AllocHGlobal(blobBuffer.Count);
|
||||
Marshal.Copy(blobBuffer.ToArray(), 0, buffer, blobBuffer.Count);
|
||||
Marshal.Copy(Enumerable.ToArray<byte>(blobBuffer), 0, buffer, blobBuffer.Count);
|
||||
context.PointersToFree = new List<IntPtr> { buffer };
|
||||
|
||||
var xsapiResult = TitleStorageUploadBlob(
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace UWPIntegration
|
|||
string resultText = string.Format("Allowed: {0}", result.IsAllowed);
|
||||
if (!result.IsAllowed)
|
||||
{
|
||||
foreach (var reason in result.Reasons)
|
||||
foreach (var reason in result.DenyReasons)
|
||||
{
|
||||
resultText += string.Format("\tReason: {0}", reason.Reason);
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ namespace UWPIntegration
|
|||
resultText += string.Format("\tPermission {0} allowed: {1}", permissionResult.PermissionRequested, permissionResult.IsAllowed);
|
||||
if (!permissionResult.IsAllowed)
|
||||
{
|
||||
foreach (var reason in permissionResult.Reasons)
|
||||
foreach (var reason in permissionResult.DenyReasons)
|
||||
{
|
||||
resultText += string.Format("\tReason: {0}", reason.Reason);
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ namespace UWPIntegration
|
|||
private async void TitleStorageGetQuota_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var quota = await this.User.Services.TitleStorageService.GetQuotaAsync(
|
||||
XboxLive.Instance.AppConfig.PrimaryServiceConfigId, TitleStorageType.Universal);
|
||||
XboxLive.Instance.AppConfig.ServiceConfigurationId, TitleStorageType.Universal);
|
||||
|
||||
this.TitleStorageData.Text = string.Format("Used bytes = {0}, Quota bytes = {1}", quota.UsedBytes, quota.QuotaBytes);
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ namespace UWPIntegration
|
|||
try
|
||||
{
|
||||
var metadataResult = await this.User.Services.TitleStorageService.GetBlobMetadataAsync(
|
||||
XboxLive.Instance.AppConfig.PrimaryServiceConfigId, TitleStorageType.Universal, "path/to/", this.User.XboxUserId);
|
||||
XboxLive.Instance.AppConfig.ServiceConfigurationId, TitleStorageType.Universal, "path/to/", this.User.XboxUserId);
|
||||
|
||||
var items = metadataResult.Items;
|
||||
if (items.Count > 0)
|
||||
|
@ -362,7 +362,7 @@ namespace UWPIntegration
|
|||
{
|
||||
try
|
||||
{
|
||||
var metadata = new TitleStorageBlobMetadata(XboxLive.Instance.AppConfig.PrimaryServiceConfigId, TitleStorageType.Universal, "path/to/newfile.txt", TitleStorageBlobType.Binary, this.user.XboxUserId);
|
||||
var metadata = new TitleStorageBlobMetadata(XboxLive.Instance.AppConfig.ServiceConfigurationId, TitleStorageType.Universal, "path/to/newfile.txt", TitleStorageBlobType.Binary, this.user.XboxUserId);
|
||||
|
||||
var bytes = System.Text.Encoding.Unicode.GetBytes("Hello, world!");
|
||||
|
||||
|
@ -403,7 +403,7 @@ namespace UWPIntegration
|
|||
{
|
||||
try
|
||||
{
|
||||
var metadata = new TitleStorageBlobMetadata(XboxLive.Instance.AppConfig.PrimaryServiceConfigId, TitleStorageType.Universal, "path/to/newfile.txt", TitleStorageBlobType.Binary, this.user.XboxUserId);
|
||||
var metadata = new TitleStorageBlobMetadata(XboxLive.Instance.AppConfig.ServiceConfigurationId, TitleStorageType.Universal, "path/to/newfile.txt", TitleStorageBlobType.Binary, this.user.XboxUserId);
|
||||
await this.User.Services.TitleStorageService.DeleteBlobAsync(metadata, false);
|
||||
|
||||
this.TitleStorageData.Text = string.Format("Successfully deleted blob with path \"path/to/newfile.txt\"", metadata.Length);
|
||||
|
|
|
@ -99,6 +99,9 @@
|
|||
<ItemGroup>
|
||||
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
|
||||
<None Include="project.json" />
|
||||
<Content Include="Microsoft.Xbox.Services.140.UWP.C.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="XboxServices.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
|
|
|
@ -59,16 +59,15 @@ Global
|
|||
{28AFCA79-691F-4493-B639-D3CAD311189B}.Release|x86.Deploy.0 = Release|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|Any CPU.Build.0 = Debug|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x64.Build.0 = Debug|x64
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x86.Build.0 = Debug|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.Build.0 = Release|ARM
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x64.ActiveCfg = Release|x64
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x64.Build.0 = Release|x64
|
||||
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x86.ActiveCfg = Release|x86
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<Import Project="..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.targets" Condition="Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.targets')" />
|
||||
<Import Project="..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.targets" Condition="Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.targets')" />
|
||||
<Import Project="..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.targets" Condition="Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.targets')" />
|
||||
<Import Project="..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets" Condition="Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets')" />
|
||||
<Import Project="..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets" Condition="Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.08.20170829.001\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="..\..\External\libHttpClient\libHttpClient.props" />
|
||||
|
@ -184,7 +184,6 @@
|
|||
<ClInclude Include="..\..\Source\Services\Common\pch.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Common\pch_common.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Common\taskargs.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Common\xbox_live_app_config_impl.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Common\xbox_live_context_impl.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Leaderboard\leaderboard_helper.h" />
|
||||
<ClInclude Include="..\..\Source\Services\Privacy\privacy_multiple_permissions_check_result_impl.h" />
|
||||
|
@ -233,6 +232,6 @@
|
|||
<Error Condition="!Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.ARM.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x64.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.v141.x86.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.11.20171204.01\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.08.20170829.001\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\CSharpSource\external\packages\Microsoft.Xbox.Live.SDK.Cpp.UWP.2017.08.20170829.001\build\native\Microsoft.Xbox.Live.SDK.Cpp.UWP.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -75,9 +75,6 @@
|
|||
<ClInclude Include="..\..\Include\xsapi\xbox_live_app_config_c.h">
|
||||
<Filter>C++ Public Includes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Source\Services\Common\xbox_live_app_config_impl.h">
|
||||
<Filter>C++ Source\Services\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Source\Shared\utils.h">
|
||||
<Filter>C++ Source\Shared</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -85,7 +85,7 @@ StatsManagerRequestFlushToService(
|
|||
|
||||
XSAPI_DLLEXPORT XSAPI_STAT_EVENT** XBL_CALLING_CONV
|
||||
StatsManagerDoWork(
|
||||
_Inout_ uint32_t* statEventsCount
|
||||
_Out_ uint32_t* statEventsCount
|
||||
);
|
||||
|
||||
XSAPI_DLLEXPORT XSAPI_RESULT XBL_CALLING_CONV
|
||||
|
@ -115,9 +115,9 @@ StatsManagerSetStatisticStringData(
|
|||
XSAPI_DLLEXPORT XSAPI_RESULT XBL_CALLING_CONV
|
||||
StatsManagerGetStatNames(
|
||||
_In_ XSAPI_XBOX_LIVE_USER* user,
|
||||
_Inout_ PCSTR** statNameList,
|
||||
_Inout_ uint32_t* statNameListCount,
|
||||
_Inout_ PCSTR* errMessage
|
||||
_Out_ PCSTR** statNameList,
|
||||
_Out_ uint32_t* statNameListCount,
|
||||
_Out_ PCSTR* errMessage
|
||||
);
|
||||
|
||||
XSAPI_DLLEXPORT XSAPI_RESULT XBL_CALLING_CONV
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xbox {
|
||||
namespace services {
|
||||
class xbox_live_app_config;
|
||||
}
|
||||
}
|
||||
|
||||
struct XBOX_LIVE_APP_CONFIG_IMPL
|
||||
{
|
||||
public:
|
||||
XBOX_LIVE_APP_CONFIG_IMPL();
|
||||
|
||||
private:
|
||||
std::string m_scid;
|
||||
std::string m_environment;
|
||||
std::string m_sandbox;
|
||||
std::shared_ptr<xbox::services::xbox_live_app_config> m_cppConfig;
|
||||
};
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче