зеркало из https://github.com/microsoft/winsdkfb.git
Finish updating all sample apps to handle rerequest of permissions properly.
This commit is contained in:
Родитель
33b069ef95
Коммит
74e65c4616
|
@ -1,4 +1,5 @@
|
||||||
.nuget
|
.nuget
|
||||||
|
*.csproj.user
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
*.suo
|
*.suo
|
||||||
|
|
|
@ -318,6 +318,7 @@ popd
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaObject.h" />
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaObject.h" />
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaStream.h" />
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaStream.h" />
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPaginatedArray.h" />
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPaginatedArray.h" />
|
||||||
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPermissions.h" />
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePicture.h" />
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePicture.h" />
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml.h">
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml.h">
|
||||||
<DependentUpon>..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml</DependentUpon>
|
<DependentUpon>..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml</DependentUpon>
|
||||||
|
@ -353,6 +354,7 @@ popd
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaObject.cpp" />
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaObject.cpp" />
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaStream.cpp" />
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookMediaStream.cpp" />
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPaginatedArray.cpp" />
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPaginatedArray.cpp" />
|
||||||
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPermissions.cpp" />
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePicture.cpp" />
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePicture.cpp" />
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml.cpp">
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml.cpp">
|
||||||
<DependentUpon>..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml</DependentUpon>
|
<DependentUpon>..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml</DependentUpon>
|
||||||
|
|
|
@ -120,6 +120,9 @@
|
||||||
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\ScaleConverter.cpp">
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\ScaleConverter.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPermissions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookAccessTokenData.h">
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookAccessTokenData.h">
|
||||||
|
@ -205,6 +208,9 @@
|
||||||
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\ScaleConverter.h">
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\ScaleConverter.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookPermissions.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml" />
|
<Page Include="..\..\FBWinSDK\FBWinSDK.Shared\FacebookProfilePictureControl.xaml" />
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookMediaObject.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookMediaObject.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookMediaStream.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookMediaStream.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookPaginatedArray.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookPaginatedArray.h" />
|
||||||
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookPermissions.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookProfilePicture.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookProfilePicture.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookProfilePictureControl.xaml.h">
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookProfilePictureControl.xaml.h">
|
||||||
<DependentUpon>$(MSBuildThisFileDirectory)FacebookProfilePictureControl.xaml</DependentUpon>
|
<DependentUpon>$(MSBuildThisFileDirectory)FacebookProfilePictureControl.xaml</DependentUpon>
|
||||||
|
@ -61,6 +62,7 @@
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookMediaObject.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookMediaObject.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookMediaStream.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookMediaStream.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookPaginatedArray.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookPaginatedArray.cpp" />
|
||||||
|
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookPermissions.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBCursors.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBCursors.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBGroup.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBGroup.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBPage.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)Generated\FBPage.cpp" />
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)HlsColor.h">
|
<ClInclude Include="$(MSBuildThisFileDirectory)HlsColor.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookPermissions.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)pch.cpp">
|
<ClCompile Include="$(MSBuildThisFileDirectory)pch.cpp">
|
||||||
|
@ -154,6 +157,9 @@
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)HlsColor.cpp">
|
<ClCompile Include="$(MSBuildThisFileDirectory)HlsColor.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(MSBuildThisFileDirectory)FacebookPermissions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Header Files">
|
<Filter Include="Header Files">
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Facebook
|
||||||
*/
|
*/
|
||||||
public enum class ErrorSubcode : int
|
public enum class ErrorSubcode : int
|
||||||
{
|
{
|
||||||
|
ErrorSubcodeAppNotAuthorized = 458,
|
||||||
ErrorSubcodeSessionInvalidated = 466
|
ErrorSubcodeSessionInvalidated = 466
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "FacebookLoginButton.h"
|
#include "FacebookLoginButton.h"
|
||||||
#include "FacebookSession.h"
|
#include "FacebookSession.h"
|
||||||
|
#include "FacebookPermissions.h"
|
||||||
|
|
||||||
using namespace Concurrency;
|
using namespace Concurrency;
|
||||||
using namespace Facebook;
|
using namespace Facebook;
|
||||||
|
@ -32,7 +33,6 @@ FBLoginButton::FBLoginButton() :
|
||||||
{
|
{
|
||||||
String^ styleKey = FBLoginButton::typeid->FullName;
|
String^ styleKey = FBLoginButton::typeid->FullName;
|
||||||
this->DefaultStyleKey = styleKey;
|
this->DefaultStyleKey = styleKey;
|
||||||
m_permissions = ref new Vector<String^>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBLoginButton::OnApplyTemplate(
|
void FBLoginButton::OnApplyTemplate(
|
||||||
|
@ -58,61 +58,21 @@ void FBLoginButton::OnApplyTemplate(
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
|
|
||||||
IVector<String^>^ FBLoginButton::Permissions::get()
|
FBPermissions^ FBLoginButton::Permissions::get()
|
||||||
{
|
{
|
||||||
return m_permissions;
|
return m_permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBLoginButton::Permissions::set(IVector<String^>^ Values)
|
void FBLoginButton::Permissions::set(FBPermissions^ Permissions)
|
||||||
{
|
{
|
||||||
m_permissions->Clear();
|
m_permissions = Permissions;
|
||||||
IIterator<String^>^ it = nullptr;
|
|
||||||
for (it = Values->First(); it->HasCurrent; it->MoveNext())
|
|
||||||
{
|
|
||||||
String^ value = it->Current;
|
|
||||||
m_permissions->Append(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBLoginButton::InitWithPermissions(
|
void FBLoginButton::InitWithPermissions(
|
||||||
IVector<String^>^ permissions
|
FBPermissions^ Permissions
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!m_permissions)
|
m_permissions = Permissions;
|
||||||
{
|
|
||||||
m_permissions = ref new Vector<String^>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_permissions->Clear();
|
|
||||||
|
|
||||||
for (IIterator<String^>^ iter = permissions->First();
|
|
||||||
iter->HasCurrent;
|
|
||||||
iter->MoveNext())
|
|
||||||
{
|
|
||||||
m_permissions->Append(iter->Current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String^ FBLoginButton::GetPermissions(
|
|
||||||
)
|
|
||||||
{
|
|
||||||
String^ permissions = nullptr;
|
|
||||||
if (m_permissions)
|
|
||||||
{
|
|
||||||
permissions = ref new String();
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_permissions->Size; i++)
|
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
{
|
|
||||||
permissions += ",";
|
|
||||||
}
|
|
||||||
|
|
||||||
permissions += m_permissions->GetAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBLoginButton::OnClick(
|
void FBLoginButton::OnClick(
|
||||||
|
@ -128,14 +88,7 @@ void FBLoginButton::OnClick(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String^ permissions = GetPermissions();
|
create_task(s->LoginAsync(m_permissions))
|
||||||
PropertySet^ parameters = ref new PropertySet();
|
|
||||||
if (permissions != nullptr)
|
|
||||||
{
|
|
||||||
parameters->Insert(L"scope", permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
create_task(s->LoginAsync(parameters))
|
|
||||||
.then([=](FBResult^ result)
|
.then([=](FBResult^ result)
|
||||||
{
|
{
|
||||||
if (result->Succeeded)
|
if (result->Succeeded)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FacebookSession.h"
|
#include "FacebookSession.h"
|
||||||
|
#include "FacebookPermissions.h"
|
||||||
|
|
||||||
namespace Facebook
|
namespace Facebook
|
||||||
{
|
{
|
||||||
|
@ -58,16 +59,16 @@ namespace Facebook
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//! Publish permissions for user
|
//! Publish permissions for user
|
||||||
property Windows::Foundation::Collections::IVector<Platform::String^>^
|
property Facebook::FBPermissions^
|
||||||
Permissions
|
Permissions
|
||||||
{
|
{
|
||||||
Windows::Foundation::Collections::IVector<Platform::String^>^ get();
|
Facebook::FBPermissions^ get();
|
||||||
void set(Windows::Foundation::Collections::IVector<Platform::String^>^);
|
void set(Facebook::FBPermissions^);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Ask for read permissions at login
|
//! Ask for read permissions at login
|
||||||
void InitWithPermissions(
|
void InitWithPermissions(
|
||||||
Windows::Foundation::Collections::IVector<Platform::String^>^ permissions
|
Facebook::FBPermissions^ permissions
|
||||||
);
|
);
|
||||||
|
|
||||||
event FBLoginErrorHandler^ FBLoginError;
|
event FBLoginErrorHandler^ FBLoginError;
|
||||||
|
@ -85,6 +86,6 @@ namespace Facebook
|
||||||
);
|
);
|
||||||
|
|
||||||
// SessionLoginBehavior m_loginBehavior;
|
// SessionLoginBehavior m_loginBehavior;
|
||||||
Platform::Collections::Vector<Platform::String^>^ m_permissions;
|
Facebook::FBPermissions^ m_permissions;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <ppltasks.h>
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
#include "FacebookPermissions.h"
|
||||||
|
|
||||||
|
using namespace Facebook;
|
||||||
|
using namespace Platform;
|
||||||
|
using namespace Windows::Foundation::Collections;
|
||||||
|
|
||||||
|
IVectorView<String^>^ FBPermissions::Values::get()
|
||||||
|
{
|
||||||
|
return _values;
|
||||||
|
};
|
||||||
|
|
||||||
|
void FBPermissions::Values::set(
|
||||||
|
IVectorView<String^>^ value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_values = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform::String^ FBPermissions::ToString(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
String^ permissions = nullptr;
|
||||||
|
if (_values)
|
||||||
|
{
|
||||||
|
permissions = ref new String();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _values->Size; i++)
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
{
|
||||||
|
permissions += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions += _values->GetAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Facebook
|
||||||
|
{
|
||||||
|
public ref class FBPermissions sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
property Windows::Foundation::Collections::IVectorView<Platform::String^>^ Values
|
||||||
|
{
|
||||||
|
Windows::Foundation::Collections::IVectorView<Platform::String^>^ get();
|
||||||
|
void set(Windows::Foundation::Collections::IVectorView<Platform::String^>^ value);
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual Platform::String^ ToString(
|
||||||
|
) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Windows::Foundation::Collections::IVectorView<Platform::String^>^ _values;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -501,7 +501,7 @@ Windows::Foundation::IAsyncOperation<FBResult^>^ FBSession::ShowRequestsDialog(
|
||||||
// the concurrency event object was deprecated in the Win10 SDK tools.
|
// the concurrency event object was deprecated in the Win10 SDK tools.
|
||||||
// Switched to plane old Windows event, but that didn't work at all,
|
// Switched to plane old Windows event, but that didn't work at all,
|
||||||
// so polling for now.
|
// so polling for now.
|
||||||
while (m_showingDialog && !dialogResponse);
|
while (m_showingDialog && !dialogResponse)
|
||||||
{
|
{
|
||||||
dialogResponse = m_dialog->GetDialogResponse();
|
dialogResponse = m_dialog->GetDialogResponse();
|
||||||
Sleep(0);
|
Sleep(0);
|
||||||
|
@ -674,9 +674,6 @@ String^ FBSession::GetRedirectUriString(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Uri^ endURI = WebAuthenticationBroker::GetCurrentApplicationCallbackUri();
|
Uri^ endURI = WebAuthenticationBroker::GetCurrentApplicationCallbackUri();
|
||||||
String^ blerg = endURI->DisplayUri;
|
|
||||||
OutputDebugString(blerg->Data());
|
|
||||||
OutputDebugString(L"\n");
|
|
||||||
return endURI->DisplayUri;
|
return endURI->DisplayUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,22 +853,33 @@ task<FBResult^> FBSession::RunWebViewLoginOnUIThread(
|
||||||
}
|
}
|
||||||
|
|
||||||
IAsyncOperation<FBResult^>^ FBSession::LoginAsync(
|
IAsyncOperation<FBResult^>^ FBSession::LoginAsync(
|
||||||
PropertySet^ Parameters
|
FBPermissions^ Permissions
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_dialog = ref new FacebookDialog();
|
m_dialog = ref new FacebookDialog();
|
||||||
|
|
||||||
return create_async([=]()
|
return create_async([=]()
|
||||||
{
|
{
|
||||||
|
PropertySet^ parameters = ref new PropertySet();
|
||||||
|
if (Permissions)
|
||||||
|
{
|
||||||
|
parameters->Insert(L"scope", Permissions->ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LoggedIn)
|
||||||
|
{
|
||||||
|
parameters->Insert(L"auth_type", L"rerequest");
|
||||||
|
}
|
||||||
|
|
||||||
return create_task([=]() -> FBResult^
|
return create_task([=]() -> FBResult^
|
||||||
{
|
{
|
||||||
FBResult^ result = nullptr;
|
FBResult^ result = nullptr;
|
||||||
|
|
||||||
task<FBResult^> authTask = TryLoginViaWebView(Parameters);
|
task<FBResult^> authTask = TryLoginViaWebView(parameters);
|
||||||
result = authTask.get();
|
result = authTask.get();
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
authTask = TryLoginViaWebAuthBroker(Parameters);
|
authTask = TryLoginViaWebAuthBroker(parameters);
|
||||||
result = authTask.get();
|
result = authTask.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "FacebookResult.h"
|
#include "FacebookResult.h"
|
||||||
#include "FBUser.h"
|
#include "FBUser.h"
|
||||||
#include "FacebookDialog.xaml.h"
|
#include "FacebookDialog.xaml.h"
|
||||||
|
#include "FacebookPermissions.h"
|
||||||
|
|
||||||
namespace Facebook
|
namespace Facebook
|
||||||
{
|
{
|
||||||
|
@ -125,7 +126,7 @@ namespace Facebook
|
||||||
);
|
);
|
||||||
|
|
||||||
Windows::Foundation::IAsyncOperation<FBResult^>^ LoginAsync(
|
Windows::Foundation::IAsyncOperation<FBResult^>^ LoginAsync(
|
||||||
Windows::Foundation::Collections::PropertySet^ Parameters
|
Facebook::FBPermissions^ Permissions
|
||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -223,19 +223,5 @@
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<<<<<<< HEAD
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
<Import Project="..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.targets" Condition="Exists('..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.targets')" />
|
|
||||||
</ImportGroup>
|
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
|
||||||
<PropertyGroup>
|
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Error Condition="!Exists('..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.props'))" />
|
|
||||||
<Error Condition="!Exists('..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\FBWinSDK.0.9.0\build\native\FBWinSDK.targets'))" />
|
|
||||||
<Error Condition="!Exists('..\packages\FBWinSDK-debug.0.9.0\build\FBWinSDK-debug.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\FBWinSDK-debug.0.9.0\build\FBWinSDK-debug.props'))" />
|
|
||||||
</Target>
|
|
||||||
=======
|
|
||||||
<ImportGroup Label="ExtensionTargets" />
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
>>>>>>> 26_change_sample_sdk_references
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "MainPage.xaml.h"
|
#include "MainPage.xaml.h"
|
||||||
#include "UserInfo.xaml.h"
|
|
||||||
#include "OptionsPage.xaml.h"
|
#include "OptionsPage.xaml.h"
|
||||||
|
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
using namespace Facebook;
|
using namespace Facebook;
|
||||||
using namespace LoginCpp;
|
using namespace LoginCpp;
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
|
using namespace Platform::Collections;
|
||||||
using namespace Windows::ApplicationModel;
|
using namespace Windows::ApplicationModel;
|
||||||
using namespace Windows::ApplicationModel::Activation;
|
using namespace Windows::ApplicationModel::Activation;
|
||||||
using namespace Windows::ApplicationModel::Core;
|
using namespace Windows::ApplicationModel::Core;
|
||||||
|
@ -85,21 +85,19 @@ void MainPage::SetSessionAppIds()
|
||||||
s->WinAppId = winAppId;
|
s->WinAppId = winAppId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String^ MainPage::BuildPermissionsString(
|
FBPermissions^ MainPage::BuildPermissions(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
String^ result = ref new String();
|
FBPermissions^ result = ref new FBPermissions();
|
||||||
|
Vector<String^>^ v = ref new Vector<String^>();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
||||||
{
|
{
|
||||||
if (i)
|
v->Append(ref new String(requested_permissions[i]));
|
||||||
{
|
|
||||||
result += L",";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += ref new String(requested_permissions[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->Values = v->GetView();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,46 +132,95 @@ BOOL MainPage::DidGetAllRequestedPermissions(
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
FBResult^ result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (result &&
|
||||||
|
(!result->Succeeded) &&
|
||||||
|
(result->ErrorInfo->Code == (int)Facebook::ErrorCode::ErrorCodeOauthException));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MainPage::ShouldRerequest(
|
||||||
|
FBResult^ result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (result &&
|
||||||
|
result->Succeeded &&
|
||||||
|
!DidGetAllRequestedPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
void MainPage::NavigateToOptionsPage()
|
void MainPage::NavigateToOptionsPage()
|
||||||
{
|
{
|
||||||
LoginButton->Content = L"Logout";
|
LoginButton->Content = L"Logout";
|
||||||
|
|
||||||
// We're redirecting to a page that shows simple user info, so
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
// have to dispatch back to the UI thread.
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
CoreWindow^ wind = CoreApplication::MainView->CoreWindow;
|
ref new Windows::UI::Core::DispatchedHandler([this]()
|
||||||
|
|
||||||
if (wind)
|
|
||||||
{
|
{
|
||||||
CoreDispatcher^ disp = wind->Dispatcher;
|
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
||||||
if (disp)
|
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
||||||
{
|
f->Navigate(OptionsPage::typeid);
|
||||||
disp->RunAsync(
|
}));
|
||||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
|
||||||
ref new Windows::UI::Core::DispatchedHandler([this]()
|
|
||||||
{
|
|
||||||
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
|
||||||
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
|
||||||
f->Navigate(OptionsPage::typeid);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task<FBResult^> MainPage::LoginViaRerequest(
|
void MainPage::TryRerequest(
|
||||||
PropertySet^ Parameters
|
BOOL retry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Parameters->Insert(L"auth_type", L"rerequest");
|
// If we're logged out, the session has cleared the FB and Windows app IDs,
|
||||||
return create_task(FBSession::ActiveSession->Logout())
|
// so they need to be set again. We load these IDs via the ResourceLoader
|
||||||
.then([=]()
|
// class, which must be accessed on the UI thread, which is why this call
|
||||||
{
|
// is outside the task context.
|
||||||
SetSessionAppIds();
|
SetSessionAppIds();
|
||||||
|
|
||||||
return FBSession::ActiveSession->LoginAsync(Parameters);
|
create_task(FBSession::ActiveSession->LoginAsync(BuildPermissions()))
|
||||||
});
|
.then([=](FBResult^ result)
|
||||||
|
{
|
||||||
|
if (result->Succeeded)
|
||||||
|
{
|
||||||
|
if (retry && (!DidGetAllRequestedPermissions()))
|
||||||
|
{
|
||||||
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
|
TryRerequest(false);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NavigateToOptionsPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::login_OnClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
|
void MainPage::LogoutAndRetry(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// It's necessary to logout prior to reattempting login, because it could
|
||||||
|
// be that the session has cached an access token that is no longer valid,
|
||||||
|
// e.g. if the user revoked the app in Settings. FBSession::Logout clears
|
||||||
|
// the session's cached access token, among other things.
|
||||||
|
create_task(FBSession::ActiveSession->Logout())
|
||||||
|
.then([=]()
|
||||||
|
{
|
||||||
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
|
TryRerequest(TRUE);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainPage::login_OnClicked(
|
||||||
|
Object^ sender,
|
||||||
|
RoutedEventArgs^ e
|
||||||
|
)
|
||||||
{
|
{
|
||||||
FBSession^ sess = FBSession::ActiveSession;
|
FBSession^ sess = FBSession::ActiveSession;
|
||||||
|
|
||||||
|
@ -187,48 +234,32 @@ void MainPage::login_OnClicked(Platform::Object^ sender, Windows::UI::Xaml::Rout
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PropertySet^ parameters = ref new PropertySet();
|
create_task(sess->LoginAsync(BuildPermissions())).then([=](FBResult^ result)
|
||||||
|
|
||||||
parameters->Insert(L"scope", BuildPermissionsString());
|
|
||||||
|
|
||||||
create_task(sess->LoginAsync(parameters)).then([=](FBResult^ result)
|
|
||||||
{
|
{
|
||||||
task<FBResult^> nextResult = create_task([=]()
|
// There may be other cases where an a failed login request should
|
||||||
|
// prompt the app to retry login, but this one is common enough that
|
||||||
|
// it's helpful to demonstrate handling it here. If the predicate
|
||||||
|
// returns TRUE, the user has gone to facebook.com in the browser,
|
||||||
|
// and removed our app from their list off allowed apps in Settings.
|
||||||
|
if (WasAppPermissionRemovedByUser(result))
|
||||||
{
|
{
|
||||||
return result;
|
LogoutAndRetry();
|
||||||
});
|
}
|
||||||
|
else if (ShouldRerequest(result))
|
||||||
if ((!result->Succeeded) &&
|
{
|
||||||
((result->ErrorInfo->Code == 190) && (result->ErrorInfo->Subcode == 466)))
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
{
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
nextResult = LoginViaRerequest(parameters);
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
}
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
return nextResult;
|
TryRerequest(FALSE);
|
||||||
})
|
}));
|
||||||
.then([=](FBResult^ loginResult)
|
}
|
||||||
{
|
else if (result->Succeeded)
|
||||||
task<FBResult^> finalResult = create_task([=]()
|
|
||||||
{
|
|
||||||
return loginResult;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loginResult->Succeeded)
|
|
||||||
{
|
|
||||||
if (!DidGetAllRequestedPermissions())
|
|
||||||
{
|
|
||||||
finalResult = LoginViaRerequest(parameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalResult;
|
|
||||||
})
|
|
||||||
.then([=](FBResult^ finalResult)
|
|
||||||
{
|
|
||||||
if (finalResult->Succeeded)
|
|
||||||
{
|
{
|
||||||
|
// Got a token and all our permissions.
|
||||||
NavigateToOptionsPage();
|
NavigateToOptionsPage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,18 +37,29 @@ namespace LoginCpp
|
||||||
void MainPage::SetSessionAppIds(
|
void MainPage::SetSessionAppIds(
|
||||||
);
|
);
|
||||||
|
|
||||||
Platform::String^ BuildPermissionsString(
|
Facebook::FBPermissions^ BuildPermissions(
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOL DidGetAllRequestedPermissions(
|
BOOL DidGetAllRequestedPermissions(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
Facebook::FBResult^ result
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL ShouldRerequest(
|
||||||
|
Facebook::FBResult^ result
|
||||||
|
);
|
||||||
|
|
||||||
void NavigateToOptionsPage(
|
void NavigateToOptionsPage(
|
||||||
);
|
);
|
||||||
|
|
||||||
concurrency::task<Facebook::FBResult^> MainPage::LoginViaRerequest(
|
void MainPage::TryRerequest(
|
||||||
Windows::Foundation::Collections::PropertySet^ Parameters
|
BOOL retry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void MainPage::LogoutAndRetry(
|
||||||
|
);
|
||||||
|
|
||||||
void login_OnClicked(
|
void login_OnClicked(
|
||||||
Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e
|
Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e
|
||||||
|
|
|
@ -23,148 +23,198 @@
|
||||||
#include "MainPage.xaml.h"
|
#include "MainPage.xaml.h"
|
||||||
#include "OptionsPage.xaml.h"
|
#include "OptionsPage.xaml.h"
|
||||||
|
|
||||||
using namespace LoginCpp;
|
|
||||||
|
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
|
using namespace Facebook;
|
||||||
|
using namespace LoginCpp;
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
|
using namespace Platform::Collections;
|
||||||
using namespace Windows::ApplicationModel;
|
using namespace Windows::ApplicationModel;
|
||||||
using namespace Windows::ApplicationModel::Activation;
|
using namespace Windows::ApplicationModel::Activation;
|
||||||
using namespace Windows::ApplicationModel::Core;
|
using namespace Windows::ApplicationModel::Core;
|
||||||
using namespace Windows::ApplicationModel::Resources;
|
using namespace Windows::ApplicationModel::Resources;
|
||||||
using namespace Windows::Foundation;
|
using namespace Windows::Foundation;
|
||||||
using namespace Windows::Foundation::Collections;
|
using namespace Windows::Foundation::Collections;
|
||||||
using namespace Windows::UI::Xaml;
|
using namespace Windows::Security::Authentication::Web;
|
||||||
using namespace Windows::UI::Core;
|
using namespace Windows::UI::Core;
|
||||||
|
using namespace Windows::UI::Xaml;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
||||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||||
using namespace Windows::UI::Xaml::Data;
|
using namespace Windows::UI::Xaml::Data;
|
||||||
using namespace Windows::UI::Xaml::Input;
|
using namespace Windows::UI::Xaml::Input;
|
||||||
using namespace Windows::UI::Xaml::Media;
|
using namespace Windows::UI::Xaml::Media;
|
||||||
using namespace Windows::UI::Xaml::Navigation;
|
using namespace Windows::UI::Xaml::Navigation;
|
||||||
using namespace Facebook;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
#define FBAppIDName L"FBApplicationId"
|
#define FBAppIDName L"FBApplicationId"
|
||||||
#define FBStoreAppIDName L"FBWindowsAppId"
|
#define FBStoreAppIDName L"FBWindowsAppId"
|
||||||
#define PermissionGranted L"granted"
|
#define PermissionGranted L"granted"
|
||||||
|
|
||||||
const wchar_t* requested_permissions[] =
|
const wchar_t* requested_permissions[] =
|
||||||
{
|
{
|
||||||
L"public_profile",
|
L"public_profile",
|
||||||
L"user_friends",
|
L"user_friends",
|
||||||
L"user_likes",
|
L"user_likes",
|
||||||
L"user_groups",
|
L"user_groups",
|
||||||
L"user_location"
|
L"user_location"
|
||||||
};
|
};
|
||||||
|
|
||||||
MainPage::MainPage()
|
MainPage::MainPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
SetSessionAppIds();
|
|
||||||
|
String^ whatever = WebAuthenticationBroker::GetCurrentApplicationCallbackUri()->DisplayUri + L"\n";
|
||||||
|
OutputDebugString(whatever->Data());
|
||||||
|
|
||||||
|
SetSessionAppIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::SetSessionAppIds()
|
void MainPage::SetSessionAppIds()
|
||||||
{
|
{
|
||||||
FBSession^ s = FBSession::ActiveSession;
|
FBSession^ s = FBSession::ActiveSession;
|
||||||
|
|
||||||
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
||||||
// in the default resource file.
|
// in the default resource file.
|
||||||
ResourceLoader^ rl = ResourceLoader::GetForCurrentView();
|
ResourceLoader^ rl = ResourceLoader::GetForCurrentView();
|
||||||
|
|
||||||
String^ appId = rl->GetString(FBAppIDName);
|
String^ appId = rl->GetString(FBAppIDName);
|
||||||
String^ winAppId = rl->GetString(FBStoreAppIDName);
|
String^ winAppId = rl->GetString(FBStoreAppIDName);
|
||||||
|
|
||||||
// IDs are both sent to FB app, so it can validate us.
|
// IDs are both sent to FB app, so it can validate us.
|
||||||
s->FBAppId = appId;
|
s->FBAppId = appId;
|
||||||
s->WinAppId = winAppId;
|
s->WinAppId = winAppId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String^ MainPage::BuildPermissionsString(
|
FBPermissions^ MainPage::BuildPermissions(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
String^ result = ref new String();
|
FBPermissions^ result = ref new FBPermissions();
|
||||||
|
Vector<String^>^ v = ref new Vector<String^>();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
||||||
{
|
{
|
||||||
if (i)
|
v->Append(ref new String(requested_permissions[i]));
|
||||||
{
|
}
|
||||||
result += L",";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += ref new String(requested_permissions[i]);
|
result->Values = v->GetView();
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL MainPage::DidGetAllRequestedPermissions(
|
BOOL MainPage::DidGetAllRequestedPermissions(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOL success = FALSE;
|
||||||
|
FBAccessTokenData^ data = FBSession::ActiveSession->AccessTokenData;
|
||||||
|
unsigned int grantedCount = 0;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
||||||
|
{
|
||||||
|
String^ perm = ref new String(requested_permissions[i]);
|
||||||
|
if (data->Permissions && (data->Permissions->HasKey(perm)))
|
||||||
|
{
|
||||||
|
String^ Value = data->Permissions->Lookup(perm);
|
||||||
|
if (!String::CompareOrdinal(Value, PermissionGranted))
|
||||||
|
{
|
||||||
|
grantedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grantedCount == ARRAYSIZE(requested_permissions))
|
||||||
|
{
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
FBResult^ result
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOL success = FALSE;
|
return (result &&
|
||||||
FBAccessTokenData^ data = FBSession::ActiveSession->AccessTokenData;
|
(!result->Succeeded) &&
|
||||||
unsigned int grantedCount = 0;
|
((result->ErrorInfo->Code == (int)Facebook::ErrorCode::ErrorCodeOauthException) &&
|
||||||
|
(result->ErrorInfo->Subcode == (int)Facebook::ErrorSubcode::ErrorSubcodeSessionInvalidated)));
|
||||||
|
}
|
||||||
|
|
||||||
if (data)
|
BOOL MainPage::ShouldRerequest(
|
||||||
{
|
FBResult^ result
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
)
|
||||||
{
|
{
|
||||||
String^ perm = ref new String(requested_permissions[i]);
|
return (result &&
|
||||||
if (data->Permissions && (data->Permissions->HasKey(perm)))
|
result->Succeeded &&
|
||||||
{
|
!DidGetAllRequestedPermissions());
|
||||||
String^ Value = data->Permissions->Lookup(perm);
|
|
||||||
if (!String::CompareOrdinal(Value, PermissionGranted))
|
|
||||||
{
|
|
||||||
grantedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grantedCount == ARRAYSIZE(requested_permissions))
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::NavigateToOptionsPage()
|
void MainPage::NavigateToOptionsPage()
|
||||||
{
|
{
|
||||||
LoginButton->Content = L"Logout";
|
LoginButton->Content = L"Logout";
|
||||||
|
|
||||||
// We're redirecting to a page that shows simple user info, so
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
// have to dispatch back to the UI thread.
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
CoreWindow^ wind = CoreApplication::MainView->CoreWindow;
|
ref new Windows::UI::Core::DispatchedHandler([this]()
|
||||||
|
{
|
||||||
if (wind)
|
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
||||||
{
|
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
||||||
CoreDispatcher^ disp = wind->Dispatcher;
|
f->Navigate(OptionsPage::typeid);
|
||||||
if (disp)
|
}));
|
||||||
{
|
|
||||||
disp->RunAsync(
|
|
||||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
|
||||||
ref new Windows::UI::Core::DispatchedHandler([this]()
|
|
||||||
{
|
|
||||||
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
|
||||||
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
|
||||||
f->Navigate(OptionsPage::typeid);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task<FBResult^> MainPage::LoginViaRerequest(
|
void MainPage::TryRerequest(
|
||||||
PropertySet^ Parameters
|
BOOL retry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Parameters->Insert(L"auth_type", L"rerequest");
|
// If we're logged out, the session has cleared the FB and Windows app IDs,
|
||||||
return create_task(FBSession::ActiveSession->Logout())
|
// so they need to be set again. We load these IDs via the ResourceLoader
|
||||||
|
// class, which must be accessed on the UI thread, which is why this call
|
||||||
|
// is outside the task context.
|
||||||
|
SetSessionAppIds();
|
||||||
|
|
||||||
|
create_task(FBSession::ActiveSession->LoginAsync(BuildPermissions()))
|
||||||
|
.then([=](FBResult^ result)
|
||||||
|
{
|
||||||
|
if (result->Succeeded)
|
||||||
|
{
|
||||||
|
if (retry && (!DidGetAllRequestedPermissions()))
|
||||||
|
{
|
||||||
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
|
TryRerequest(false);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NavigateToOptionsPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainPage::LogoutAndRetry(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// It's necessary to logout prior to reattempting login, because it could
|
||||||
|
// be that the session has cached an access token that is no longer valid,
|
||||||
|
// e.g. if the user revoked the app in Settings. FBSession::Logout clears
|
||||||
|
// the session's cached access token, among other things.
|
||||||
|
create_task(FBSession::ActiveSession->Logout())
|
||||||
.then([=]()
|
.then([=]()
|
||||||
{
|
{
|
||||||
SetSessionAppIds();
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
return FBSession::ActiveSession->LoginAsync(Parameters);
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
|
TryRerequest(TRUE);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,49 +232,32 @@ void MainPage::login_OnClicked(Platform::Object^ sender, Windows::UI::Xaml::Rout
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PropertySet^ parameters = ref new PropertySet();
|
create_task(sess->LoginAsync(BuildPermissions())).then([=](FBResult^ result)
|
||||||
|
{
|
||||||
parameters->Insert(L"scope", BuildPermissionsString());
|
// There may be other cases where an a failed login request should
|
||||||
|
// prompt the app to retry login, but this one is common enough that
|
||||||
create_task(sess->LoginAsync(parameters)).then([=](FBResult^ result)
|
// it's helpful to demonstrate handling it here. If the predicate
|
||||||
{
|
// returns TRUE, the user has gone to facebook.com in the browser,
|
||||||
task<FBResult^> nextResult = create_task([=]()
|
// and removed our app from their list off allowed apps in Settings.
|
||||||
{
|
if (WasAppPermissionRemovedByUser(result))
|
||||||
return result;
|
{
|
||||||
});
|
LogoutAndRetry();
|
||||||
|
|
||||||
if ((!result->Succeeded) &&
|
|
||||||
((result->ErrorInfo->Code == 190) && (result->ErrorInfo->Subcode == 466)))
|
|
||||||
{
|
|
||||||
nextResult = LoginViaRerequest(parameters);
|
|
||||||
}
|
}
|
||||||
|
else if (ShouldRerequest(result))
|
||||||
return nextResult;
|
|
||||||
})
|
|
||||||
.then([=](FBResult^ loginResult)
|
|
||||||
{
|
|
||||||
task<FBResult^> finalResult = create_task([=]()
|
|
||||||
{
|
{
|
||||||
return loginResult;
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
});
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
if (loginResult->Succeeded)
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
{
|
|
||||||
if (!DidGetAllRequestedPermissions())
|
|
||||||
{
|
{
|
||||||
finalResult = LoginViaRerequest(parameters);
|
TryRerequest(FALSE);
|
||||||
}
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
return finalResult;
|
|
||||||
})
|
|
||||||
.then([=](FBResult^ finalResult)
|
|
||||||
{
|
|
||||||
if (finalResult->Succeeded)
|
|
||||||
{
|
|
||||||
NavigateToOptionsPage();
|
|
||||||
}
|
}
|
||||||
|
else if (result && result->Succeeded)
|
||||||
|
{
|
||||||
|
// Got a token, and all the permissions we wanted - go ahead to the options page
|
||||||
|
NavigateToOptionsPage();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,23 +33,36 @@ namespace LoginCpp
|
||||||
public:
|
public:
|
||||||
MainPage();
|
MainPage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void MainPage::SetSessionAppIds(
|
void MainPage::SetSessionAppIds(
|
||||||
|
);
|
||||||
|
|
||||||
|
Facebook::FBPermissions^ BuildPermissions(
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL DidGetAllRequestedPermissions(
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
Facebook::FBResult^ result
|
||||||
);
|
);
|
||||||
|
|
||||||
Platform::String^ BuildPermissionsString(
|
BOOL ShouldRerequest(
|
||||||
|
Facebook::FBResult^ result
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOL DidGetAllRequestedPermissions(
|
void NavigateToOptionsPage(
|
||||||
|
);
|
||||||
|
|
||||||
|
void MainPage::TryRerequest(
|
||||||
|
BOOL retry
|
||||||
);
|
);
|
||||||
|
|
||||||
void NavigateToOptionsPage(
|
void MainPage::LogoutAndRetry(
|
||||||
);
|
);
|
||||||
|
|
||||||
concurrency::task<Facebook::FBResult^> MainPage::LoginViaRerequest(
|
void login_OnClicked(
|
||||||
Windows::Foundation::Collections::PropertySet^ Parameters
|
Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e
|
||||||
);
|
);
|
||||||
|
|
||||||
void login_OnClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<DebuggerFlavor>WindowsPhoneEmulatorDebugger</DebuggerFlavor>
|
||||||
|
<WindowsPhoneEmulatorID>8BDF218D-FDBB-4A97-90F9-3AA33B559A92;Mobile Emulator 10.0.10240.0 WVGA 4 inch 512MB</WindowsPhoneEmulatorID>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
|
@ -9,7 +9,7 @@
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Button x:Name ="LoginButton" Content="Login" HorizontalAlignment="Left" Margin="39,48,0,0" VerticalAlignment="Top" Click="LoginButton_Click" Width="315"/>
|
<Button x:Name ="LoginButton" Content="Login" HorizontalAlignment="Left" Margin="39,48,0,0" VerticalAlignment="Top" Click="login_OnClicked" Width="315"/>
|
||||||
<TextBlock FontSize="14" HorizontalAlignment="Left" Margin="39,302,0,0" TextWrapping="Wrap" Text="Access Token:" VerticalAlignment="Top" Width="261" Height="18"/>
|
<TextBlock FontSize="14" HorizontalAlignment="Left" Margin="39,302,0,0" TextWrapping="Wrap" Text="Access Token:" VerticalAlignment="Top" Width="261" Height="18"/>
|
||||||
<TextBlock x:Name="ResponseText" FontSize="14" HorizontalAlignment="Left" Margin="39,325,0,0" Text="TextBox" TextWrapping="Wrap" VerticalAlignment="Top" Height="94" Width="261"/>
|
<TextBlock x:Name="ResponseText" FontSize="14" HorizontalAlignment="Left" Margin="39,325,0,0" Text="TextBox" TextWrapping="Wrap" VerticalAlignment="Top" Height="94" Width="261"/>
|
||||||
<TextBlock FontSize="14" HorizontalAlignment="Left" Margin="39,445,0,0" TextWrapping="Wrap" Text="Expires" VerticalAlignment="Top" Height="24" Width="261"/>
|
<TextBlock FontSize="14" HorizontalAlignment="Left" Margin="39,445,0,0" TextWrapping="Wrap" Text="Expires" VerticalAlignment="Top" Height="24" Width="261"/>
|
||||||
|
|
|
@ -23,13 +23,18 @@
|
||||||
#include "MainPage.xaml.h"
|
#include "MainPage.xaml.h"
|
||||||
#include "OptionsPage.xaml.h"
|
#include "OptionsPage.xaml.h"
|
||||||
|
|
||||||
using namespace LoginCpp;
|
|
||||||
|
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
|
using namespace Facebook;
|
||||||
|
using namespace LoginCpp;
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
|
using namespace Platform::Collections;
|
||||||
|
using namespace Windows::ApplicationModel;
|
||||||
|
using namespace Windows::ApplicationModel::Activation;
|
||||||
using namespace Windows::ApplicationModel::Core;
|
using namespace Windows::ApplicationModel::Core;
|
||||||
|
using namespace Windows::ApplicationModel::Resources;
|
||||||
using namespace Windows::Foundation;
|
using namespace Windows::Foundation;
|
||||||
using namespace Windows::Foundation::Collections;
|
using namespace Windows::Foundation::Collections;
|
||||||
|
using namespace Windows::Security::Authentication::Web;
|
||||||
using namespace Windows::UI::Core;
|
using namespace Windows::UI::Core;
|
||||||
using namespace Windows::UI::Xaml;
|
using namespace Windows::UI::Xaml;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
||||||
|
@ -38,225 +43,221 @@ using namespace Windows::UI::Xaml::Data;
|
||||||
using namespace Windows::UI::Xaml::Input;
|
using namespace Windows::UI::Xaml::Input;
|
||||||
using namespace Windows::UI::Xaml::Media;
|
using namespace Windows::UI::Xaml::Media;
|
||||||
using namespace Windows::UI::Xaml::Navigation;
|
using namespace Windows::UI::Xaml::Navigation;
|
||||||
using namespace Windows::ApplicationModel::Resources;
|
|
||||||
using namespace Windows::Globalization;
|
|
||||||
using namespace Facebook;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
#define FBAppIDName L"FBApplicationId"
|
#define FBAppIDName L"FBApplicationId"
|
||||||
#define FBPhoneAppIDName L"FBWinPhoneAppId"
|
#define FBStoreAppIDName L"FBWindowsAppId"
|
||||||
#define PermissionGranted L"granted"
|
#define PermissionGranted L"granted"
|
||||||
|
|
||||||
const wchar_t* requested_permissions[] =
|
const wchar_t* requested_permissions[] =
|
||||||
{
|
{
|
||||||
L"public_profile",
|
L"public_profile",
|
||||||
L"user_friends",
|
L"user_friends",
|
||||||
L"user_likes",
|
L"user_likes",
|
||||||
L"user_groups",
|
L"user_groups",
|
||||||
L"user_location"
|
L"user_location"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MainPage::MainPage()
|
MainPage::MainPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
SetSessionAppIds();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
String^ whatever = WebAuthenticationBroker::GetCurrentApplicationCallbackUri()->DisplayUri + L"\n";
|
||||||
/// Invoked when this page is about to be displayed in a Frame.
|
OutputDebugString(whatever->Data());
|
||||||
/// </summary>
|
|
||||||
/// <param name="e">Event data that describes how this page was reached. The Parameter
|
|
||||||
/// property is typically used to configure the page.</param>
|
|
||||||
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
|
|
||||||
{
|
|
||||||
(void)e; // Unused parameter
|
|
||||||
|
|
||||||
// TODO: Prepare page for display here.
|
SetSessionAppIds();
|
||||||
|
|
||||||
// TODO: If your application contains multiple pages, ensure that you are
|
|
||||||
// handling the hardware Back button by registering for the
|
|
||||||
// Windows::Phone::UI::Input::HardwareButtons.BackPressed event.
|
|
||||||
// If you are using the NavigationHelper provided by some templates,
|
|
||||||
// this event is handled for you.
|
|
||||||
FBSession^ sess = FBSession::ActiveSession;
|
|
||||||
|
|
||||||
if (sess->LoggedIn)
|
|
||||||
{
|
|
||||||
LoginButton->Content = L"Logout";
|
|
||||||
Calendar^ cal = ref new Calendar();
|
|
||||||
cal->SetDateTime(sess->AccessTokenData->ExpirationDate);
|
|
||||||
|
|
||||||
ResponseText->Text = sess->AccessTokenData->AccessToken;
|
|
||||||
|
|
||||||
ExpirationDate->Text = cal->DayOfWeekAsString() + "," + cal->YearAsString() + "/" +
|
|
||||||
cal->MonthAsNumericString() + "/" + cal->DayAsString() + ", " +
|
|
||||||
cal->HourAsPaddedString(2) + ":" + cal->MinuteAsPaddedString(2) + ":" +
|
|
||||||
cal->SecondAsPaddedString(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::SetSessionAppIds()
|
void MainPage::SetSessionAppIds()
|
||||||
{
|
{
|
||||||
FBSession^ s = FBSession::ActiveSession;
|
FBSession^ s = FBSession::ActiveSession;
|
||||||
|
|
||||||
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
||||||
// in the default resource file.
|
// in the default resource file.
|
||||||
ResourceLoader^ rl = ResourceLoader::GetForCurrentView();
|
ResourceLoader^ rl = ResourceLoader::GetForCurrentView();
|
||||||
|
|
||||||
String^ appId = rl->GetString(FBAppIDName);
|
String^ appId = rl->GetString(FBAppIDName);
|
||||||
String^ winAppId = rl->GetString(FBPhoneAppIDName);
|
String^ winAppId = rl->GetString(FBStoreAppIDName);
|
||||||
|
|
||||||
// IDs are both sent to FB app, so it can validate us.
|
// IDs are both sent to FB app, so it can validate us.
|
||||||
s->FBAppId = appId;
|
s->FBAppId = appId;
|
||||||
s->WinAppId = winAppId;
|
s->WinAppId = winAppId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String^ MainPage::BuildPermissionsString(
|
FBPermissions^ MainPage::BuildPermissions(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
String^ result = ref new String();
|
FBPermissions^ result = ref new FBPermissions();
|
||||||
|
Vector<String^>^ v = ref new Vector<String^>();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
||||||
{
|
{
|
||||||
if (i)
|
v->Append(ref new String(requested_permissions[i]));
|
||||||
{
|
}
|
||||||
result += L",";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += ref new String(requested_permissions[i]);
|
result->Values = v->GetView();
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL MainPage::DidGetAllRequestedPermissions(
|
BOOL MainPage::DidGetAllRequestedPermissions(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOL success = FALSE;
|
BOOL success = FALSE;
|
||||||
FBAccessTokenData^ data = FBSession::ActiveSession->AccessTokenData;
|
FBAccessTokenData^ data = FBSession::ActiveSession->AccessTokenData;
|
||||||
unsigned int grantedCount = 0;
|
unsigned int grantedCount = 0;
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
for (unsigned int i = 0; i < ARRAYSIZE(requested_permissions); i++)
|
||||||
{
|
{
|
||||||
String^ perm = ref new String(requested_permissions[i]);
|
String^ perm = ref new String(requested_permissions[i]);
|
||||||
if (data->Permissions && (data->Permissions->HasKey(perm)))
|
if (data->Permissions && (data->Permissions->HasKey(perm)))
|
||||||
{
|
{
|
||||||
String^ Value = data->Permissions->Lookup(perm);
|
String^ Value = data->Permissions->Lookup(perm);
|
||||||
if (!String::CompareOrdinal(Value, PermissionGranted))
|
if (!String::CompareOrdinal(Value, PermissionGranted))
|
||||||
{
|
{
|
||||||
grantedCount++;
|
grantedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grantedCount == ARRAYSIZE(requested_permissions))
|
if (grantedCount == ARRAYSIZE(requested_permissions))
|
||||||
{
|
{
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
FBResult^ result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (result &&
|
||||||
|
(!result->Succeeded) &&
|
||||||
|
((result->ErrorInfo->Code == (int)Facebook::ErrorCode::ErrorCodeOauthException) &&
|
||||||
|
(result->ErrorInfo->Subcode == (int)Facebook::ErrorSubcode::ErrorSubcodeSessionInvalidated)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MainPage::ShouldRerequest(
|
||||||
|
FBResult^ result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (result &&
|
||||||
|
result->Succeeded &&
|
||||||
|
!DidGetAllRequestedPermissions());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::NavigateToOptionsPage()
|
void MainPage::NavigateToOptionsPage()
|
||||||
{
|
{
|
||||||
LoginButton->Content = L"Logout";
|
LoginButton->Content = L"Logout";
|
||||||
|
|
||||||
// We're redirecting to a page that shows simple user info, so
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
// have to dispatch back to the UI thread.
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
CoreWindow^ wind = CoreApplication::MainView->CoreWindow;
|
ref new Windows::UI::Core::DispatchedHandler([this]()
|
||||||
|
{
|
||||||
if (wind)
|
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
||||||
{
|
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
||||||
CoreDispatcher^ disp = wind->Dispatcher;
|
f->Navigate(OptionsPage::typeid);
|
||||||
if (disp)
|
}));
|
||||||
{
|
|
||||||
disp->RunAsync(
|
|
||||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
|
||||||
ref new Windows::UI::Core::DispatchedHandler([this]()
|
|
||||||
{
|
|
||||||
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
|
||||||
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
|
||||||
f->Navigate(OptionsPage::typeid);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task<FBResult^> MainPage::LoginViaRerequest(
|
void MainPage::TryRerequest(
|
||||||
PropertySet^ Parameters
|
BOOL retry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Parameters->Insert(L"auth_type", L"rerequest");
|
// If we're logged out, the session has cleared the FB and Windows app IDs,
|
||||||
return create_task(FBSession::ActiveSession->Logout())
|
// so they need to be set again. We load these IDs via the ResourceLoader
|
||||||
.then([=]()
|
// class, which must be accessed on the UI thread, which is why this call
|
||||||
{
|
// is outside the task context.
|
||||||
SetSessionAppIds();
|
SetSessionAppIds();
|
||||||
|
|
||||||
return FBSession::ActiveSession->LoginAsync(Parameters);
|
create_task(FBSession::ActiveSession->LoginAsync(BuildPermissions()))
|
||||||
});
|
.then([=](FBResult^ result)
|
||||||
|
{
|
||||||
|
if (result->Succeeded)
|
||||||
|
{
|
||||||
|
if (retry && (!DidGetAllRequestedPermissions()))
|
||||||
|
{
|
||||||
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
|
{
|
||||||
|
TryRerequest(false);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NavigateToOptionsPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPage::LoginButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
|
void MainPage::LogoutAndRetry(
|
||||||
|
)
|
||||||
{
|
{
|
||||||
FBSession^ sess = FBSession::ActiveSession;
|
// It's necessary to logout prior to reattempting login, because it could
|
||||||
|
// be that the session has cached an access token that is no longer valid,
|
||||||
if (sess->LoggedIn)
|
// e.g. if the user revoked the app in Settings. FBSession::Logout clears
|
||||||
{
|
// the session's cached access token, among other things.
|
||||||
sess->Logout();
|
create_task(FBSession::ActiveSession->Logout())
|
||||||
LoginButton->Content = L"Logout";
|
.then([=]()
|
||||||
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
{
|
||||||
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
f->Navigate(MainPage::typeid);
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
}
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
else
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
{
|
{
|
||||||
PropertySet^ parameters = ref new PropertySet();
|
TryRerequest(TRUE);
|
||||||
|
}));
|
||||||
parameters->Insert(L"scope", BuildPermissionsString());
|
});
|
||||||
|
}
|
||||||
create_task(sess->LoginAsync(parameters)).then([=](FBResult^ result)
|
|
||||||
{
|
void MainPage::login_OnClicked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
|
||||||
task<FBResult^> nextResult = create_task([=]()
|
{
|
||||||
{
|
FBSession^ sess = FBSession::ActiveSession;
|
||||||
return result;
|
|
||||||
});
|
if (sess->LoggedIn)
|
||||||
|
{
|
||||||
if ((!result->Succeeded) &&
|
sess->Logout();
|
||||||
((result->ErrorInfo->Code == 190) && (result->ErrorInfo->Subcode == 466)))
|
LoginButton->Content = L"Logout";
|
||||||
{
|
LoginCpp::App^ a = dynamic_cast<LoginCpp::App^>(Application::Current);
|
||||||
nextResult = LoginViaRerequest(parameters);
|
Windows::UI::Xaml::Controls::Frame^ f = a->CreateRootFrame();
|
||||||
}
|
f->Navigate(MainPage::typeid);
|
||||||
|
}
|
||||||
return nextResult;
|
else
|
||||||
})
|
{
|
||||||
.then([=](FBResult^ loginResult)
|
create_task(sess->LoginAsync(BuildPermissions())).then([=](FBResult^ result)
|
||||||
{
|
{
|
||||||
task<FBResult^> finalResult = create_task([=]()
|
// There may be other cases where an a failed login request should
|
||||||
{
|
// prompt the app to retry login, but this one is common enough that
|
||||||
return loginResult;
|
// it's helpful to demonstrate handling it here. If the predicate
|
||||||
});
|
// returns TRUE, the user has gone to facebook.com in the browser,
|
||||||
|
// and removed our app from their list off allowed apps in Settings.
|
||||||
if (loginResult->Succeeded)
|
if (WasAppPermissionRemovedByUser(result))
|
||||||
{
|
{
|
||||||
if (!DidGetAllRequestedPermissions())
|
LogoutAndRetry();
|
||||||
{
|
}
|
||||||
finalResult = LoginViaRerequest(parameters);
|
else if (ShouldRerequest(result))
|
||||||
}
|
{
|
||||||
}
|
// Login call has to happen on UI thread, so circle back around to it
|
||||||
|
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||||
return finalResult;
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||||
})
|
ref new Windows::UI::Core::DispatchedHandler([=]()
|
||||||
.then([=](FBResult^ finalResult)
|
{
|
||||||
{
|
TryRerequest(FALSE);
|
||||||
if (finalResult->Succeeded)
|
}));
|
||||||
{
|
}
|
||||||
NavigateToOptionsPage();
|
else if (result && result->Succeeded)
|
||||||
}
|
{
|
||||||
});
|
// Got a token, and all the permissions we wanted - go ahead to the options page
|
||||||
}
|
NavigateToOptionsPage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,45 +25,45 @@
|
||||||
|
|
||||||
namespace LoginCpp
|
namespace LoginCpp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ref class MainPage sealed
|
public ref class MainPage sealed
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MainPage();
|
MainPage();
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void OnNavigatedTo(
|
|
||||||
Windows::UI::Xaml::Navigation::NavigationEventArgs^ e
|
|
||||||
) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void StartLogin(
|
void MainPage::SetSessionAppIds(
|
||||||
Facebook::FBSession^ Session
|
|
||||||
);
|
|
||||||
|
|
||||||
void MainPage::SetSessionAppIds(
|
|
||||||
);
|
|
||||||
|
|
||||||
Platform::String^ BuildPermissionsString(
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOL DidGetAllRequestedPermissions(
|
|
||||||
);
|
|
||||||
|
|
||||||
void NavigateToOptionsPage(
|
|
||||||
);
|
|
||||||
|
|
||||||
concurrency::task<Facebook::FBResult^> MainPage::LoginViaRerequest(
|
|
||||||
Windows::Foundation::Collections::PropertySet^ Parameters
|
|
||||||
);
|
|
||||||
|
|
||||||
void LoginButton_Click(
|
|
||||||
Platform::Object^ sender,
|
|
||||||
Windows::UI::Xaml::RoutedEventArgs^ e
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Windows::Foundation::EventRegistrationToken m_cookie;
|
Facebook::FBPermissions^ BuildPermissions(
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL DidGetAllRequestedPermissions(
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL MainPage::WasAppPermissionRemovedByUser(
|
||||||
|
Facebook::FBResult^ result
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOL ShouldRerequest(
|
||||||
|
Facebook::FBResult^ result
|
||||||
|
);
|
||||||
|
|
||||||
|
void NavigateToOptionsPage(
|
||||||
|
);
|
||||||
|
|
||||||
|
void MainPage::TryRerequest(
|
||||||
|
BOOL retry
|
||||||
|
);
|
||||||
|
|
||||||
|
void MainPage::LogoutAndRetry(
|
||||||
|
);
|
||||||
|
|
||||||
|
void login_OnClicked(
|
||||||
|
Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e
|
||||||
|
);
|
||||||
|
void LoginButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<<<<<<< HEAD
|
|
||||||
<Import Project="..\..\packages\FBWinSDK-debug.0.9.0\build\FBWinSDK-debug.props" Condition="Exists('..\..\packages\FBWinSDK-debug.0.9.0\build\FBWinSDK-debug.props')" />
|
|
||||||
<Import Project="..\..\packages\FBWinSDK.0.9.0\build\win\FBWinSDK.props" Condition="Exists('..\..\packages\FBWinSDK.0.9.0\build\win\FBWinSDK.props')" />
|
|
||||||
=======
|
|
||||||
>>>>>>> 26_change_sample_sdk_references
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
|
|
@ -32,6 +32,8 @@ using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
using Facebook;
|
using Facebook;
|
||||||
using Windows.Globalization;
|
using Windows.Globalization;
|
||||||
|
using Windows.ApplicationModel.Resources;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
@ -45,11 +47,14 @@ namespace LoginCs
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
|
SetSessionAppIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string _granted = "granted";
|
private const string FBAppIDName = "FBApplicationId";
|
||||||
|
private const string FBPhoneAppIDName = "FBWinPhoneAppId";
|
||||||
|
private const string PermissionGranted = "granted";
|
||||||
|
|
||||||
private string[] requested_permissions =
|
private readonly string[] requested_permissions =
|
||||||
{
|
{
|
||||||
"public_profile",
|
"public_profile",
|
||||||
"email",
|
"email",
|
||||||
|
@ -57,39 +62,55 @@ namespace LoginCs
|
||||||
"publish_actions"
|
"publish_actions"
|
||||||
};
|
};
|
||||||
|
|
||||||
private string BuildPermissionsString()
|
void SetSessionAppIds(
|
||||||
|
)
|
||||||
{
|
{
|
||||||
string permissions = "";
|
FBSession s = FBSession.ActiveSession;
|
||||||
|
|
||||||
|
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
||||||
|
// in the default resource file.
|
||||||
|
ResourceLoader rl = ResourceLoader.GetForCurrentView();
|
||||||
|
|
||||||
|
String appId = rl.GetString(FBAppIDName);
|
||||||
|
String winAppId = rl.GetString(FBPhoneAppIDName);
|
||||||
|
|
||||||
|
// IDs are both sent to FB app, so it can validate us.
|
||||||
|
s.FBAppId = appId;
|
||||||
|
s.WinAppId = winAppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBPermissions BuildPermissions(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FBPermissions result = new FBPermissions();
|
||||||
|
List<string> perms = new List<string>();
|
||||||
|
|
||||||
for (uint i = 0; i < requested_permissions.Length; i++)
|
for (uint i = 0; i < requested_permissions.Length; i++)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
perms.Add(requested_permissions[i]);
|
||||||
{
|
|
||||||
permissions += ",";
|
|
||||||
}
|
|
||||||
|
|
||||||
permissions += requested_permissions[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return permissions;
|
result.Values = perms;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DidGetRequestedPermissions(
|
bool DidGetAllRequestedPermissions(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool gotPermissions = false;
|
bool success = false;
|
||||||
|
FBAccessTokenData data = FBSession.ActiveSession.AccessTokenData;
|
||||||
uint grantedCount = 0;
|
uint grantedCount = 0;
|
||||||
|
|
||||||
if (FBSession.ActiveSession.AccessTokenData != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
IReadOnlyDictionary<string, string> Permissions =
|
|
||||||
FBSession.ActiveSession.AccessTokenData.Permissions;
|
|
||||||
|
|
||||||
for (uint i = 0; i < requested_permissions.Length; i++)
|
for (uint i = 0; i < requested_permissions.Length; i++)
|
||||||
{
|
{
|
||||||
if (Permissions.ContainsKey(requested_permissions[i]))
|
string perm = requested_permissions[i];
|
||||||
|
if ((data.Permissions != null) && (data.Permissions.ContainsKey(perm)))
|
||||||
{
|
{
|
||||||
if (String.CompareOrdinal(Permissions[requested_permissions[i]], _granted) == 0)
|
string Value = data.Permissions[perm];
|
||||||
|
if (string.CompareOrdinal(Value, PermissionGranted) == 0)
|
||||||
{
|
{
|
||||||
grantedCount++;
|
grantedCount++;
|
||||||
}
|
}
|
||||||
|
@ -98,49 +119,53 @@ namespace LoginCs
|
||||||
|
|
||||||
if (grantedCount == requested_permissions.Length)
|
if (grantedCount == requested_permissions.Length)
|
||||||
{
|
{
|
||||||
gotPermissions = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gotPermissions;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void LoginToFB()
|
bool WasAppPermissionRemovedByUser(
|
||||||
|
FBResult Result
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Uri endURI =
|
return ((Result != null) &&
|
||||||
WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
|
(!Result.Succeeded) &&
|
||||||
string uriString = endURI.ToString();
|
(Result.ErrorInfo.Code == (int)Facebook.ErrorCode.ErrorCodeOauthException));
|
||||||
PropertySet parameters = new PropertySet();
|
}
|
||||||
|
|
||||||
parameters.Add(new KeyValuePair<String, Object>("scope",
|
bool ShouldRerequest(
|
||||||
BuildPermissionsString()));
|
FBResult Result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ((Result != null) &&
|
||||||
|
Result.Succeeded &&
|
||||||
|
!DidGetAllRequestedPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
FBResult result = await FBSession.ActiveSession.LoginAsync(parameters);
|
async Task TryRerequest(
|
||||||
if ((!result.Succeeded) &&
|
bool Retry
|
||||||
(((ErrorCode)result.ErrorInfo.Code == ErrorCode.ErrorCodeOauthException) &&
|
)
|
||||||
((ErrorSubcode)result.ErrorInfo.Subcode == ErrorSubcode.ErrorSubcodeSessionInvalidated)))
|
{
|
||||||
{
|
// If we're logged out, the session has cleared the FB and Windows app IDs,
|
||||||
parameters.Add(new KeyValuePair<String, Object>("auth_type", "rerequest"));
|
// so they need to be set again. We load these IDs via the ResourceLoader
|
||||||
result = await FBSession.ActiveSession.LoginAsync(parameters);
|
// class, which must be accessed on the UI thread, which is why this call
|
||||||
}
|
// is outside the task context.
|
||||||
|
SetSessionAppIds();
|
||||||
|
|
||||||
|
FBResult result = await FBSession.ActiveSession.LoginAsync(BuildPermissions());
|
||||||
|
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
if (DidGetRequestedPermissions())
|
if (Retry && (!DidGetAllRequestedPermissions()))
|
||||||
{
|
{
|
||||||
Frame.Navigate(typeof(UserInfo));
|
await TryRerequest(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!parameters.ContainsKey("auth_type"))
|
//Navigate back to same page, to clear out logged in info.
|
||||||
{
|
App.RootFrame.Navigate(typeof(UserInfo));
|
||||||
parameters.Add(new KeyValuePair<String, Object>("auth_type", "rerequest"));
|
|
||||||
}
|
|
||||||
result = await FBSession.ActiveSession.LoginAsync(parameters);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
Frame.Navigate(typeof(UserInfo));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +219,27 @@ namespace LoginCs
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LoginButton.Content = "Logout";
|
LoginButton.Content = "Logout";
|
||||||
LoginToFB();
|
FBResult result = await sess.LoginAsync(BuildPermissions());
|
||||||
|
|
||||||
|
// There may be other cases where an a failed login request should
|
||||||
|
// prompt the app to retry login, but this one is common enough that
|
||||||
|
// it's helpful to demonstrate handling it here. If the predicate
|
||||||
|
// returns TRUE, the user has gone to facebook.com in the browser,
|
||||||
|
// and removed our app from their list off allowed apps in Settings.
|
||||||
|
if (WasAppPermissionRemovedByUser(result))
|
||||||
|
{
|
||||||
|
await sess.Logout();
|
||||||
|
await TryRerequest(true);
|
||||||
|
}
|
||||||
|
else if (ShouldRerequest(result))
|
||||||
|
{
|
||||||
|
await TryRerequest(false);
|
||||||
|
}
|
||||||
|
else if (result.Succeeded)
|
||||||
|
{
|
||||||
|
//Navigate back to same page, to clear out logged in info.
|
||||||
|
App.RootFrame.Navigate(typeof(UserInfo));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Windows.ApplicationModel.Resources;
|
using Windows.ApplicationModel.Resources;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
using Windows.Foundation.Collections;
|
using Windows.Foundation.Collections;
|
||||||
|
@ -41,45 +42,133 @@ namespace LoginCs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
const string FBAppIDName = "FBApplicationId";
|
const string FBAppIDName = "FBApplicationId";
|
||||||
const string FBPhoneAppIDName = "FBWinPhoneAppId";
|
const string FBPhoneAppIDName = "FBWinPhoneAppId";
|
||||||
|
const string PermissionGranted = "granted";
|
||||||
|
|
||||||
|
readonly string[] requested_permissions =
|
||||||
|
{
|
||||||
|
"public_profile",
|
||||||
|
"user_friends",
|
||||||
|
"user_likes",
|
||||||
|
"user_groups",
|
||||||
|
"user_location"
|
||||||
|
};
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
|
|
||||||
this.NavigationCacheMode = NavigationCacheMode.Required;
|
this.NavigationCacheMode = NavigationCacheMode.Required;
|
||||||
|
SetSessionAppIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void StartLogin(
|
void SetSessionAppIds(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FBSession s = FBSession.ActiveSession;
|
FBSession s = FBSession.ActiveSession;
|
||||||
|
|
||||||
// Assumes the Facebook App ID and Windows Phone Store ID have been
|
// Assumes the Facebook App ID and Windows Phone Store ID have been saved
|
||||||
// saved in the default resource file.
|
// in the default resource file.
|
||||||
ResourceLoader rl = ResourceLoader.GetForCurrentView();
|
ResourceLoader rl = ResourceLoader.GetForCurrentView();
|
||||||
|
|
||||||
String appId = rl.GetString(FBAppIDName);
|
String appId = rl.GetString(FBAppIDName);
|
||||||
String winAppId = rl.GetString(FBPhoneAppIDName);
|
String winAppId = rl.GetString(FBPhoneAppIDName);
|
||||||
|
|
||||||
|
|
||||||
// IDs are both sent to FB app, so it can validate us.
|
// IDs are both sent to FB app, so it can validate us.
|
||||||
s.FBAppId = appId;
|
s.FBAppId = appId;
|
||||||
s.WinAppId = winAppId;
|
s.WinAppId = winAppId;
|
||||||
|
}
|
||||||
|
|
||||||
// These are the default permissions, needed to retrieve user info.
|
FBPermissions BuildPermissions(
|
||||||
//s.AddPermission("public_profile");
|
)
|
||||||
//s.AddPermission("user_friends");
|
{
|
||||||
//s.AddPermission("user_likes");
|
FBPermissions result = new FBPermissions();
|
||||||
|
List<string> perms = new List<string>();
|
||||||
|
|
||||||
PropertySet parameters = new PropertySet();
|
for (uint i = 0; i < requested_permissions.Length; i++)
|
||||||
parameters.Add(
|
{
|
||||||
new KeyValuePair<string, object>("scope",
|
perms.Add(requested_permissions[i]);
|
||||||
"public_profile,user_friends,user_likes"));
|
}
|
||||||
// Launches a URI to redirect to the FB app, which will log us in
|
|
||||||
// and return the result via our registered protocol.
|
result.Values = perms;
|
||||||
FBResult result = await s.LoginAsync();
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DidGetAllRequestedPermissions(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
FBAccessTokenData data = FBSession.ActiveSession.AccessTokenData;
|
||||||
|
uint grantedCount = 0;
|
||||||
|
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
for (uint i = 0; i < requested_permissions.Length; i++)
|
||||||
|
{
|
||||||
|
string perm = requested_permissions[i];
|
||||||
|
if ((data.Permissions != null) && (data.Permissions.ContainsKey(perm)))
|
||||||
|
{
|
||||||
|
string Value = data.Permissions[perm];
|
||||||
|
if (string.CompareOrdinal(Value, PermissionGranted) == 0)
|
||||||
|
{
|
||||||
|
grantedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grantedCount == requested_permissions.Length)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WasAppPermissionRemovedByUser(
|
||||||
|
FBResult Result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ((Result != null) &&
|
||||||
|
(!Result.Succeeded) &&
|
||||||
|
(Result.ErrorInfo.Code == (int)Facebook.ErrorCode.ErrorCodeOauthException));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShouldRerequest(
|
||||||
|
FBResult Result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ((Result != null) &&
|
||||||
|
Result.Succeeded &&
|
||||||
|
!DidGetAllRequestedPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task TryRerequest(
|
||||||
|
bool Retry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// If we're logged out, the session has cleared the FB and Windows app IDs,
|
||||||
|
// so they need to be set again. We load these IDs via the ResourceLoader
|
||||||
|
// class, which must be accessed on the UI thread, which is why this call
|
||||||
|
// is outside the task context.
|
||||||
|
SetSessionAppIds();
|
||||||
|
|
||||||
|
FBResult result = await FBSession.ActiveSession.LoginAsync(BuildPermissions());
|
||||||
|
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
if (Retry && (!DidGetAllRequestedPermissions()))
|
||||||
|
{
|
||||||
|
await TryRerequest(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Navigate back to same page, to clear out logged in info.
|
||||||
|
App.RootFrame.Navigate(typeof(UserInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -127,7 +216,27 @@ namespace LoginCs
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LoginButton.Content = "Logout";
|
LoginButton.Content = "Logout";
|
||||||
StartLogin();
|
|
||||||
|
FBResult result = await sess.LoginAsync(BuildPermissions());
|
||||||
|
|
||||||
|
// There may be other cases where an a failed login request should
|
||||||
|
// prompt the app to retry login, but this one is common enough that
|
||||||
|
// it's helpful to demonstrate handling it here. If the predicate
|
||||||
|
// returns TRUE, the user has gone to facebook.com in the browser,
|
||||||
|
// and removed our app from their list off allowed apps in Settings.
|
||||||
|
if (WasAppPermissionRemovedByUser(result))
|
||||||
|
{
|
||||||
|
await sess.Logout();
|
||||||
|
}
|
||||||
|
else if (ShouldRerequest(result))
|
||||||
|
{
|
||||||
|
await TryRerequest(false);
|
||||||
|
}
|
||||||
|
else if (result.Succeeded)
|
||||||
|
{
|
||||||
|
//Navigate back to same page, to clear out logged in info.
|
||||||
|
App.RootFrame.Navigate(typeof(UserInfo));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче