Tons of cleanup working preperation for preview release (#178)

This commit is contained in:
John L 2017-12-15 11:37:26 -08:00 коммит произвёл GitHub
Родитель d75ae9d4d4
Коммит a0570b8eef
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
106 изменённых файлов: 491 добавлений и 3975 удалений

Просмотреть файл

@ -56,7 +56,7 @@ public class XboxLiveConfigurationEditor : EditorWindow
if (this.configuration != null) 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); 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("Publisher", this.configuration.PublisherDisplayName);
PropertyLabel("App ID", this.configuration.AppId); PropertyLabel("App ID", this.configuration.AppId);
PropertyLabel("Product Family Name", this.configuration.ProductFamilyName); 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("Title ID", this.configuration.TitleId.ToString());
PropertyLabel("Sandbox", this.configuration.Sandbox); PropertyLabel("Sandbox", this.configuration.Sandbox);
} }

Просмотреть файл

@ -35,7 +35,7 @@ namespace Microsoft.Xbox.Services.ConnectedStorage
if (resultCallBack != null) if (resultCallBack != null)
{ {
#if ENABLE_WINMD_SUPPORT #if ENABLE_WINMD_SUPPORT
var configId = XboxLive.Instance.AppConfig.PrimaryServiceConfigId; var configId = XboxLive.Instance.AppConfig.ServiceConfigurationId;
var initTask = GameSaveProvider.GetForUserAsync(xboxLiveUser.WindowsSystemUser, configId).AsTask(); var initTask = GameSaveProvider.GetForUserAsync(xboxLiveUser.WindowsSystemUser, configId).AsTask();
if (initTask.Result.Status == GameSaveErrorStatus.Ok) if (initTask.Result.Status == GameSaveErrorStatus.Ok)
{ {

Просмотреть файл

@ -64,7 +64,7 @@ public class UserProfile : MonoBehaviour
public void Start() public void Start()
{ {
// Disable the sign-in button if there's no configuration available. // 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; this.ConfigAvailable = false;
@ -86,7 +86,7 @@ public class UserProfile : MonoBehaviour
{ {
XboxLiveUserManager.Instance.UserForSingleUserMode = Instantiate(this.XboxLiveUserPrefab); XboxLiveUserManager.Instance.UserForSingleUserMode = Instantiate(this.XboxLiveUserPrefab);
this.XboxLiveUser = XboxLiveUserManager.Instance.UserForSingleUserMode; 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(); this.SignIn();
} }

Просмотреть файл

@ -44,8 +44,6 @@ public class XboxLiveUserInfo : MonoBehaviour
} }
} }
} }
MockXboxLiveData.Load(Path.Combine(Application.dataPath, "MockData.json"));
} }
public void Initialize() public void Initialize()

1
CSharpSource/.gitignore поставляемый
Просмотреть файл

@ -49,6 +49,7 @@ External/**/lib/
External/**/bin/ External/**/bin/
External/**/Debug/ External/**/Debug/
External/**/Release/ External/**/Release/
Tests/**/*.dll
**/*.classpath **/*.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*{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*{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*{cbd81e44-f37f-47d6-b71b-a43a748ae09c}*SharedItemsImports = 4
api\Microsoft.Xbox.Services.Shared.projitems*{cfb2ca8f-6611-4dca-981c-4b7afcca19a8}*SharedItemsImports = 4
EndGlobalSection EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM 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|ARM.ActiveCfg = Release|ARM
{4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|x64.ActiveCfg = Release|x64 {4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|x64.ActiveCfg = Release|x64
{4C1806D5-7279-4DFC-8874-13D66D52A31B}.ReleaseNET35|x86.ActiveCfg = Release|x86 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

Просмотреть файл

@ -29,7 +29,6 @@ namespace Microsoft.Xbox.Services.System
public string AgeGroup { get; set; } public string AgeGroup { get; set; }
public string Privileges { get; set; } public string Privileges { get; set; }
public string WebAccountId { get; set; } public string WebAccountId { get; set; }
public AuthConfig AuthConfig { get; set; }
public IntPtr XboxLiveUserPtr { get; } public IntPtr XboxLiveUserPtr { get; }
public Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh) public Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh)
@ -37,10 +36,10 @@ namespace Microsoft.Xbox.Services.System
return Task.FromResult(new SignInResult(SignInStatus.Success)); 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(';'); string[] authHeaderParts = authHeader.Substring(9).Split(';');
return Task.FromResult(new TokenAndSignatureResult return Task.FromResult(new GetTokenAndSignatureResult
{ {
Gamertag = this.Gamertag, Gamertag = this.Gamertag,
XboxUserId = this.XboxUserId, XboxUserId = this.XboxUserId,

Просмотреть файл

@ -3,17 +3,11 @@
// //
namespace Microsoft.Xbox.Services namespace Microsoft.Xbox.Services
{ {
public partial class XboxLive public partial class XboxLive
{ {
public static bool UseMockServices public static bool UseMockServices
{ {
get { return false; } get { return false; }
} }
public static bool UseMockHttp
{
get { return true; }
}
} }
} }

Просмотреть файл

@ -5,11 +5,11 @@ namespace Microsoft.Xbox.Services
{ {
public partial class XboxLiveAppConfiguration public partial class XboxLiveAppConfiguration
{ {
public static XboxLiveAppConfiguration Load(string path) private static XboxLiveAppConfiguration Load()
{ {
return new XboxLiveAppConfiguration return new XboxLiveAppConfiguration
{ {
PrimaryServiceConfigId = "00000000-0000-0000-0000-0000694f5acb", ServiceConfigurationId = "00000000-0000-0000-0000-0000694f5acb",
TitleId = 1766808267, TitleId = 1766808267,
Environment = string.Empty, Environment = string.Empty,
Sandbox = "JDTDWX.0", Sandbox = "JDTDWX.0",

Просмотреть файл

@ -9,10 +9,5 @@ namespace Microsoft.Xbox.Services
{ {
get { return false; } get { return false; }
} }
public static bool UseMockHttp
{
get { return false; }
}
} }
} }

Просмотреть файл

@ -4,28 +4,43 @@
namespace Microsoft.Xbox.Services 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 partial class XboxLiveAppConfiguration
{ {
public static XboxLiveAppConfiguration Load(string path) private static XboxLiveAppConfiguration Load()
{ {
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current; IntPtr appConfigPtr;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation; var result = GetXboxLiveAppConfigSingleton(out appConfigPtr);
if (result != XSAPI_RESULT.XSAPI_RESULT_OK)
string fullPath = Path.Combine(installedLocation.Path, path);
if (!File.Exists(fullPath))
{ {
throw new FileNotFoundException(string.Format("Unable to find Xbox Live app configuration file '{0}'.", path)); throw new XboxException(result);
} }
string content = File.ReadAllText(fullPath); var appConfigStruct = Marshal.PtrToStructure<XSAPI_XBOX_LIVE_APP_CONFIG>(appConfigPtr);
if (string.IsNullOrWhiteSpace(content))
{
throw new XboxException(string.Format("Xbox Live app configeration file '{0}' was empty.", path));
}
return JsonSerialization.FromJson<XboxLiveAppConfiguration>(content); return new XboxLiveAppConfiguration
{
TitleId = appConfigStruct.titleId,
Environment = MarshalingHelpers.Utf8ToString(appConfigStruct.environment),
Sandbox = MarshalingHelpers.Utf8ToString(appConfigStruct.sandbox),
ServiceConfigurationId = MarshalingHelpers.Utf8ToString(appConfigStruct.scid)
};
} }
[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 namespace Microsoft.Xbox.Services
{ {
using global::System.Threading.Tasks;
using Microsoft.Xbox.Services.System; using Microsoft.Xbox.Services.System;
public partial class XboxLiveUser public partial class XboxLiveUser
@ -14,41 +13,51 @@ namespace Microsoft.Xbox.Services
public XboxLiveUser(Windows.System.User systemUser) 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 // The UserImpl monitors the underlying system for sign out events
// and notifies us that a user has been signed out. We can then // and notifies us that a user has been signed out. We can then
// pass that event on the application with a concrete reference. // pass that event on the application with a concrete reference.
user.SignInCompleted += (sender, args) => userImpl.SignInCompleted += (sender, args) =>
{ {
OnSignInCompleted(this); if (SignInCompleted != null)
{
SignInCompleted(null, new SignInCompletedEventArgs(this));
}
}; };
user.SignOutCompleted += (sender, args) => userImpl.SignOutCompleted += (sender, args) =>
{ {
OnSignOutCompleted(this); if (SignOutCompleted != null)
{
SignOutCompleted(null, new SignOutCompletedEventArgs(this));
}
}; };
this.userImpl = user;
} }
internal XboxLiveUser(global::System.IntPtr xboxLiveUserPtr) 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 // The UserImpl monitors the underlying system for sign out events
// and notifies us that a user has been signed out. We can then // and notifies us that a user has been signed out. We can then
// pass that event on the application with a concrete reference. // pass that event on the application with a concrete reference.
user.SignInCompleted += (sender, args) => userImpl.SignInCompleted += (sender, args) =>
{ {
OnSignInCompleted(this); if (SignInCompleted != null)
{
SignInCompleted(null, new SignInCompletedEventArgs(this));
}
}; };
user.SignOutCompleted += (sender, args) => userImpl.SignOutCompleted += (sender, args) =>
{ {
OnSignOutCompleted(this); if (SignOutCompleted != null)
{
SignOutCompleted(null, new SignOutCompletedEventArgs(this));
}
}; };
userImpl.UpdatePropertiesFromXboxLiveUserPtr();
this.userImpl = user;
user.UpdatePropertiesFromXboxLiveUserPtr();
} }
public Windows.System.User WindowsSystemUser public Windows.System.User WindowsSystemUser
@ -63,20 +72,5 @@ namespace Microsoft.Xbox.Services
{ {
get { return (this.userImpl as UserImpl); } 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\StatisticEvent.cs" />
<Compile Include="Statistics\Manager\StatisticManager.cs" /> <Compile Include="Statistics\Manager\StatisticManager.cs" />
<Compile Include="System\TitleCallableUI.cs" /> <Compile Include="System\TitleCallableUI.cs" />
<Compile Include="System\TokenRequestResult.cs" />
<Compile Include="System\UserImpl.cs" /> <Compile Include="System\UserImpl.cs" />
<Compile Include="Common\XboxLiveUser.cs" /> <Compile Include="Common\XboxLiveUser.cs" />
<Compile Include="Common\XboxLiveAppConfiguration.cs" /> <Compile Include="Common\XboxLiveAppConfiguration.cs" />

Просмотреть файл

@ -6,7 +6,6 @@ namespace Microsoft.Xbox.Services.Social.Manager
using global::System; using global::System;
using global::System.Collections.Generic; using global::System.Collections.Generic;
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
using Microsoft.Xbox.Services.Presence;
using System; using System;
public partial class SocialManager : ISocialManager public partial class SocialManager : ISocialManager
@ -26,19 +25,14 @@ namespace Microsoft.Xbox.Services.Social.Manager
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // 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 // Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
m_localUsers.Add(user); m_localUsers.Add(user);
@ -48,19 +42,13 @@ namespace Microsoft.Xbox.Services.Social.Manager
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = SocialManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage); XSAPI_RESULT errCode = SocialManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
m_localUsers.Remove(user); m_localUsers.Remove(user);
@ -70,25 +58,18 @@ namespace Microsoft.Xbox.Services.Social.Manager
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cGroupPtr;
IntPtr cGroupPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromFilters(user.Impl.XboxLiveUserPtr, presenceFilter, relationshipFilter, cGroupPtr, cErrMessage); XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromFilters(user.Impl.XboxLiveUserPtr, presenceFilter, relationshipFilter, out cGroupPtr, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Handles returned objects // Handles returned objects
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(Marshal.ReadIntPtr(cGroupPtr)); XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(cGroupPtr);
Marshal.FreeHGlobal(cGroupPtr);
m_groups.Add(socialUserGroup); m_groups.Add(socialUserGroup);
return socialUserGroup; return socialUserGroup;
@ -100,41 +81,23 @@ namespace Microsoft.Xbox.Services.Social.Manager
if (xboxUserIdList == null) throw new ArgumentNullException("xboxUserIdList"); if (xboxUserIdList == null) throw new ArgumentNullException("xboxUserIdList");
// Allocates memory for parameters // Allocates memory for parameters
List<IntPtr> userIdPtrs = new List<IntPtr>(); IntPtr cUserIds = MarshalingHelpers.StringListToHGlobalUtf8StringArray(xboxUserIdList);
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);
// Allocates memory for returned objects // Allocates memory for returned objects
IntPtr cGroupPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cGroupPtr;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cErrMessage;
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromList(user.Impl.XboxLiveUserPtr, cUserIds, (uint)xboxUserIdList.Count, cGroupPtr, cErrMessage); XSAPI_RESULT errCode = SocialManagerCreateSocialUserGroupFromList(user.Impl.XboxLiveUserPtr, cUserIds, (uint)xboxUserIdList.Count, out cGroupPtr, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
MarshalingHelpers.FreeHGlobalUtf8StringArray(cUserIds, xboxUserIdList.Count);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) 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 // Handles returned objects
XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(Marshal.ReadIntPtr(cGroupPtr)); XboxSocialUserGroup socialUserGroup = new XboxSocialUserGroup(cGroupPtr);
Marshal.FreeHGlobal(cGroupPtr);
m_groups.Add(socialUserGroup); m_groups.Add(socialUserGroup);
return socialUserGroup; return socialUserGroup;
@ -146,37 +109,20 @@ namespace Microsoft.Xbox.Services.Social.Manager
if (users == null) throw new ArgumentNullException("users"); if (users == null) throw new ArgumentNullException("users");
// Allocates memory for parameters // Allocates memory for parameters
List<IntPtr> userIdPtrs = new List<IntPtr>(); IntPtr cUserIds = MarshalingHelpers.StringListToHGlobalUtf8StringArray(users);
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);
// Allocates memory for returned objects // Allocates memory for returned objects
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cErrMessage;
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = SocialManagerUpdateSocialUserGroup(socialGroup.GetPtr(), cUserIds, (uint)users.Count, cErrMessage); XSAPI_RESULT errCode = SocialManagerUpdateSocialUserGroup(socialGroup.GetPtr(), cUserIds, (uint)users.Count, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringUni(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
MarshalingHelpers.FreeHGlobalUtf8StringArray(cUserIds, users.Count);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) 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 // Does local work
socialGroup.Refresh(); socialGroup.Refresh();
} }
@ -184,39 +130,27 @@ namespace Microsoft.Xbox.Services.Social.Manager
public void DestroySocialUserGroup(XboxSocialUserGroup xboxSocialUserGroup) public void DestroySocialUserGroup(XboxSocialUserGroup xboxSocialUserGroup)
{ {
if (xboxSocialUserGroup == null) throw new ArgumentNullException("xboxSocialUserGroup"); 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 // Invokes the c method
XSAPI_RESULT errCode = SocialManagerDestroySocialUserGroup(xboxSocialUserGroup.GetPtr(), cErrMessage); XSAPI_RESULT errCode = SocialManagerDestroySocialUserGroup(xboxSocialUserGroup.GetPtr(), out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Does local work // Does local work
m_groups.Remove(xboxSocialUserGroup); m_groups.Remove(xboxSocialUserGroup);
} }
public IList<SocialEvent> DoWork() public IList<SocialEvent> DoWork()
{ {
UInt32 eventsCount;
// Allocates memory for returned objects
IntPtr cEventsCount = Marshal.AllocHGlobal(Marshal.SizeOf<Int32>());
// Invokes the c method // 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);
// Does local work
List<SocialEvent> events = new List<SocialEvent>(); List<SocialEvent> events = new List<SocialEvent>();
if (eventsCount > 0) if (eventsCount > 0)
@ -250,19 +184,13 @@ namespace Microsoft.Xbox.Services.Social.Manager
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = SocialManagerSetRichPresencePollingStatus(user.Impl.XboxLiveUserPtr, shouldEnablePolling, cErrMessage); XSAPI_RESULT errCode = SocialManagerSetRichPresencePollingStatus(user.Impl.XboxLiveUserPtr, shouldEnablePolling, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Does local work // Does local work
@ -271,28 +199,28 @@ namespace Microsoft.Xbox.Services.Social.Manager
// Marshaling // Marshaling
[DllImport(XboxLive.FlatCDllName)] [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)] [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)] [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)] [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)] [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)] [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)] [DllImport(XboxLive.FlatCDllName)]
private static extern IntPtr SocialManagerDoWork(IntPtr numOfEvents); private static extern IntPtr SocialManagerDoWork(out UInt32 numOfEvents);
[DllImport(XboxLive.FlatCDllName)] [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)] [StructLayout(LayoutKind.Sequential)]

Просмотреть файл

@ -12,7 +12,6 @@ namespace Microsoft.Xbox.Services.Social.Manager
TITLE_HISTORY cTitleHistory = Marshal.PtrToStructure<TITLE_HISTORY>(titleHistoryPtr); TITLE_HISTORY cTitleHistory = Marshal.PtrToStructure<TITLE_HISTORY>(titleHistoryPtr);
HasUserPlayed = cTitleHistory.UserHasPlayed; HasUserPlayed = cTitleHistory.UserHasPlayed;
// todo test
LastTimeUserPlayed = DateTimeOffset.FromUnixTimeSeconds(cTitleHistory.LastTimeUserPlayed); LastTimeUserPlayed = DateTimeOffset.FromUnixTimeSeconds(cTitleHistory.LastTimeUserPlayed);
} }

Просмотреть файл

@ -15,24 +15,18 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
private readonly List<XboxLiveUser> m_localUsers = new List<XboxLiveUser>(); private readonly List<XboxLiveUser> m_localUsers = new List<XboxLiveUser>();
[DllImport(XboxLive.FlatCDllName)] [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) public void AddLocalUser(XboxLiveUser user)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerAddLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage); XSAPI_RESULT errCode = StatsManagerAddLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Does local work // Does local work
@ -40,24 +34,18 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void RemoveLocalUser(XboxLiveUser user)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, cErrMessage); XSAPI_RESULT errCode = StatsManagerRemoveLocalUser(user.Impl.XboxLiveUserPtr, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Does local work // Does local work
@ -65,40 +53,29 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void RequestFlushToService(XboxLiveUser user, bool isHighPriority = false)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerRequestFlushToService(user.Impl.XboxLiveUserPtr, isHighPriority, cErrMessage); XSAPI_RESULT errCode = StatsManagerRequestFlushToService(user.Impl.XboxLiveUserPtr, isHighPriority, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [DllImport(XboxLive.FlatCDllName)]
private static extern IntPtr StatsManagerDoWork(IntPtr numOfEvents); private static extern IntPtr StatsManagerDoWork(out Int32 numOfEvents);
public IList<StatisticEvent> DoWork() public IList<StatisticEvent> DoWork()
{ {
// Allocates memory for returned objects
IntPtr cEventsCount = Marshal.AllocHGlobal(Marshal.SizeOf<Int32>());
Int32 eventsCount;
// Invokes the c method // Invokes the c method
IntPtr eventsPtr = StatsManagerDoWork(cEventsCount); IntPtr eventsPtr = StatsManagerDoWork(out eventsCount);
// Does local work
uint eventsCount = (uint)Marshal.ReadInt32(cEventsCount);
Marshal.FreeHGlobal(cEventsCount);
List<StatisticEvent> events = new List<StatisticEvent>(); List<StatisticEvent> events = new List<StatisticEvent>();
@ -123,176 +100,134 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void SetStatisticNumberData(XboxLiveUser user, string statName, double value)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerSetStatisticNumberData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage); XSAPI_RESULT errCode = StatsManagerSetStatisticNumberData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void SetStatisticIntegerData(XboxLiveUser user, string statName, long value)
{ {
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerSetStatisticIntegerData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage); XSAPI_RESULT errCode = StatsManagerSetStatisticIntegerData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void SetStatisticStringData(XboxLiveUser user, string statName, string value)
{ {
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerSetStatisticStringData(user.Impl.XboxLiveUserPtr, statName, value, cErrMessage); XSAPI_RESULT errCode = StatsManagerSetStatisticStringData(user.Impl.XboxLiveUserPtr, statName, value, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void DeleteStatistic(XboxLiveUser user, string statName)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerDeleteStat(user.Impl.XboxLiveUserPtr, statName, cErrMessage); XSAPI_RESULT errCode = StatsManagerDeleteStat(user.Impl.XboxLiveUserPtr, statName, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void GetLeaderboard(XboxLiveUser user, string statName, LeaderboardQuery query)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerGetLeaderboard(user.Impl.XboxLiveUserPtr, statName, query.GetPtr(), cErrMessage); XSAPI_RESULT errCode = StatsManagerGetLeaderboard(user.Impl.XboxLiveUserPtr, statName, query.GetPtr(), out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode > 0) if (errCode > 0)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public void GetSocialLeaderboard(XboxLiveUser user, string statName, string socialGroup, LeaderboardQuery query)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerGetSocialLeaderboard(user.Impl.XboxLiveUserPtr, statName, socialGroup, query.GetPtr(), cErrMessage); XSAPI_RESULT errCode = StatsManagerGetSocialLeaderboard(user.Impl.XboxLiveUserPtr, statName, socialGroup, query.GetPtr(), out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
} }
[DllImport(XboxLive.FlatCDllName)] [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) public StatisticValue GetStatistic(XboxLiveUser user, string statName)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects // Allocates memory for returned objects
IntPtr cStatValue = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cStatValue;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cErrMessage;
IntPtr cStatName = Marshal.StringToHGlobalAnsi(statName); IntPtr cStatName = MarshalingHelpers.StringToHGlobalUtf8(statName);
// Invokes the c method // Invokes the c method
XSAPI_RESULT errCode = StatsManagerGetStat(user.Impl.XboxLiveUserPtr, cStatName, cStatValue, cErrMessage); XSAPI_RESULT errCode = StatsManagerGetStat(user.Impl.XboxLiveUserPtr, cStatName, out cStatValue, out cErrMessage);
// Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
Marshal.FreeHGlobal(cErrMessage);
Marshal.FreeHGlobal(cStatName);
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
// Handles returned objects // Handles returned objects
StatisticValue statValue = new StatisticValue(Marshal.ReadIntPtr(cStatValue)); StatisticValue statValue = new StatisticValue(cStatValue);
Marshal.FreeHGlobal(cStatValue);
return statValue; return statValue;
} }
[DllImport(XboxLive.FlatCDllName)] [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) public IList<string> GetStatisticNames(XboxLiveUser user)
{ {
if (user == null) throw new ArgumentNullException("user"); if (user == null) throw new ArgumentNullException("user");
// Allocates memory for returned objects IntPtr cStatListPtr;
IntPtr cStatListPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); UInt32 statListCount;
IntPtr cStatListCount = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); IntPtr cErrMessage;
IntPtr cErrMessage = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
// Invokes the c method // 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 // Handles error
string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage)); string errMessage = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(cErrMessage));
@ -300,29 +235,9 @@ namespace Microsoft.Xbox.Services.Statistics.Manager
if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK) if (errCode != XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
// todo do something throw new XboxException(errCode, cErrMessage);
} }
return MarshalingHelpers.Utf8StringArrayToStringList(cStatListPtr, statListCount);
// 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;
} }
} }
} }

Просмотреть файл

@ -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 AgeGroup { get; private set; }
public string Privileges { get; private set; } public string Privileges { get; private set; }
public string WebAccountId { 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 User CreationContext { get; private set; }
public IntPtr XboxLiveUserPtr { get; private set; } public IntPtr XboxLiveUserPtr { get; private set; }
@ -48,7 +47,6 @@ namespace Microsoft.Xbox.Services.System
{ {
throw new XboxException(result); throw new XboxException(result);
} }
Init(); Init();
} }
@ -62,16 +60,7 @@ namespace Microsoft.Xbox.Services.System
{ {
signOutHandlerContext = AddSignOutCompletedHandler(OnSignOutCompleted); signOutHandlerContext = AddSignOutCompletedHandler(OnSignOutCompleted);
xboxLiveUserInstanceMap[XboxLiveUserPtr] = this; xboxLiveUserInstanceMap[XboxLiveUserPtr] = this;
var appConfig = XboxLiveAppConfiguration.SingletonInstance;
// 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
};
} }
~UserImpl() ~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(() => Task.Run(() =>
{ {
@ -196,7 +185,7 @@ namespace Microsoft.Xbox.Services.System
} }
int contextKey; 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 }; context.PointersToFree = new List<IntPtr> { pHttpMethod, pUrl, pHeaders, pBody };
var result = XboxLiveUserGetTokenAndSignature( var result = XboxLiveUserGetTokenAndSignature(
@ -223,12 +212,12 @@ namespace Microsoft.Xbox.Services.System
{ {
int contextKey = context.ToInt32(); int contextKey = context.ToInt32();
XsapiCallbackContext<UserImpl, TokenAndSignatureResult> contextObject; XsapiCallbackContext<UserImpl, GetTokenAndSignatureResult> contextObject;
if (XsapiCallbackContext<UserImpl, TokenAndSignatureResult>.TryRemove(contextKey, out contextObject)) if (XsapiCallbackContext<UserImpl, GetTokenAndSignatureResult>.TryRemove(contextKey, out contextObject))
{ {
if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK) if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
contextObject.TaskCompletionSource.SetResult(new TokenAndSignatureResult contextObject.TaskCompletionSource.SetResult(new GetTokenAndSignatureResult
{ {
WebAccountId = MarshalingHelpers.Utf8ToString(payload.WebAccountId), WebAccountId = MarshalingHelpers.Utf8ToString(payload.WebAccountId),
Privileges = MarshalingHelpers.Utf8ToString(payload.Privileges), Privileges = MarshalingHelpers.Utf8ToString(payload.Privileges),
@ -237,7 +226,6 @@ namespace Microsoft.Xbox.Services.System
XboxUserId = MarshalingHelpers.Utf8ToString(payload.XboxUserId), XboxUserId = MarshalingHelpers.Utf8ToString(payload.XboxUserId),
Signature = MarshalingHelpers.Utf8ToString(payload.Signature), Signature = MarshalingHelpers.Utf8ToString(payload.Signature),
Token = MarshalingHelpers.Utf8ToString(payload.Token) Token = MarshalingHelpers.Utf8ToString(payload.Token)
//TokenRequestResultStatus = tokenResult.ResponseStatus // TODO
}); });
} }
else else
@ -333,7 +321,7 @@ namespace Microsoft.Xbox.Services.System
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
private struct XSAPI_SIGN_IN_RESULT private struct XSAPI_SIGN_IN_RESULT
{ {
public SignInStatus status; public SignInStatus status;
} }

Просмотреть файл

@ -4,16 +4,10 @@
namespace Microsoft.Xbox.Services.UWP.UnitTests namespace Microsoft.Xbox.Services.UWP.UnitTests
{ {
using global::System; using global::System;
using Windows.System;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Microsoft.Xbox.Services.System;
using global::System.Linq; using global::System.Linq;
using Moq;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
using UITestMethod = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.UITestMethodAttribute; using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Windows.Security.Authentication.Web.Core; using Windows.System;
using global::System.Collections.Generic;
using global::System.Threading;
[TestClass] [TestClass]
public class UserTest public class UserTest
@ -30,28 +24,9 @@ namespace Microsoft.Xbox.Services.UWP.UnitTests
private const int mockErrorcode = 9999; private const int mockErrorcode = 9999;
private const string mockErrorMessage = "mock error message"; 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] [TestCleanup]
public void Cleanup() public void Cleanup()
{ {
XboxLiveUser.CleanupEventHandler();
} }
[TestCategory("XboxLiveUser")] [TestCategory("XboxLiveUser")]
@ -71,156 +46,5 @@ namespace Microsoft.Xbox.Services.UWP.UnitTests
var xbluser = new XboxLiveUser(systemUser); var xbluser = new XboxLiveUser(systemUser);
Assert.AreEqual(systemUser.NonRoamableId, xbluser.WindowsSystemUser.NonRoamableId); 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> </Otherwise>
</Choose> </Choose>
<ItemGroup> <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="Social\SocialManagerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Stats\StatsManagerTests.cs" /> <Compile Include="Stats\StatsManagerTests.cs" />
@ -73,22 +69,7 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Leaderboards\MockDataForLeaderboardTests.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TitleStorage\TitleStorageUT.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="packages.config" /> <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"> <None Include="XboxServices.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </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() public override void TestInitialize()
{ {
base.TestInitialize(); base.TestInitialize();
MockXboxLiveData.Load(Environment.CurrentDirectory + "\\Social\\SocialManagerUT.json");
} }
[TestMethod] [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; } get { return true; }
} }
public static bool UseMockHttp
{
get { return false; }
}
} }
} }

Просмотреть файл

@ -4,10 +4,30 @@
namespace Microsoft.Xbox.Services namespace Microsoft.Xbox.Services
{ {
using Newtonsoft.Json;
using global::System.IO; using global::System.IO;
public partial class XboxLiveAppConfiguration 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) public static XboxLiveAppConfiguration Load(string path)
{ {
if (!File.Exists(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)); 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 // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.Xbox.Services.Leaderboard namespace Microsoft.Xbox.Services.Leaderboard
{ {

Просмотреть файл

@ -1,12 +1,15 @@
 // Copyright (c) Microsoft Corporation
using System; // Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.Xbox.Services.Leaderboard namespace Microsoft.Xbox.Services.Leaderboard
{ {
using global::System;
class LeaderboardQueryUnityEditorImpl : ILeaderboardQueryImpl class LeaderboardQueryUnityEditorImpl : ILeaderboardQueryImpl
{ {
public IntPtr GetPtr() { return IntPtr.Zero; } public IntPtr GetPtr() { return IntPtr.Zero; }
uint m_maxItems; uint m_maxItems;
public uint GetMaxItems() public uint GetMaxItems()
{ {

Просмотреть файл

@ -16,11 +16,10 @@ namespace Microsoft.Xbox.Services.System
public string AgeGroup { get; set; } public string AgeGroup { get; set; }
public string Privileges { get; set; } public string Privileges { get; set; }
public string WebAccountId { get; set; } public string WebAccountId { get; set; }
public AuthConfig AuthConfig { get; set; }
private static int numberOfInstances; private static int numberOfInstances;
private static Random random = new Random(); private static Random random = new Random();
public Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh) public Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh)
{ {
if (XboxLive.UseMockServices) if (XboxLive.UseMockServices)
@ -36,11 +35,11 @@ namespace Microsoft.Xbox.Services.System
throw new NotImplementedException(); 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) if (XboxLive.UseMockServices)
{ {
return Task.FromResult(new TokenAndSignatureResult return Task.FromResult(new GetTokenAndSignatureResult
{ {
Gamertag = this.Gamertag, Gamertag = this.Gamertag,
XboxUserId = this.XboxUserId, XboxUserId = this.XboxUserId,

Просмотреть файл

@ -1,33 +1,17 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
using global::System;
public class HttpCallRequestMessage public class HttpCallRequestMessage
{ {
public HttpRequestMessageType GetHttpRequestMessageType { get; private set; }
public HttpRequestMessageType GetHttpRequestMessageType public Byte[] RequestMessageVector { get; private set; }
{
get;
private set;
}
public Byte[] RequestMessageVector
{
get;
private set;
}
public string RequestMessageString
{
get;
private set;
}
public string RequestMessageString { get; private set; }
} }
} }

Просмотреть файл

@ -3,8 +3,6 @@
// //
namespace Microsoft.Xbox.Services namespace Microsoft.Xbox.Services
{ {
using global::System;
public enum HttpCallResponseBodyType : uint public enum HttpCallResponseBodyType : uint
{ {
StringBody, 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; using global::System.Threading.Tasks;
public interface IXboxLiveUser internal interface IXboxLiveUser
{ {
string WebAccountId { get; } string WebAccountId { get; }
@ -29,10 +29,10 @@ namespace Microsoft.Xbox.Services
Task<SignInResult> SignInSilentlyAsync(); 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 class SignInCompletedEventArgs : EventArgs
{ {
public SignInCompletedEventArgs(IXboxLiveUser user) public SignInCompletedEventArgs(XboxLiveUser user)
{ {
this.User = 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 class SignOutCompletedEventArgs : EventArgs
{ {
public SignOutCompletedEventArgs(IXboxLiveUser user) public SignOutCompletedEventArgs(XboxLiveUser user)
{ {
this.User = user; this.User = user;
} }
// TODO change this to XboxLiveUser instead of IXboxLive user to match WinRT projections public XboxLiveUser User { get; private set; }
public IXboxLiveUser User { get; private set; }
} }
} }

Просмотреть файл

@ -8,7 +8,7 @@ using Windows.Security.Authentication.Web.Core;
namespace Microsoft.Xbox.Services namespace Microsoft.Xbox.Services
{ {
public class TokenAndSignatureResult public class GetTokenAndSignatureResult
{ {
public string WebAccountId { get; set; } public string WebAccountId { get; set; }
@ -25,10 +25,5 @@ namespace Microsoft.Xbox.Services
public string Signature { get; set; } public string Signature { get; set; }
public string Token { 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) 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))) : 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;
using global::System.IO; using global::System.IO;
using global::System.ComponentModel;
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
using Microsoft.Xbox.Services.Presence;
using Microsoft.Xbox.Services.Social.Manager; using Microsoft.Xbox.Services.Social.Manager;
using Microsoft.Xbox.Services.Statistics.Manager; using Microsoft.Xbox.Services.Statistics.Manager;
using Microsoft.Xbox.Services.System; using Microsoft.Xbox.Services.System;
@ -16,7 +14,6 @@ namespace Microsoft.Xbox.Services
{ {
private bool disposed; private bool disposed;
private static XboxLive instance; private static XboxLive instance;
private XboxLiveSettings settings;
private IStatisticManager statsManager; private IStatisticManager statsManager;
private ISocialManager socialManager; private ISocialManager socialManager;
@ -32,24 +29,23 @@ namespace Microsoft.Xbox.Services
private XboxLive() private XboxLive()
{ {
this.settings = new XboxLiveSettings();
try try
{ {
this.appConfig = XboxLiveAppConfiguration.Instance; #if WINDOWS_UWP
var result = XBLGlobalInitialize();
if (result != XSAPI_RESULT.XSAPI_RESULT_OK)
{
throw new XboxException(result);
}
#endif
// TODO flat C APIs for settings
//this.Settings = null;
this.appConfig = XboxLiveAppConfiguration.SingletonInstance;
} }
catch (FileLoadException) catch (FileLoadException)
{ {
this.appConfig = null; this.appConfig = null;
} }
#if WINDOWS_UWP
var result = XBLGlobalInitialize();
if (result != XSAPI_RESULT.XSAPI_RESULT_OK)
{
throw new XboxException(result);
}
#endif
} }
~XboxLive() ~XboxLive()
@ -104,15 +100,14 @@ namespace Microsoft.Xbox.Services
} }
} }
public XboxLiveSettings Settings //public XboxLiveContextSettings Settings { get; private set; }
{
get { return Instance.settings; }
set { Instance.settings = value; }
}
public XboxLiveAppConfiguration AppConfig public XboxLiveAppConfiguration AppConfig
{ {
get { return Instance.appConfig; } get
{
return Instance.appConfig;
}
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
@ -134,7 +129,7 @@ namespace Microsoft.Xbox.Services
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
public static Int64 DefaultTaskGroupId internal static Int64 DefaultTaskGroupId
{ {
get 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 namespace Microsoft.Xbox.Services
{ {
using global::System; using global::System;
#if UNITY_EDITOR
using Newtonsoft.Json; using global::Newtonsoft.Json;
#endif
public partial class XboxLiveAppConfiguration public partial class XboxLiveAppConfiguration
{ {
@ -14,45 +15,10 @@ namespace Microsoft.Xbox.Services
private static readonly object instanceLock = new object(); private static readonly object instanceLock = new object();
private static XboxLiveAppConfiguration instance; private static XboxLiveAppConfiguration instance;
public static XboxLiveAppConfiguration Instance #if UNITY_EDITOR
{ [JsonProperty("PrimaryServiceConfigId")]
get #endif
{ public string ServiceConfigurationId { get; set; }
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; }
public uint TitleId { get; set; } public uint TitleId { get; set; }
@ -60,30 +26,34 @@ namespace Microsoft.Xbox.Services
public string Environment { get; set; } public string Environment { get; set; }
public bool XboxLiveCreatorsTitle { get; set; } public static XboxLiveAppConfiguration SingletonInstance
public string GetEndpointForService(string serviceName, string protocol = "https")
{ {
return string.Format("{0}://{1}{2}.xboxlive.com", protocol, serviceName, string.IsNullOrEmpty(this.Environment) ? string.Empty : ("." + this.Environment)); get
}
public static XboxLiveAppConfiguration Load()
{
try
{ {
// Attempt to load it from a file if (instance == null)
return Load(FileName);
}
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)
{ {
return new XboxLiveAppConfiguration(); lock (instanceLock)
{
try
{
if (instance == null)
{
instance = XboxLiveAppConfiguration.Load();
}
}
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)
{
return new XboxLiveAppConfiguration();
}
throw new XboxException(string.Format("Unable to find or load Xbox Live configuration. Make sure a properly configured Xboxservices.config exists."), e);
}
}
} }
return instance;
throw new XboxException(string.Format("Unable to find or load Xbox Live configuration. Make sure a properly configured {0} exists.", FileName), e);
} }
} }
} }

Просмотреть файл

@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
@ -12,5 +8,4 @@ namespace Microsoft.Xbox.Services
{ {
ThisCodeNeedsToBeChangedToFollowBestPractices = 0, ThisCodeNeedsToBeChangedToFollowBestPractices = 0,
} }
}
}

Просмотреть файл

@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
@ -12,5 +8,4 @@ namespace Microsoft.Xbox.Services
{ {
ThisCodeNeedsToBeChangedToAvoidThrottling = 0, 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 // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
using global::System;
public class XboxLiveLogCallEventArgs : EventArgs public class XboxLiveLogCallEventArgs : EventArgs
{ {
public string Message { get; private set; }
public string Message public string Category { get; private set; }
{
get;
private set;
}
public string Category
{
get;
private set;
}
public XboxServicesDiagnosticsTraceLevel Level
{
get;
private set;
}
public XboxServicesDiagnosticsTraceLevel Level { get; private set; }
} }
} }

Просмотреть файл

@ -16,11 +16,7 @@ namespace Microsoft.Xbox.Services
public XboxLiveServices(XboxLiveUser user) public XboxLiveServices(XboxLiveUser user)
{ {
#if UNITY_EDITOR #if WINDOWS_UWP
// TODO Implement mock title storage service for unity editor
this.TitleStorageService = null;
this.PrivacyService = null;
#else
IntPtr xboxLiveContext; IntPtr xboxLiveContext;
var xsapiResult = XboxLiveContextCreate(user.PCXboxLiveUser, out xboxLiveContext); var xsapiResult = XboxLiveContextCreate(user.PCXboxLiveUser, out xboxLiveContext);
@ -32,6 +28,10 @@ namespace Microsoft.Xbox.Services
this.TitleStorageService = new TitleStorageService(XboxLiveContextPtr); this.TitleStorageService = new TitleStorageService(XboxLiveContextPtr);
this.PrivacyService = new PrivacyService(XboxLiveContextPtr); this.PrivacyService = new PrivacyService(XboxLiveContextPtr);
#else
// TODO MockServices and/or MockHttp
this.TitleStorageService = null;
this.PrivacyService = null;
#endif #endif
} }

Просмотреть файл

@ -5,22 +5,16 @@ namespace Microsoft.Xbox.Services
{ {
using global::System; using global::System;
public class XboxLiveSettings public class XboxLiveContextSettings
{ {
private const int DefaultHttpTimeoutWindowInSeconds = 20; public XboxLiveContextSettings()
private const int DefaultLongHttpTimeoutInSeconds = 5 * 60;
private const int DefaultRetryDelayInSeconds = 2;
public XboxLiveSettings()
{ {
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 bool UseCoreDispatcherForEventRouting { get; set; }
public TimeSpan HttpTimeout { get; set; }
public TimeSpan HttpTimeoutWindow { get; set; } public TimeSpan HttpTimeoutWindow { get; set; }
public TimeSpan HttpRetryDelay { 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) public void DisableAssertsForMaximumNumberOfWebsocketsActivated(XboxLiveContextRecommendedSetting setting)
//{ {
// throw new NotImplementedException(); throw new NotImplementedException();
//} }
} }
} }

Просмотреть файл

@ -4,10 +4,8 @@
namespace Microsoft.Xbox.Services namespace Microsoft.Xbox.Services
{ {
using global::System; using global::System;
using global::System.Collections.Generic;
using global::System.Text; using global::System.Text;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
using Microsoft.Xbox.Services.System; using Microsoft.Xbox.Services.System;
public partial class XboxLiveUser : IXboxLiveUser public partial class XboxLiveUser : IXboxLiveUser
@ -17,38 +15,9 @@ namespace Microsoft.Xbox.Services
private readonly IUserImpl userImpl; private readonly IUserImpl userImpl;
private XboxLiveServices xboxLiveServices; private XboxLiveServices xboxLiveServices;
private static event EventHandler<SignInCompletedEventArgs> InternalSignInCompleted; public static event EventHandler<SignInCompletedEventArgs> SignInCompleted;
private static List<EventHandler<SignInCompletedEventArgs>> signInDelegates = new List<EventHandler<SignInCompletedEventArgs>>(); public static event EventHandler<SignOutCompletedEventArgs> SignOutCompleted;
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 string WebAccountId public string WebAccountId
{ {
get get
@ -136,36 +105,19 @@ namespace Microsoft.Xbox.Services
return this.userImpl.SignInImpl(false, false); 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); 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)); 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); 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 // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
using global::System;
public class XboxServiceCallRoutedEventArgs : EventArgs public class XboxServiceCallRoutedEventArgs : EventArgs
{ {
public string XboxUserId public string XboxUserId { get; private set; }
{
get;
private set;
}
public TimeSpan ElapsedCallTime public TimeSpan ElapsedCallTime { get; private set; }
{
get;
private set;
}
public DateTimeOffset ResponseTimeUTC public DateTimeOffset ResponseTimeUTC { get; private set; }
{
get;
private set;
}
public DateTimeOffset RequestTimeUTC public DateTimeOffset RequestTimeUTC { get; private set; }
{
get;
private set;
}
public string FullResponseToString public string FullResponseToString { get; private set; }
{
get;
private set;
}
public uint HttpStatus public uint HttpStatus { get; private set; }
{
get;
private set;
}
public string Signature public string Signature { get; private set; }
{
get;
private set;
}
public string Token public string Token { get; private set; }
{
get;
private set;
}
public string ETag public string ETag { get; private set; }
{
get;
private set;
}
public string ResponseBody public string ResponseBody { get; private set;}
{
get;
private set;
}
public string ResponseHeaders public string ResponseHeaders { get; private set; }
{
get;
private set;
}
public uint ResponseCount public uint ResponseCount { get; private set; }
{
get;
private set;
}
public HttpCallRequestMessage RequestBody public HttpCallRequestMessage RequestBody { get; private set; }
{
get;
private set;
}
public string RequestHeaders public string RequestHeaders { get; private set; }
{
get;
private set;
}
public Uri Url public Uri Url { get; private set; }
{
get;
private set;
}
public string HttpMethod
{
get;
private set;
}
public string HttpMethod { get; private set; }
} }
} }

Просмотреть файл

@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services
{ {
@ -16,5 +12,4 @@ namespace Microsoft.Xbox.Services
Info = 3, Info = 3,
Verbose = 4, Verbose = 4,
} }
}
}

Просмотреть файл

@ -6,7 +6,7 @@ namespace Microsoft.Xbox.Services.Leaderboard
internal interface ILeaderboardQueryImpl internal interface ILeaderboardQueryImpl
{ {
IntPtr GetPtr(); IntPtr GetPtr();
uint GetSkipResultToRank(); uint GetSkipResultToRank();
void SetSkipResultToRank(uint skipResultToRank); void SetSkipResultToRank(uint skipResultToRank);

Просмотреть файл

@ -4,138 +4,17 @@
namespace Microsoft.Xbox.Services.Leaderboard namespace Microsoft.Xbox.Services.Leaderboard
{ {
using global::System; using global::System;
using global::System.Collections.Generic;
using global::System.Text;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
public class LeaderboardService : ILeaderboardService 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() internal LeaderboardService()
{ {
this.appConfig = XboxLive.Instance.AppConfig;
} }
/// <inheritdoc />
public Task<LeaderboardResult> GetLeaderboardAsync(XboxLiveUser user, LeaderboardQuery query) public Task<LeaderboardResult> GetLeaderboardAsync(XboxLiveUser user, LeaderboardQuery query)
{ {
string skipToXboxUserId = null; throw new NotImplementedException();
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("&");
} }
} }
} }

Просмотреть файл

@ -3,6 +3,7 @@
namespace Microsoft.Xbox.Services.Leaderboard namespace Microsoft.Xbox.Services.Leaderboard
{ {
using global::Newtonsoft.Json;
using global::System.Collections.Generic; using global::System.Collections.Generic;
using global::System.Linq; using global::System.Linq;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
@ -20,7 +21,7 @@ namespace Microsoft.Xbox.Services.Leaderboard
internal LeaderboardResult CreateLeaderboardResponse(LeaderboardQuery query) 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 }; 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 Values = row.Value != null ? new List<string> { row.Value } : row.Values
}).ToList(); }).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); LeaderboardResult result = new LeaderboardResult(rows, columns, lbResponse.LeaderboardInfo.TotalCount);
return result; return result;
} }

Просмотреть файл

@ -25,11 +25,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementTitleAssociation.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementTitleAssociation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementType.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Achievements\AchievementType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpCallRequestMessage.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\HttpRequestMessageType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpRetryAfterApiState.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\HttpCallResponseBodyType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\HttpRetryAfterManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\IXboxLiveUser.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\IXboxLiveUser.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\ServiceCallLoggingConfig.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\ServiceCallLoggingConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\SignInCompletedEventArgs.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\SignInCompletedEventArgs.cs" />
@ -39,12 +36,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Common\TokenAndSignatureResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\TokenAndSignatureResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxException.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLive.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxLive.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveAPIName.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveAppConfiguration.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveAppConfiguration.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveContextRecommendedSetting.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveContextRecommendedSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveContextThrottleSetting.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\XboxLiveLogCallEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveServices.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveServices.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveSettings.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Common\XboxLiveSettings.cs" />
@ -79,16 +73,19 @@
<Compile Include="$(MSBuildThisFileDirectory)GameServerPlatform\QualityOfServiceServer.cs" /> <Compile Include="$(MSBuildThisFileDirectory)GameServerPlatform\QualityOfServiceServer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardQueryImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardQueryImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardResultImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardResultImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\ILeaderboardService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQueryImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQueryImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResultImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResultImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardStatType.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardStatType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardResultImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardResultImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\MockLeaderboardService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Privacy\IPrivacyService.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Privacy\IPrivacyService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Privacy\Models\PrivacySettingsRequest.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\ISocialManagerPresenceRecord.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\IXboxSocialUserGroup.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Manager\IXboxSocialUserGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\SocialManagerPresenceRecord.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\IStatisticManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\LeaderboardResultEventArgs.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\LeaderboardResultEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\MockStatisticManager.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\MockStatisticManager.cs" />
@ -98,31 +95,24 @@
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticEventType.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticEventType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticManager.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticValue.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Statistics\Manager\StatisticValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AuthConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IUserImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\IUserImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MarshallingHelpers.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\MarshallingHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveCallbackContext.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveServicesSettings.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\XboxLiveResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\XsapiCallbackContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\XsapiResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\ITitleStorageService.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\SortOrder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQuery.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardQuery.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResponse.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResponse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardColumn.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardColumn.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardRow.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardRow.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Leaderboard\LeaderboardService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\CreateMatchTicketResponse.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Matchmaking\CreateMatchTicketResponse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\HopperStatisticsResponse.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Matchmaking\HopperStatisticsResponse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchmakingService.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchmakingService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchTicketDetailsResponse.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Matchmaking\MatchTicketDetailsResponse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\PreserveSessionMode.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Matchmaking\PreserveSessionMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Matchmaking\TicketStatus.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\FindMatchCompletedEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\HostChangedEventArgs.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\HostChangedEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\Joinability.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Multiplayer\Manager\Joinability.cs" />
@ -195,7 +185,6 @@
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionError.cs" /> <Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionError.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionErrorEventArgs.cs" /> <Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionErrorEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RealTimeActivity\RealTimeActivitySubscriptionState.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\ISocialManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\MockSocialManager.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Manager\MockSocialManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\PreferredColor.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Manager\PreferredColor.cs" />
@ -214,7 +203,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Social\Manager\XboxSocialUserGroup.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Manager\XboxSocialUserGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsRequest.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsRequest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsResponse.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\Models\ProfileSettingsResponse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\ProfileService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackItem.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackItem.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackType.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\ReputationFeedbackType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\ReputationService.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\ReputationService.cs" />
@ -228,13 +216,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Social\XboxSocialRelationshipResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\XboxSocialRelationshipResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Social\XboxUserProfile.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Social\XboxUserProfile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\GamingPrivilege.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\GamingPrivilege.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\JsonSerialization.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringService.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\StringService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\VerifyStringResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\VerifyStringResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\VerifyStringResultCode.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\TitleStorageBlobMetadata.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobMetadataResult.cs" /> <Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobMetadataResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TitleStorage\TitleStorageBlobResult.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,8 +12,8 @@ namespace Microsoft.Xbox.Services.Privacy
/// Get the list of Xbox Live Ids the calling user should avoid during multiplayer matchmaking. /// Get the list of Xbox Live Ids the calling user should avoid during multiplayer matchmaking.
/// </summary> /// </summary>
/// <returns>A collection of XboxUserIds that correspond to the calling user's avoid list.</returns> /// <returns>A collection of XboxUserIds that correspond to the calling user's avoid list.</returns>
Task<IList<string>> GetAvoidListAsync(); Task<IReadOnlyList<string>> GetAvoidListAsync();
/// <summary> /// <summary>
/// Check a single permission with a single target user. /// Check a single permission with a single target user.
/// </summary> /// </summary>
@ -33,15 +33,15 @@ namespace Microsoft.Xbox.Services.Privacy
/// See Microsoft::Xbox::Services::Privacy::PermissionIdConstants for the latest options.</param> /// 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> /// <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> /// <returns>A collection of <see cref="PermissionCheckResult"/> objects containing results of the target xbox user ids.</returns>
Task<List<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync( Task<IReadOnlyList<MultiplePermissionsCheckResult>> CheckMultiplePermissionsWithMultipleTargetUsersAsync(
IList<string> permissionIds, IReadOnlyList<string> permissionIds,
IList<string> targetXboxUserIds IReadOnlyList<string> targetXboxUserIds
); );
/// <summary> /// <summary>
/// Get the list of Xbox Live Ids that the calling user should not hear (mute) during multiplayer matchmaking. /// Get the list of Xbox Live Ids that the calling user should not hear (mute) during multiplayer matchmaking.
/// </summary> /// </summary>
/// <returns>The collection of Xbox user IDs that represent the mute list for a user.</returns> /// <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 class MultiplePermissionsCheckResult
{ {
public IList<PermissionCheckResult> Items { get; private set; } public IReadOnlyList<PermissionCheckResult> Items { get; private set; }
public string XboxUserId { get; private set; } public string XboxUserId { get; private set; }
@ -20,7 +20,7 @@ namespace Microsoft.Xbox.Services.Privacy
XboxUserId = MarshalingHelpers.Utf8ToString(multiplePermissionsStruct.xboxUserId); 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>(); int size = MarshalingHelpers.SizeOf<XSAPI_PRIVACY_PERMISSION_CHECK_RESULT>();
IntPtr permissionStructPtr = multiplePermissionsStruct.items; IntPtr permissionStructPtr = multiplePermissionsStruct.items;
@ -28,9 +28,10 @@ namespace Microsoft.Xbox.Services.Privacy
for (ulong i = 0; i < multiplePermissionsStruct.itemsCount; ++i) for (ulong i = 0; i < multiplePermissionsStruct.itemsCount; ++i)
{ {
var permissionCheckResultStruct = MarshalingHelpers.PtrToStructure<XSAPI_PRIVACY_PERMISSION_CHECK_RESULT>(permissionStructPtr); var permissionCheckResultStruct = MarshalingHelpers.PtrToStructure<XSAPI_PRIVACY_PERMISSION_CHECK_RESULT>(permissionStructPtr);
Items.Add(new PermissionCheckResult(permissionCheckResultStruct)); items.Add(new PermissionCheckResult(permissionCheckResultStruct));
permissionStructPtr = permissionStructPtr.Increment(size); permissionStructPtr = permissionStructPtr.Increment(size);
} }
Items = items;
} }
} }

Просмотреть файл

@ -11,7 +11,7 @@ namespace Microsoft.Xbox.Services.Privacy
public class PermissionCheckResult public class PermissionCheckResult
{ {
public IList<PermissionDenyReason> Reasons { get; private set; } public IReadOnlyList<PermissionDenyReason> DenyReasons { get; private set; }
public string PermissionRequested { get; private set; } public string PermissionRequested { get; private set; }
@ -27,17 +27,17 @@ namespace Microsoft.Xbox.Services.Privacy
IsAllowed = permissionCheckResultStruct.isAllowed; IsAllowed = permissionCheckResultStruct.isAllowed;
PermissionRequested = MarshalingHelpers.Utf8ToString(permissionCheckResultStruct.permissionRequested); 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>(); int size = MarshalingHelpers.SizeOf<XSAPI_PRIVACY_PERMISSION_DENY_REASON>();
IntPtr denyReasonPtr = permissionCheckResultStruct.denyReasons; IntPtr denyReasonPtr = permissionCheckResultStruct.denyReasons;
for (ulong i = 0; i < permissionCheckResultStruct.denyReasonsCount; ++i) for (ulong i = 0; i < permissionCheckResultStruct.denyReasonsCount; ++i)
{ {
Reasons.Add(new PermissionDenyReason(denyReasonPtr)); denyReasons.Add(new PermissionDenyReason(denyReasonPtr));
denyReasonPtr = denyReasonPtr.Increment(size); denyReasonPtr = denyReasonPtr.Increment(size);
} }
DenyReasons = denyReasons;
} }
} }

Просмотреть файл

@ -19,12 +19,12 @@ namespace Microsoft.Xbox.Services.Privacy
this.pCXboxLiveContext = pCXboxLiveContext; 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(() => 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); var xsapiResult = PrivacyGetAvoidList(this.pCXboxLiveContext, GetPrivacyUserListComplete, (IntPtr)contextKey, XboxLive.DefaultTaskGroupId);
if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK) if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK)
@ -35,12 +35,12 @@ namespace Microsoft.Xbox.Services.Privacy
return tcs.Task; 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(() => 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); var xsapiResult = PrivacyGetMuteList(this.pCXboxLiveContext, GetPrivacyUserListComplete, (IntPtr)contextKey, XboxLive.DefaultTaskGroupId);
if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK) if (xsapiResult != XSAPI_RESULT.XSAPI_RESULT_OK)
@ -58,7 +58,7 @@ namespace Microsoft.Xbox.Services.Privacy
{ {
if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK) if (result.errorCode == XSAPI_RESULT.XSAPI_RESULT_OK)
{ {
context.TaskCompletionSource.SetResult(MarshalingHelpers.Utf8StringArrayToStringList(xboxUserIdList, (int)count)); context.TaskCompletionSource.SetResult(MarshalingHelpers.Utf8StringArrayToStringList(xboxUserIdList, count));
} }
else 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(() => Task.Run(() =>
{ {
var permissionIdsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(permissionIds); var permissionIdsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(permissionIds);
var xuidsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(targetXboxUserIds); var xuidsArray = MarshalingHelpers.StringListToHGlobalUtf8StringArray(targetXboxUserIds);
int contextKey = XsapiCallbackContext<CheckMultiplePermissionsContext, List<MultiplePermissionsCheckResult>>.CreateContext( int contextKey = XsapiCallbackContext<CheckMultiplePermissionsContext, IReadOnlyList<MultiplePermissionsCheckResult>>.CreateContext(
new CheckMultiplePermissionsContext new CheckMultiplePermissionsContext
{ {
permissionIdsArray = permissionIdsArray, 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 new SocialManagerPresenceTitleRecord
{ {
TitleId = XboxLiveAppConfiguration.Instance.TitleId, TitleId = XboxLiveAppConfiguration.SingletonInstance.TitleId,
IsTitleActive = true, IsTitleActive = true,
} }
}; };

Просмотреть файл

@ -35,6 +35,5 @@ namespace Microsoft.Xbox.Services.Social.Manager
return m_instance; return m_instance;
} }
} }
} }
} }

Просмотреть файл

@ -9,101 +9,21 @@ namespace Microsoft.Xbox.Services.Social
public class ProfileService public class ProfileService
{ {
private readonly string profileEndpoint;
protected XboxLiveAppConfiguration config;
internal ProfileService() 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 NotImplementedException();
{
throw new ArgumentException("invalid xboxUserId", "xboxUserId");
}
List<string> profiles = new List<string> { xboxUserId };
return this.GetUserProfilesAsync(user, profiles).ContinueWith(task => task.Result[0]);
} }
public Task<List<XboxUserProfile>> GetUserProfilesAsync(XboxLiveUser user, List<string> xboxUserIds) public Task<IReadOnlyList<XboxUserProfile>> GetUserProfilesAsync(IReadOnlyList<string> xboxUserIds)
{ {
if (xboxUserIds == null) throw new NotImplementedException();
{
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(); 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 // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services.System
{ {
@ -33,5 +29,4 @@ namespace Microsoft.Xbox.Services.System
MultiplayerSessions = 254, MultiplayerSessions = 254,
AddFriend = 255, AddFriend = 255,
} }
} }

Просмотреть файл

@ -14,16 +14,14 @@ namespace Microsoft.Xbox.Services.System
string AgeGroup { get; } string AgeGroup { get; }
string Privileges { get; } string Privileges { get; }
string WebAccountId { get; } string WebAccountId { get; }
AuthConfig AuthConfig { get; }
#if WINDOWS_UWP #if WINDOWS_UWP
Windows.System.User CreationContext { get; } Windows.System.User CreationContext { get; }
#endif #endif
#if !UNITY_EDITOR #if !UNITY_EDITOR
IntPtr XboxLiveUserPtr { get; } IntPtr XboxLiveUserPtr { get; }
#endif #endif
Task<SignInResult> SignInImpl(bool showUI, bool forceRefresh); 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;
using global::System.Collections.Generic; using global::System.Collections.Generic;
using global::System.Linq;
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
using global::System.Text; 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="arrayPtr">Pointer to the C-style string array</param>
/// <param name="length">Number of strings in the array</param> /// <param name="length">Number of strings in the array</param>
/// <returns></returns> /// <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) for (int i = 0; i < length; ++i)
{ {
string str = MarshalingHelpers.Utf8ToString(Marshal.ReadIntPtr(arrayPtr)); string str = MarshalingHelpers.Utf8ToString(Marshal.ReadIntPtr(arrayPtr));
@ -69,9 +70,9 @@ namespace Microsoft.Xbox.Services
/// </summary> /// </summary>
/// <param name="strings">The array of string to allocate</param> /// <param name="strings">The array of string to allocate</param>
/// <returns>An IntPtr to the first Utf8String pointer</returns> /// <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; int offset = 0;
foreach (var str in strings) foreach (var str in strings)
{ {

Просмотреть файл

@ -1,16 +1,14 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services.System
{ {
using global::System;
using global::System.Threading.Tasks;
public class StringService public class StringService
{ {
public Task<VerifyStringResult> VerifyStringAsync(string stringToVerify) public Task<VerifyStringResult> VerifyStringAsync(string stringToVerify)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

Просмотреть файл

@ -1,16 +1,11 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services.System
{ {
public class VerifyStringResult public class VerifyStringResult
{ {
public string FirstOffendingSubstring public string FirstOffendingSubstring
{ {
get; get;

Просмотреть файл

@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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 namespace Microsoft.Xbox.Services.System
{ {
@ -15,5 +11,4 @@ namespace Microsoft.Xbox.Services.System
TooLong = 2, TooLong = 2,
UnknownError = 3, UnknownError = 3,
} }
} }

Просмотреть файл

@ -11,6 +11,6 @@ namespace Microsoft.Xbox.Services.System
public static XboxLiveServicesSettings SingletonInstance { get; private set; } 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.Collections.Generic;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
using Microsoft.Xbox.Services.TitleStorage; using Microsoft.Xbox.Services.TitleStorage;
/// <summary> /// <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="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> /// <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> /// <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> /// <summary>
/// [optional] Timestamp assigned by the client. /// [optional] Timestamp assigned by the client.
/// </summary> /// </summary>
public DateTimeOffset? ClientTimeStamp { get; private set; } public DateTimeOffset ClientTimeStamp { get; private set; }
/// <summary> /// <summary>
/// ETag for the file used in read and write requests. /// 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 displayName = MarshalingHelpers.StringToHGlobalUtf8(this.DisplayName);
var etag = MarshalingHelpers.StringToHGlobalUtf8(this.ETag); 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(scid);
Marshal.FreeHGlobal(path); Marshal.FreeHGlobal(path);
Marshal.FreeHGlobal(xuid); Marshal.FreeHGlobal(xuid);
Marshal.FreeHGlobal(displayName); Marshal.FreeHGlobal(displayName);
Marshal.FreeHGlobal(etag); Marshal.FreeHGlobal(etag);
Marshal.FreeHGlobal(clientTimePtr);
} }
internal void Refresh() internal void Refresh()

Просмотреть файл

@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
namespace Microsoft.Xbox.Services.TitleStorage namespace Microsoft.Xbox.Services.TitleStorage
{ {
using global::System; using global::System;

Просмотреть файл

@ -3,8 +3,8 @@
// //
namespace Microsoft.Xbox.Services.TitleStorage namespace Microsoft.Xbox.Services.TitleStorage
{ {
using global::System.Runtime.InteropServices;
using global::System; using global::System;
using global::System.Runtime.InteropServices;
/// <summary> /// <summary>
/// Blob data returned from the cloud. /// Blob data returned from the cloud.

Просмотреть файл

@ -28,6 +28,15 @@ namespace Microsoft.Xbox.Services.TitleStorage
/// </summary> /// </summary>
public TitleStorageType StorageType { get; private set; } 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> /// <summary>
/// Initialze a TitleStorageQuota from the corresponding C object /// Initialze a TitleStorageQuota from the corresponding C object
@ -37,6 +46,8 @@ namespace Microsoft.Xbox.Services.TitleStorage
QuotaBytes = quotaStruct.QuotaBytes; QuotaBytes = quotaStruct.QuotaBytes;
UsedBytes = quotaStruct.UsedBytes; UsedBytes = quotaStruct.UsedBytes;
StorageType = quotaStruct.storageType; 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;
using global::System.Collections.Generic; using global::System.Collections.Generic;
using global::System.Linq;
using global::System.Runtime.InteropServices; using global::System.Runtime.InteropServices;
using global::System.Threading.Tasks; using global::System.Threading.Tasks;
using Microsoft.Xbox.Services.Shared.TitleStorage; using Microsoft.Xbox.Services.Shared.TitleStorage;
@ -38,7 +39,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
var tcs = new TaskCompletionSource<TitleStorageQuota>(); var tcs = new TaskCompletionSource<TitleStorageQuota>();
Task.Run(() => Task.Run(() =>
{ {
var scid = MarshalingHelpers.StringToHGlobalUtf8(XboxLive.Instance.AppConfig.PrimaryServiceConfigId); var scid = MarshalingHelpers.StringToHGlobalUtf8(XboxLive.Instance.AppConfig.ServiceConfigurationId);
int contextKey; int contextKey;
var context = XsapiCallbackContext<object, TitleStorageQuota>.CreateContext(null, tcs, out 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="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> /// <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> /// <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>(); var tcs = new TaskCompletionSource<TitleStorageBlobMetadata>();
Task.Run(() => Task.Run(() =>
@ -255,7 +256,7 @@ namespace Microsoft.Xbox.Services.TitleStorage
var context = XsapiCallbackContext<TitleStorageBlobMetadata, TitleStorageBlobMetadata>.CreateContext(blobMetadata, tcs, out contextKey); var context = XsapiCallbackContext<TitleStorageBlobMetadata, TitleStorageBlobMetadata>.CreateContext(blobMetadata, tcs, out contextKey);
var buffer = Marshal.AllocHGlobal(blobBuffer.Count); 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 }; context.PointersToFree = new List<IntPtr> { buffer };
var xsapiResult = TitleStorageUploadBlob( var xsapiResult = TitleStorageUploadBlob(

Просмотреть файл

@ -219,7 +219,7 @@ namespace UWPIntegration
string resultText = string.Format("Allowed: {0}", result.IsAllowed); string resultText = string.Format("Allowed: {0}", result.IsAllowed);
if (!result.IsAllowed) if (!result.IsAllowed)
{ {
foreach (var reason in result.Reasons) foreach (var reason in result.DenyReasons)
{ {
resultText += string.Format("\tReason: {0}", reason.Reason); resultText += string.Format("\tReason: {0}", reason.Reason);
} }
@ -249,7 +249,7 @@ namespace UWPIntegration
resultText += string.Format("\tPermission {0} allowed: {1}", permissionResult.PermissionRequested, permissionResult.IsAllowed); resultText += string.Format("\tPermission {0} allowed: {1}", permissionResult.PermissionRequested, permissionResult.IsAllowed);
if (!permissionResult.IsAllowed) if (!permissionResult.IsAllowed)
{ {
foreach (var reason in permissionResult.Reasons) foreach (var reason in permissionResult.DenyReasons)
{ {
resultText += string.Format("\tReason: {0}", reason.Reason); resultText += string.Format("\tReason: {0}", reason.Reason);
} }
@ -333,7 +333,7 @@ namespace UWPIntegration
private async void TitleStorageGetQuota_Click(object sender, RoutedEventArgs e) private async void TitleStorageGetQuota_Click(object sender, RoutedEventArgs e)
{ {
var quota = await this.User.Services.TitleStorageService.GetQuotaAsync( 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); this.TitleStorageData.Text = string.Format("Used bytes = {0}, Quota bytes = {1}", quota.UsedBytes, quota.QuotaBytes);
} }
@ -343,7 +343,7 @@ namespace UWPIntegration
try try
{ {
var metadataResult = await this.User.Services.TitleStorageService.GetBlobMetadataAsync( 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; var items = metadataResult.Items;
if (items.Count > 0) if (items.Count > 0)
@ -362,7 +362,7 @@ namespace UWPIntegration
{ {
try 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!"); var bytes = System.Text.Encoding.Unicode.GetBytes("Hello, world!");
@ -403,7 +403,7 @@ namespace UWPIntegration
{ {
try 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); await this.User.Services.TitleStorageService.DeleteBlobAsync(metadata, false);
this.TitleStorageData.Text = string.Format("Successfully deleted blob with path \"path/to/newfile.txt\"", metadata.Length); this.TitleStorageData.Text = string.Format("Successfully deleted blob with path \"path/to/newfile.txt\"", metadata.Length);
@ -457,7 +457,7 @@ namespace UWPIntegration
} }
this.StatsData.Text = string.Join(Environment.NewLine, statNames.Select(n => this.StatsManager.GetStatistic(this.User, n)).Select(s => $"{s.Name} ({s.DataType}) = {GetStatValue(s)}")); this.StatsData.Text = string.Join(Environment.NewLine, statNames.Select(n => this.StatsManager.GetStatistic(this.User, n)).Select(s => $"{s.Name} ({s.DataType}) = {GetStatValue(s)}"));
} }
IList<SocialEvent> socialEvents = this.SocialManager.DoWork(); IList<SocialEvent> socialEvents = this.SocialManager.DoWork();
foreach (SocialEvent ev in socialEvents) foreach (SocialEvent ev in socialEvents)
{ {

Просмотреть файл

@ -99,6 +99,9 @@
<ItemGroup> <ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included --> <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" /> <None Include="project.json" />
<Content Include="Microsoft.Xbox.Services.140.UWP.C.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="XboxServices.config"> <Content Include="XboxServices.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Content> </Content>
@ -153,8 +156,8 @@
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<Target Name="CopyCdllToAppx" AfterTargets="Build"> <Target Name="CopyCdllToAppx" AfterTargets="Build">
<Message Importance="high" Text="Copying C dll to Appx folder from $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\ to $(TargetDir)AppX\" /> <Message Importance="high" Text="Copying C dll to Appx folder from $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\ to $(TargetDir)AppX\" />
<Exec Command="xcopy /y /d $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\*.dll $(TargetDir)AppX\" /> <Exec Command="xcopy /y /d $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\*.dll $(TargetDir)AppX\" />
<Exec Command="xcopy /y /d $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\*.pdb $(TargetDir)AppX\" /> <Exec Command="xcopy /y /d $(BuildRoot)\..\CppSource\binaries\$(Configuration)\$(CDllPlatform)\Microsoft.Xbox.Services.140.UWP.C\*.pdb $(TargetDir)AppX\" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

Просмотреть файл

@ -59,16 +59,15 @@ Global
{28AFCA79-691F-4493-B639-D3CAD311189B}.Release|x86.Deploy.0 = Release|x86 {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.ActiveCfg = Debug|x86
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|ARM
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|ARM.Build.0 = Debug|Any CPU {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.ActiveCfg = Debug|x64
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x64.Build.0 = 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.ActiveCfg = Debug|x86
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Debug|x86.Build.0 = 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.ActiveCfg = Release|x86
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|Any CPU.Build.0 = Release|Any CPU {CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.ActiveCfg = Release|ARM
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.ActiveCfg = Release|Any CPU {CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.Build.0 = Release|ARM
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|ARM.Build.0 = Release|Any CPU
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x64.ActiveCfg = Release|x64 {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|x64.Build.0 = Release|x64
{CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x86.ActiveCfg = Release|x86 {CFB2CA8F-6611-4DCA-981C-4B7AFCCA19A8}.Release|x86.ActiveCfg = Release|x86

Просмотреть файл

@ -2,4 +2,4 @@
"TitleId" : 1798668314, "TitleId" : 1798668314,
"PrimaryServiceConfigId" : "00000000-0000-0000-0000-00006b35801a", "PrimaryServiceConfigId" : "00000000-0000-0000-0000-00006b35801a",
"XboxLiveCreatorsTitle" : true "XboxLiveCreatorsTitle" : true
} }

Просмотреть файл

@ -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.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.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.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>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="..\..\External\libHttpClient\libHttpClient.props" /> <Import Project="..\..\External\libHttpClient\libHttpClient.props" />
@ -184,7 +184,6 @@
<ClInclude Include="..\..\Source\Services\Common\pch.h" /> <ClInclude Include="..\..\Source\Services\Common\pch.h" />
<ClInclude Include="..\..\Source\Services\Common\pch_common.h" /> <ClInclude Include="..\..\Source\Services\Common\pch_common.h" />
<ClInclude Include="..\..\Source\Services\Common\taskargs.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\Common\xbox_live_context_impl.h" />
<ClInclude Include="..\..\Source\Services\Leaderboard\leaderboard_helper.h" /> <ClInclude Include="..\..\Source\Services\Leaderboard\leaderboard_helper.h" />
<ClInclude Include="..\..\Source\Services\Privacy\privacy_multiple_permissions_check_result_impl.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.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.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.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> </Target>
</Project> </Project>

Просмотреть файл

@ -75,9 +75,6 @@
<ClInclude Include="..\..\Include\xsapi\xbox_live_app_config_c.h"> <ClInclude Include="..\..\Include\xsapi\xbox_live_app_config_c.h">
<Filter>C++ Public Includes</Filter> <Filter>C++ Public Includes</Filter>
</ClInclude> </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"> <ClInclude Include="..\..\Source\Shared\utils.h">
<Filter>C++ Source\Shared</Filter> <Filter>C++ Source\Shared</Filter>
</ClInclude> </ClInclude>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше