mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-10 15:19:21 +02:00
Merge pull request #16555 from zfox23/DEV-2858
DEV-2858: White screen displayed when using screenshare
This commit is contained in:
commit
9dc1167e73
6 changed files with 108 additions and 30 deletions
|
@ -3616,28 +3616,18 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMes
|
|||
}
|
||||
|
||||
void DomainServer::processAvatarZonePresencePacket(QSharedPointer<ReceivedMessage> message) {
|
||||
QUuid avatar = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
QUuid avatarID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
QUuid zoneID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
if (avatar.isNull()) {
|
||||
if (avatarID.isNull()) {
|
||||
qCWarning(domain_server) << "Ignoring null avatar presence";
|
||||
return;
|
||||
}
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
auto matchingNode = limitedNodeList->nodeWithUUID(avatar);
|
||||
if (!matchingNode) {
|
||||
qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar" << avatar;
|
||||
return;
|
||||
}
|
||||
QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName();
|
||||
if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in.
|
||||
return;
|
||||
}
|
||||
static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60;
|
||||
screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, SCREENSHARE_EXPIRATION_SECONDS);
|
||||
screensharePresence(zoneID.isNull() ? "" : zoneID.toString(), avatarID, SCREENSHARE_EXPIRATION_SECONDS);
|
||||
}
|
||||
|
||||
void DomainServer::screensharePresence(QString roomname, QString username, int expirationSeconds) {
|
||||
void DomainServer::screensharePresence(QString roomname, QUuid avatarID, int expirationSeconds) {
|
||||
if (!DependencyManager::get<AccountManager>()->hasValidAccessToken()) {
|
||||
static std::once_flag presenceAuthorityWarning;
|
||||
std::call_once(presenceAuthorityWarning, [] {
|
||||
|
@ -3645,14 +3635,33 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
|
|||
});
|
||||
return;
|
||||
}
|
||||
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
auto matchingNode = limitedNodeList->nodeWithUUID(avatarID);
|
||||
if (!matchingNode) {
|
||||
qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar ID" << avatarID;
|
||||
return;
|
||||
}
|
||||
QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName();
|
||||
if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in.
|
||||
return;
|
||||
}
|
||||
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.callbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence";
|
||||
callbackParams.errorCallbackMethod = "handleFailedScreensharePresence";
|
||||
// Construct `callbackData`, which is data that will be available to the callback functions.
|
||||
// In this case, the "success" callback needs access to the "roomname" (the zone ID) and the
|
||||
// relevant avatar's UUID.
|
||||
QJsonObject callbackData;
|
||||
callbackData.insert("roomname", roomname);
|
||||
callbackData.insert("avatarID", avatarID.toString());
|
||||
callbackParams.callbackData = callbackData;
|
||||
const QString PATH = "api/v1/domains/%1/screenshare";
|
||||
QString domain_id = uuidStringWithoutCurlyBraces(getID());
|
||||
QJsonObject json, screenshare;
|
||||
screenshare["username"] = username;
|
||||
screenshare["username"] = verifiedUsername;
|
||||
screenshare["roomname"] = roomname;
|
||||
if (expirationSeconds > 0) {
|
||||
screenshare["expiration"] = expirationSeconds;
|
||||
|
@ -3666,11 +3675,18 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
|
|||
);
|
||||
}
|
||||
|
||||
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply) {
|
||||
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData) {
|
||||
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
|
||||
if (jsonObject["status"].toString() != "success") {
|
||||
qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the client that we just authorized to screenshare which zone ID in which they are authorized to screenshare.
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
auto packet = NLPacket::create(PacketType::AvatarZonePresence, NUM_BYTES_RFC4122_UUID, true);
|
||||
packet->write(QUuid(callbackData["roomname"].toString()).toRfc4122());
|
||||
nodeList->sendPacket(std::move(packet), *(nodeList->nodeWithUUID(QUuid(callbackData["avatarID"].toString()))));
|
||||
}
|
||||
|
||||
void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) {
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
bool isAssetServerEnabled();
|
||||
|
||||
void screensharePresence(QString roomname, QString username, int expiration_seconds = 0);
|
||||
void screensharePresence(QString roomname, QUuid avatarID, int expiration_seconds = 0);
|
||||
|
||||
public slots:
|
||||
/// Called by NodeList to inform us a node has been added
|
||||
|
@ -132,7 +132,7 @@ private slots:
|
|||
void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply);
|
||||
void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply);
|
||||
|
||||
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply);
|
||||
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData);
|
||||
void handleFailedScreensharePresence(QNetworkReply* requestReply);
|
||||
|
||||
void updateReplicatedNodes();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <NodeList.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
|
@ -37,14 +38,48 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
|
|||
_requestScreenshareInfoRetryTimer->setSingleShot(true);
|
||||
_requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS);
|
||||
connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo);
|
||||
|
||||
// This packet listener handles the packet containing information about the latest zone ID in which we are allowed to share.
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient");
|
||||
};
|
||||
|
||||
ScreenshareScriptingInterface::~ScreenshareScriptingInterface() {
|
||||
stopScreenshare();
|
||||
}
|
||||
|
||||
void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message) {
|
||||
QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
if (zone.isNull()) {
|
||||
qWarning() << "Ignoring avatar zone presence packet that doesn't specify a zone.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the last known authorized screenshare zone ID to the zone that the Domain Server just told us about.
|
||||
_lastAuthorizedZoneID = zone;
|
||||
|
||||
// If we had previously started the screenshare process but knew that we weren't going to be authorized to screenshare,
|
||||
// let's continue the screenshare process here.
|
||||
if (_waitingForAuthorization) {
|
||||
requestScreenshareInfo();
|
||||
}
|
||||
}
|
||||
|
||||
static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5;
|
||||
void ScreenshareScriptingInterface::requestScreenshareInfo() {
|
||||
// If the screenshare zone that we're currently in (i.e. `startScreenshare()` was called) is different from
|
||||
// the zone in which we are authorized to screenshare...
|
||||
// ...return early here and wait for the DS to send us a packet containing this zone's ID.
|
||||
if (_screenshareZoneID != _lastAuthorizedZoneID) {
|
||||
qDebug() << "Client not yet authorized to screenshare. Waiting for authorization message from domain server...";
|
||||
_waitingForAuthorization = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_waitingForAuthorization = false;
|
||||
|
||||
_requestScreenshareInfoRetries++;
|
||||
|
||||
if (_requestScreenshareInfoRetries >= MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES) {
|
||||
|
@ -174,6 +209,7 @@ void ScreenshareScriptingInterface::stopScreenshare() {
|
|||
_projectAPIKey = "";
|
||||
_sessionID = "";
|
||||
_isPresenter = false;
|
||||
_waitingForAuthorization = false;
|
||||
}
|
||||
|
||||
// Called when the Metaverse returns the information necessary to start/view a screen share.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QNetworkReply>
|
||||
|
||||
#include <PathUtils.h>
|
||||
#include <ReceivedMessage.h>
|
||||
|
||||
class ScreenshareScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -36,6 +37,7 @@ signals:
|
|||
void localWebEntityZOffsetChanged(const float& newZOffset);
|
||||
|
||||
private slots:
|
||||
void processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message);
|
||||
void onWebEventReceived(const QUuid& entityID, const QVariant& message);
|
||||
void handleSuccessfulScreenshareInfoGet(QNetworkReply* reply);
|
||||
void handleFailedScreenshareInfoGet(QNetworkReply* reply);
|
||||
|
@ -82,6 +84,9 @@ private:
|
|||
QUuid _screenshareZoneID;
|
||||
QUuid _smartboardEntityID;
|
||||
bool _isPresenter{ false };
|
||||
|
||||
QUuid _lastAuthorizedZoneID;
|
||||
bool _waitingForAuthorization{ false };
|
||||
};
|
||||
|
||||
#endif // hifi_ScreenshareScriptingInterface_h
|
||||
|
|
|
@ -52,11 +52,13 @@ const int PULL_SETTINGS_RETRY_INTERVAL = 2 * MSECS_PER_SECOND;
|
|||
const int MAX_PULL_RETRIES = 10;
|
||||
|
||||
JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver,
|
||||
const QString& jsonCallbackMethod,
|
||||
const QString& errorCallbackMethod) :
|
||||
const QString& jsonCallbackMethod,
|
||||
const QString& errorCallbackMethod,
|
||||
const QJsonObject& callbackData) :
|
||||
callbackReceiver(callbackReceiver),
|
||||
jsonCallbackMethod(jsonCallbackMethod),
|
||||
errorCallbackMethod(errorCallbackMethod)
|
||||
errorCallbackMethod(errorCallbackMethod),
|
||||
callbackData(callbackData)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -348,9 +350,17 @@ void AccountManager::sendRequest(const QString& path,
|
|||
[callbackParams, networkReply] {
|
||||
if (networkReply->error() == QNetworkReply::NoError) {
|
||||
if (!callbackParams.jsonCallbackMethod.isEmpty()) {
|
||||
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.jsonCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply));
|
||||
bool invoked = false;
|
||||
if (callbackParams.callbackData.isEmpty()) {
|
||||
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.jsonCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply));
|
||||
} else {
|
||||
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.jsonCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply),
|
||||
Q_ARG(QJsonObject, callbackParams.callbackData));
|
||||
}
|
||||
|
||||
if (!invoked) {
|
||||
QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* "
|
||||
|
@ -366,9 +376,18 @@ void AccountManager::sendRequest(const QString& path,
|
|||
}
|
||||
} else {
|
||||
if (!callbackParams.errorCallbackMethod.isEmpty()) {
|
||||
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.errorCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply));
|
||||
bool invoked = false;
|
||||
if (callbackParams.callbackData.isEmpty()) {
|
||||
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.errorCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply));
|
||||
}
|
||||
else {
|
||||
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||
qPrintable(callbackParams.errorCallbackMethod),
|
||||
Q_ARG(QNetworkReply*, networkReply),
|
||||
Q_ARG(QJsonObject, callbackParams.callbackData));
|
||||
}
|
||||
|
||||
if (!invoked) {
|
||||
QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* "
|
||||
|
|
|
@ -30,14 +30,16 @@
|
|||
class JSONCallbackParameters {
|
||||
public:
|
||||
JSONCallbackParameters(QObject* callbackReceiver = nullptr,
|
||||
const QString& jsonCallbackMethod = QString(),
|
||||
const QString& errorCallbackMethod = QString());
|
||||
const QString& jsonCallbackMethod = QString(),
|
||||
const QString& errorCallbackMethod = QString(),
|
||||
const QJsonObject& callbackData = QJsonObject());
|
||||
|
||||
bool isEmpty() const { return !callbackReceiver; }
|
||||
|
||||
QObject* callbackReceiver;
|
||||
QString jsonCallbackMethod;
|
||||
QString errorCallbackMethod;
|
||||
QJsonObject callbackData;
|
||||
};
|
||||
|
||||
namespace AccountManagerAuth {
|
||||
|
|
Loading…
Reference in a new issue