Interface login through steam

This commit is contained in:
Atlante45 2016-07-14 11:02:32 -07:00
parent 45921a5c8d
commit cea0e182c0
10 changed files with 275 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -203,24 +203,48 @@ ScrollingWindow {
}
}
Rectangle {
Row {
width: loginDialog.inputWidth
height: loginDialog.inputHeight
radius: height / 2
color: "#353535"
TextInput {
anchors.fill: parent
text: "Login"
color: "white"
horizontalAlignment: Text.AlignHCenter
Rectangle {
width: loginDialog.inputWidth / 3
height: loginDialog.inputHeight
radius: height / 2
color: "#353535"
TextInput {
anchors.fill: parent
text: "Login"
color: "white"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
loginDialog.login(username.text, password.text)
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
loginDialog.login(username.text, password.text)
Image {
source: "../images/steam-sign-in.png"
width: loginDialog.inputWidth / 3
height: loginDialog.inputHeight
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
leftMargin: loginDialog.inputHeight / 4
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
loginDialog.loginThroughSteam()
}
}
}
}

View file

@ -86,15 +86,16 @@
#include <PhysicsHelpers.h>
#include <plugins/PluginManager.h>
#include <plugins/CodecPlugin.h>
#include <RecordingScriptingInterface.h>
#include <RenderableWebEntityItem.h>
#include <RenderShadowTask.h>
#include <RenderDeferredTask.h>
#include <ResourceCache.h>
#include <SceneScriptingInterface.h>
#include <RecordingScriptingInterface.h>
#include <ScriptEngines.h>
#include <ScriptCache.h>
#include <SoundCache.h>
#include <ScriptEngines.h>
#include <steamworks-wrapper/SteamClient.h>
#include <Tooltip.h>
#include <udt/PacketHeaders.h>
#include <UserActivityLogger.h>
@ -2910,6 +2911,8 @@ void Application::idle(float nsecsElapsed) {
PROFILE_RANGE(__FUNCTION__);
SteamClient::runCallbacks();
float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND;
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.

View file

@ -8,6 +8,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <thread>
#include <QCommandLineParser>
#include <QDebug>
#include <QDir>
@ -20,12 +22,13 @@
#include <gl/OpenGLVersionChecker.h>
#include <SharedUtil.h>
#include <steamworks-wrapper/SteamClient.h>
#include "AddressManager.h"
#include "Application.h"
#include "InterfaceLogging.h"
#include "UserActivityLogger.h"
#include "MainWindow.h"
#include <thread>
#ifdef HAS_BUGSPLAT
#include <BuildInfo.h>
@ -137,6 +140,8 @@ int main(int argc, const char* argv[]) {
// or in the main window ctor, before GL startup.
Application::initPlugins(arguments);
SteamClient::init();
int exitCode;
{
QSettings::setDefaultFormat(QSettings::IniFormat);
@ -202,6 +207,8 @@ int main(int argc, const char* argv[]) {
Application::shutdownPlugins();
SteamClient::shutdown();
qCDebug(interfaceapp, "Normal exit.");
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
// HACK: exit immediately (don't handle shutdown callbacks) for Release build

View file

@ -14,6 +14,7 @@
#include <QDesktopServices>
#include <NetworkingConstants.h>
#include <steamworks-wrapper/SteamClient.h>
#include "AccountManager.h"
#include "DependencyManager.h"
@ -82,6 +83,20 @@ void LoginDialog::login(const QString& username, const QString& password) {
DependencyManager::get<AccountManager>()->requestAccessToken(username, password);
}
void LoginDialog::loginThroughSteam() {
qDebug() << "Attempting to login through Steam";
setStatusText("Logging in...");
SteamClient::requestTicket([this](Ticket ticket) {
if (ticket.isNull()) {
setStatusText("Steam client not logged into an account");
return;
}
DependencyManager::get<AccountManager>()->requestAccessTokenWithSteam(ticket);
});
}
void LoginDialog::openUrl(const QString& url) {
qDebug() << url;
QDesktopServices::openUrl(url);

View file

@ -41,6 +41,7 @@ protected:
void handleLoginFailed();
Q_INVOKABLE void login(const QString& username, const QString& password);
Q_INVOKABLE void loginThroughSteam();
Q_INVOKABLE void openUrl(const QString& url);
private:
QString _statusText;

View file

@ -505,6 +505,29 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
}
void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request;
request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter());
QUrl grantURL = _authURL;
grantURL.setPath("/oauth/token");
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
QByteArray postData;
postData.append("grant_type=password&");
postData.append("ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&");
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
request.setUrl(grantURL);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = networkAccessManager.post(request, postData);
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished);
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
}
void AccountManager::requestAccessTokenFinished() {
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());

View file

@ -96,6 +96,7 @@ public:
public slots:
void requestAccessToken(const QString& login, const QString& password);
void requestAccessTokenWithSteam(QByteArray authSessionTicket);
void requestAccessTokenFinished();
void requestProfileFinished();

View file

@ -11,9 +11,180 @@
#include "SteamClient.h"
#include <atomic>
#include <memory>
#include <QtCore/QDebug>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#endif
#include <steam/steam_api.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
static const Ticket INVALID_TICKET = Ticket();
class SteamTicketRequests {
public:
SteamTicketRequests();
~SteamTicketRequests();
HAuthTicket startRequest(TicketRequestCallback callback);
void stopRequest(HAuthTicket authTicket);
STEAM_CALLBACK(SteamTicketRequests, onGetAuthSessionTicketResponse,
GetAuthSessionTicketResponse_t, _getAuthSessionTicketResponse);
private:
void stopAll();
struct PendingTicket {
HAuthTicket authTicket;
Ticket ticket;
TicketRequestCallback callback;
};
std::vector<PendingTicket> _pendingTickets;
};
SteamTicketRequests::SteamTicketRequests() :
_getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse)
{
}
SteamTicketRequests::~SteamTicketRequests() {
stopAll();
}
HAuthTicket SteamTicketRequests::startRequest(TicketRequestCallback callback) {
static const uint32 MAX_TICKET_SIZE { 1024 };
uint32 ticketSize { 0 };
char ticket[MAX_TICKET_SIZE];
auto authTicket = SteamUser()->GetAuthSessionTicket(ticket, MAX_TICKET_SIZE, &ticketSize);
qDebug() << "Got Steam auth session ticket:" << authTicket;
if (authTicket == k_HAuthTicketInvalid) {
qWarning() << "Auth session ticket is invalid.";
callback(INVALID_TICKET);
} else {
PendingTicket pendingTicket{ authTicket, QByteArray(ticket, ticketSize).toHex(), callback };
_pendingTickets.push_back(pendingTicket);
}
return authTicket;
}
void SteamTicketRequests::stopRequest(HAuthTicket authTicket) {
auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) {
return pendingTicket.authTicket == authTicket;
});
if (it != _pendingTickets.end()) {
SteamUser()->CancelAuthTicket(it->authTicket);
it->callback(INVALID_TICKET);
_pendingTickets.erase(it);
}
}
void SteamTicketRequests::stopAll() {
auto steamUser = SteamUser();
if (steamUser) {
for (const auto& pendingTicket : _pendingTickets) {
steamUser->CancelAuthTicket(pendingTicket.authTicket);
pendingTicket.callback(INVALID_TICKET);
}
}
_pendingTickets.clear();
}
void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketResponse_t* pCallback) {
auto authTicket = pCallback->m_hAuthTicket;
auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) {
return pendingTicket.authTicket == authTicket;
});
if (it != _pendingTickets.end()) {
if (pCallback->m_eResult == k_EResultOK) {
qDebug() << "Got steam callback, auth session ticket is valid. Send it." << authTicket;
it->callback(it->ticket);
} else {
qWarning() << "Steam auth session ticket callback encountered an error:" << pCallback->m_eResult;
it->callback(INVALID_TICKET);
}
_pendingTickets.erase(it);
} else {
qWarning() << "Could not find steam auth session ticket in list of pending tickets:" << authTicket;
}
}
static std::atomic_bool initialized { false };
static std::unique_ptr<SteamTicketRequests> steamTicketRequests;
bool SteamClient::init() {
if (!initialized) {
initialized = SteamAPI_Init();
}
if (!steamTicketRequests && initialized) {
steamTicketRequests.reset(new SteamTicketRequests());
}
return initialized;
}
void SteamClient::shutdown() {
if (initialized) {
SteamAPI_Shutdown();
}
if (steamTicketRequests) {
steamTicketRequests.reset();
}
}
void SteamClient::runCallbacks() {
if (!initialized) {
init();
}
if (!initialized) {
qDebug() << "Steam not initialized";
return;
}
auto steamPipe = SteamAPI_GetHSteamPipe();
if (!steamPipe) {
qDebug() << "Could not get SteamPipe";
return;
}
Steam_RunCallbacks(steamPipe, false);
}
void SteamClient::requestTicket(TicketRequestCallback callback) {
if (!initialized) {
init();
}
if (!initialized) {
qDebug() << "Steam not initialized";
return;
}
steamTicketRequests->startRequest(callback);
}

View file

@ -13,8 +13,21 @@
#ifndef hifi_SteamClient_h
#define hifi_SteamClient_h
class SteamClient {
#include <functional>
#include <QtCore/QByteArray>
using Ticket = QByteArray;
using TicketRequestCallback = std::function<void(Ticket)>;
class SteamClient {
public:
static bool init();
static void shutdown();
static void runCallbacks();
static void requestTicket(TicketRequestCallback callback);
};