diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 0455377d89..4fc8975262 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -51,6 +51,8 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri LogUtils::init(); QSettings::setDefaultFormat(QSettings::IniFormat); + + DependencyManager::set(); auto scriptableAvatar = DependencyManager::set(); auto addressManager = DependencyManager::set(); @@ -116,7 +118,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connections to AccountManager for authentication - connect(&AccountManager::getInstance(), &AccountManager::authRequired, + connect(DependencyManager::get().data(), &AccountManager::authRequired, this, &AssignmentClient::handleAuthenticationRequest); // Create Singleton objects on main thread @@ -309,13 +311,13 @@ void AssignmentClient::handleAuthenticationRequest() { QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV); QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV); - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); if (!username.isEmpty() && !password.isEmpty()) { // ask the account manager to log us in from the env variables - accountManager.requestAccessToken(username, password); + accountManager->requestAccessToken(username, password); } else { - qCWarning(assigmnentclient) << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString()) + qCWarning(assigmnentclient) << "Authentication was requested against" << qPrintable(accountManager->getAuthURL().toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) << "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate."; diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 94e79416a5..919ac37ee9 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -485,7 +485,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username) { qDebug() << "Requesting public key for user" << username; - AccountManager::getInstance().sendRequest(USER_PUBLIC_KEY_PATH.arg(username), + DependencyManager::get()->sendRequest(USER_PUBLIC_KEY_PATH.arg(username), AccountManagerAuth::None, QNetworkAccessManager::GetOperation, callbackParams); } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index a5c485ebe2..0aab6b7e31 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -77,7 +78,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : // make sure we have a fresh AccountManager instance // (need this since domain-server can restart itself and maintain static variables) - AccountManager::getInstance(true); + DependencyManager::set(); auto args = arguments(); @@ -195,8 +196,8 @@ bool DomainServer::optionallySetupOAuth() { _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL; } - AccountManager& accountManager = AccountManager::getInstance(); - accountManager.setAuthURL(_oauthProviderURL); + auto accountManager = DependencyManager::get(); + accountManager->setAuthURL(_oauthProviderURL); _oauthClientID = settingsMap.value(OAUTH_CLIENT_ID_OPTION).toString(); _oauthClientSecret = QProcessEnvironment::systemEnvironment().value(OAUTH_CLIENT_SECRET_ENV); @@ -239,7 +240,7 @@ void DomainServer::optionallyGetTemporaryName(const QStringList& arguments) { // we've been asked to grab a temporary name from the API // so fire off that request now - auto& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); // get callbacks for temporary domain result JSONCallbackParameters callbackParameters; @@ -248,8 +249,8 @@ void DomainServer::optionallyGetTemporaryName(const QStringList& arguments) { callbackParameters.errorCallbackReceiver = this; callbackParameters.errorCallbackMethod = "handleTempDomainError"; - accountManager.sendRequest("/api/v1/domains/temporary", AccountManagerAuth::None, - QNetworkAccessManager::PostOperation, callbackParameters); + accountManager->sendRequest("/api/v1/domains/temporary", AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, callbackParameters); } } @@ -397,7 +398,7 @@ bool DomainServer::resetAccountManagerAccessToken() { << "at keypath metaverse.access_token or in your ENV at key DOMAIN_SERVER_ACCESS_TOKEN"; // clear any existing access token from AccountManager - AccountManager::getInstance().setAccessTokenForCurrentAuthURL(QString()); + DependencyManager::get()->setAccessTokenForCurrentAuthURL(QString()); return false; } @@ -407,7 +408,7 @@ bool DomainServer::resetAccountManagerAccessToken() { } // give this access token to the AccountManager - AccountManager::getInstance().setAccessTokenForCurrentAuthURL(accessToken); + DependencyManager::get()->setAccessTokenForCurrentAuthURL(accessToken); return true; @@ -499,17 +500,17 @@ void DomainServer::setupICEHeartbeatForFullNetworking() { limitedNodeList->startSTUNPublicSocketUpdate(); // to send ICE heartbeats we'd better have a private key locally with an uploaded public key - auto& accountManager = AccountManager::getInstance(); - auto domainID = accountManager.getAccountInfo().getDomainID(); + auto accountManager = DependencyManager::get(); + auto domainID = accountManager->getAccountInfo().getDomainID(); // if we have an access token and we don't have a private key or the current domain ID has changed // we should generate a new keypair - if (!accountManager.getAccountInfo().hasPrivateKey() || domainID != limitedNodeList->getSessionUUID()) { - accountManager.generateNewDomainKeypair(limitedNodeList->getSessionUUID()); + if (!accountManager->getAccountInfo().hasPrivateKey() || domainID != limitedNodeList->getSessionUUID()) { + accountManager->generateNewDomainKeypair(limitedNodeList->getSessionUUID()); } // hookup to the signal from account manager that tells us when keypair is available - connect(&accountManager, &AccountManager::newKeypair, this, &DomainServer::handleKeypairChange); + connect(accountManager.data(), &AccountManager::newKeypair, this, &DomainServer::handleKeypairChange); if (!_iceHeartbeatTimer) { // setup a timer to heartbeat with the ice-server every so often @@ -962,9 +963,9 @@ void DomainServer::setupPendingAssignmentCredits() { void DomainServer::sendPendingTransactionsToServer() { - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); - if (accountManager.hasValidAccessToken()) { + if (accountManager->hasValidAccessToken()) { // enumerate the pending transactions and send them to the server to complete payment TransactionHash::iterator i = _pendingAssignmentCredits.begin(); @@ -975,7 +976,7 @@ void DomainServer::sendPendingTransactionsToServer() { transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback"; while (i != _pendingAssignmentCredits.end()) { - accountManager.sendRequest("api/v1/transactions", + accountManager->sendRequest("api/v1/transactions", AccountManagerAuth::Required, QNetworkAccessManager::PostOperation, transactionCallbackParams, i.value()->postJson().toJson()); @@ -1073,7 +1074,7 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson())); - AccountManager::getInstance().sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), + DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Required, QNetworkAccessManager::PutOperation, JSONCallbackParameters(), @@ -1103,7 +1104,7 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() { static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address"; - AccountManager::getInstance().sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), + DependencyManager::get()->sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, callbackParameters, @@ -1123,15 +1124,15 @@ void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestRepl void DomainServer::sendHeartbeatToIceServer() { if (!_iceServerSocket.getAddress().isNull()) { - auto& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); auto limitedNodeList = DependencyManager::get(); - if (!accountManager.getAccountInfo().hasPrivateKey()) { + if (!accountManager->getAccountInfo().hasPrivateKey()) { qWarning() << "Cannot send an ice-server heartbeat without a private key for signature."; qWarning() << "Waiting for keypair generation to complete before sending ICE heartbeat."; if (!limitedNodeList->getSessionUUID().isNull()) { - accountManager.generateNewDomainKeypair(limitedNodeList->getSessionUUID()); + accountManager->generateNewDomainKeypair(limitedNodeList->getSessionUUID()); } else { qWarning() << "Attempting to send ICE server heartbeat with no domain ID. This is not supported"; } @@ -1208,7 +1209,7 @@ void DomainServer::sendHeartbeatToIceServer() { auto plaintext = QByteArray::fromRawData(_iceServerHeartbeatPacket->getPayload(), _iceServerHeartbeatPacket->getPayloadSize()); // generate a signature for the plaintext data in the packet - auto signature = accountManager.getAccountInfo().signPlaintext(plaintext); + auto signature = accountManager->getAccountInfo().signPlaintext(plaintext); // pack the signature with the data heartbeatDataStream << signature; @@ -2101,7 +2102,7 @@ void DomainServer::processICEServerHeartbeatDenialPacket(QSharedPointer(); - AccountManager::getInstance().generateNewDomainKeypair(limitedNodeList->getSessionUUID()); + DependencyManager::get()->generateNewDomainKeypair(limitedNodeList->getSessionUUID()); // reset our number of heartbeat denials _numHeartbeatDenials = 0; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5f08877ae2..9ad24526c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -402,6 +402,7 @@ bool setupEssentials(int& argc, char** argv) { Setting::init(); // Set dependencies + DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -656,15 +657,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch); // connect to appropriate slots on AccountManager - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); auto dialogsManager = DependencyManager::get(); - connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); - connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); + connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); + connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle); // set the account manager's root URL and trigger a login request if we don't have the access token - accountManager.setIsAgent(true); - accountManager.setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. @@ -1057,6 +1058,38 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : firstRun.set(false); } +QString Application::getUserAgent() { + if (QThread::currentThread() != thread()) { + QString userAgent; + + QMetaObject::invokeMethod(this, "getUserAgent", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userAgent)); + + return userAgent; + } + + QString userAgent = "Mozilla/5.0 (HighFidelityInterface/" + BuildInfo::VERSION + "; " + + QSysInfo::productType() + " " + QSysInfo::productVersion() + ")"; + + auto formatPluginName = [](QString name) -> QString { return name.trimmed().replace(" ", "-"); }; + + // For each plugin, add to userAgent + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); + for (auto& dp : displayPlugins) { + if (dp->isActive() && dp->isHmd()) { + userAgent += " " + formatPluginName(dp->getName()); + } + } + auto inputPlugins= PluginManager::getInstance()->getInputPlugins(); + for (auto& ip : inputPlugins) { + if (ip->isActive()) { + userAgent += " " + formatPluginName(ip->getName()); + } + } + + return userAgent; +} + + void Application::checkChangeCursor() { QMutexLocker locker(&_changeCursorLock); @@ -4135,7 +4168,7 @@ void Application::updateWindowTitle() const { auto nodeList = DependencyManager::get(); QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; - QString username = AccountManager::getInstance().getAccountInfo().getUsername(); + QString username = DependencyManager::get()->getAccountInfo().getUsername(); QString currentPlaceName = DependencyManager::get()->getHost(); if (currentPlaceName.isEmpty()) { @@ -4775,8 +4808,8 @@ void Application::takeSnapshot() { QString fileName = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); - AccountManager& accountManager = AccountManager::getInstance(); - if (!accountManager.isLoggedIn()) { + auto accountManager = DependencyManager::get(); + if (!accountManager->isLoggedIn()) { return; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 558190c8d1..5616722c92 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -112,6 +112,9 @@ public: QString getPreviousScriptLocation(); void setPreviousScriptLocation(const QString& previousScriptLocation); + // Return an HTTP User-Agent string with OS and device information. + Q_INVOKABLE QString getUserAgent(); + void initializeGL(); void initializeUi(); void paintGL(); diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index a8b0a265c9..83f87f82ba 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -35,9 +35,9 @@ const QString API_USER_HEARTBEAT_PATH = "/api/v1/user/heartbeat"; const QString SESSION_ID_KEY = "session_id"; void DiscoverabilityManager::updateLocation() { - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); - if (_mode.get() != Discoverability::None && accountManager.isLoggedIn()) { + if (_mode.get() != Discoverability::None && accountManager->isLoggedIn()) { auto addressManager = DependencyManager::get(); DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); @@ -98,7 +98,7 @@ void DiscoverabilityManager::updateLocation() { apiPath = API_USER_LOCATION_PATH; } - accountManager.sendRequest(apiPath, AccountManagerAuth::Required, + accountManager->sendRequest(apiPath, AccountManagerAuth::Required, QNetworkAccessManager::PutOperation, callbackParameters, QJsonDocument(rootObject).toJson()); @@ -116,7 +116,7 @@ void DiscoverabilityManager::updateLocation() { heartbeatObject[SESSION_ID_KEY] = QJsonValue(); } - accountManager.sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, + accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, callbackParameters, QJsonDocument(heartbeatObject).toJson()); } @@ -131,8 +131,8 @@ void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply } void DiscoverabilityManager::removeLocation() { - AccountManager& accountManager = AccountManager::getInstance(); - accountManager.sendRequest(API_USER_LOCATION_PATH, AccountManagerAuth::Required, QNetworkAccessManager::DeleteOperation); + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(API_USER_LOCATION_PATH, AccountManagerAuth::Required, QNetworkAccessManager::DeleteOperation); } void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discoverabilityMode) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 05bb03bf86..8b69bb8022 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -54,7 +54,7 @@ Menu* Menu::getInstance() { Menu::Menu() { auto dialogsManager = DependencyManager::get(); - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); // File/Application menu ---------------------------------- MenuWrapper* fileMenu = addMenu("File"); @@ -64,9 +64,9 @@ Menu::Menu() { addActionToQMenuAndActionHash(fileMenu, MenuOption::Login); // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item - connect(&accountManager, &AccountManager::profileChanged, + connect(accountManager.data(), &AccountManager::profileChanged, dialogsManager.data(), &DialogsManager::toggleLoginDialog); - connect(&accountManager, &AccountManager::logoutComplete, + connect(accountManager.data(), &AccountManager::logoutComplete, dialogsManager.data(), &DialogsManager::toggleLoginDialog); } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 1726d47045..13f9470fda 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -144,11 +144,11 @@ int main(int argc, const char* argv[]) { // If we failed the OpenGLVersion check, log it. if (override) { - auto& accountManager = AccountManager::getInstance(); - if (accountManager.isLoggedIn()) { + auto accountManager = DependencyManager::get(); + if (accountManager->isLoggedIn()) { UserActivityLogger::getInstance().insufficientGLVersion(glData); } else { - QObject::connect(&AccountManager::getInstance(), &AccountManager::loginComplete, [glData](){ + QObject::connect(accountManager.data(), &AccountManager::loginComplete, [glData](){ static bool loggedInsufficientGL = false; if (!loggedInsufficientGL) { UserActivityLogger::getInstance().insufficientGLVersion(glData); @@ -168,9 +168,9 @@ int main(int argc, const char* argv[]) { QObject::connect(&server, &QLocalServer::newConnection, &app, &Application::handleLocalServerConnection, Qt::DirectConnection); #ifdef HAS_BUGSPLAT - AccountManager& accountManager = AccountManager::getInstance(); - crashReporter.mpSender.setDefaultUserName(qPrintable(accountManager.getAccountInfo().getUsername())); - QObject::connect(&accountManager, &AccountManager::usernameChanged, &app, [&crashReporter](const QString& newUsername) { + auto accountManager = DependencyManager::get(); + crashReporter.mpSender.setDefaultUserName(qPrintable(accountManager->getAccountInfo().getUsername())); + QObject::connect(accountManager.data(), &AccountManager::usernameChanged, &app, [&crashReporter](const QString& newUsername) { crashReporter.mpSender.setDefaultUserName(qPrintable(newUsername)); }); diff --git a/interface/src/scripting/AccountScriptingInterface.cpp b/interface/src/scripting/AccountScriptingInterface.cpp index 1b6d52ac2a..1328197195 100644 --- a/interface/src/scripting/AccountScriptingInterface.cpp +++ b/interface/src/scripting/AccountScriptingInterface.cpp @@ -19,14 +19,14 @@ AccountScriptingInterface* AccountScriptingInterface::getInstance() { } bool AccountScriptingInterface::isLoggedIn() { - AccountManager& accountManager = AccountManager::getInstance(); - return accountManager.isLoggedIn(); + auto accountManager = DependencyManager::get(); + return accountManager->isLoggedIn(); } QString AccountScriptingInterface::getUsername() { - AccountManager& accountManager = AccountManager::getInstance(); - if (accountManager.isLoggedIn()) { - return accountManager.getAccountInfo().getUsername(); + auto accountManager = DependencyManager::get(); + if (accountManager->isLoggedIn()) { + return accountManager->getAccountInfo().getUsername(); } else { return "Unknown user"; } diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index e8d63a6d99..d7e5bae3f8 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -17,10 +17,10 @@ #include "GlobalServicesScriptingInterface.h" GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { - AccountManager& accountManager = AccountManager::getInstance(); - connect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); - connect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); - connect(&accountManager, &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected); + auto accountManager = DependencyManager::get(); + connect(accountManager.data(), &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); + connect(accountManager.data(), &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); + connect(accountManager.data(), &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected); _downloading = false; QTimer* checkDownloadTimer = new QTimer(this); @@ -34,10 +34,10 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { } GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { - AccountManager& accountManager = AccountManager::getInstance(); - disconnect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); - disconnect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); - disconnect(&accountManager, &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected); + auto accountManager = DependencyManager::get(); + disconnect(accountManager.data(), &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); + disconnect(accountManager.data(), &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); + disconnect(accountManager.data(), &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected); } GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() { @@ -46,7 +46,7 @@ GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance( } const QString& GlobalServicesScriptingInterface::getUsername() const { - return AccountManager::getInstance().getAccountInfo().getUsername(); + return DependencyManager::get()->getAccountInfo().getUsername(); } void GlobalServicesScriptingInterface::loggedOut() { diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 60d19df355..80d52b7a07 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -24,14 +24,15 @@ HIFI_QML_DEF(LoginDialog) LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { - connect(&AccountManager::getInstance(), &AccountManager::loginComplete, + auto accountManager = DependencyManager::get(); + connect(accountManager.data(), &AccountManager::loginComplete, this, &LoginDialog::handleLoginCompleted); - connect(&AccountManager::getInstance(), &AccountManager::loginFailed, + connect(accountManager.data(), &AccountManager::loginFailed, this, &LoginDialog::handleLoginFailed); } void LoginDialog::toggleAction() { - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login); Q_CHECK_PTR(loginAction); static QMetaObject::Connection connection; @@ -39,10 +40,10 @@ void LoginDialog::toggleAction() { disconnect(connection); } - if (accountManager.isLoggedIn()) { + if (accountManager->isLoggedIn()) { // change the menu item to logout - loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername()); - connection = connect(loginAction, &QAction::triggered, &accountManager, &AccountManager::logout); + loginAction->setText("Logout " + accountManager->getAccountInfo().getUsername()); + connection = connect(loginAction, &QAction::triggered, accountManager.data(), &AccountManager::logout); } else { // change the menu item to login loginAction->setText("Login"); @@ -78,7 +79,7 @@ QString LoginDialog::rootUrl() const { void LoginDialog::login(const QString& username, const QString& password) { qDebug() << "Attempting to login " << username; setStatusText("Logging in..."); - AccountManager::getInstance().requestAccessToken(username, password); + DependencyManager::get()->requestAccessToken(username, password); } void LoginDialog::openUrl(const QString& url) { diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index e35039df3d..b8be2bb8c4 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -92,7 +92,7 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) { QUrl currentURL = DependencyManager::get()->currentAddress(); shot.setText(URL, currentURL.toString()); - QString username = AccountManager::getInstance().getAccountInfo().getUsername(); + QString username = DependencyManager::get()->getAccountInfo().getUsername(); // normalize username, replace all non alphanumeric with '-' username.replace(QRegExp("[^A-Za-z0-9_]"), "-"); @@ -144,14 +144,15 @@ const QString SUCCESS_LABEL_TEMPLATE = "Success!!! Go check out your image ...(); + if (accountManager->getAccountInfo().getDiscourseApiKey().isEmpty()) { OffscreenUi::warning(nullptr, "", "Your Discourse API key is missing, you cannot share snapshots. Please try to relog."); return QString(); } QHttpPart apiKeyPart; apiKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"api_key\"")); - apiKeyPart.setBody(AccountManager::getInstance().getAccountInfo().getDiscourseApiKey().toLatin1()); + apiKeyPart.setBody(accountManager->getAccountInfo().getDiscourseApiKey().toLatin1()); QString filename = fileUrl.toLocalFile(); qDebug() << filename; @@ -206,7 +207,7 @@ QString SnapshotUploader::sendForumPost(const QString& snapshotPath, const QStri QUrl forumUrl(FORUM_POST_URL); QUrlQuery query; - query.addQueryItem("api_key", AccountManager::getInstance().getAccountInfo().getDiscourseApiKey()); + query.addQueryItem("api_key", DependencyManager::get()->getAccountInfo().getDiscourseApiKey()); query.addQueryItem("topic_id", FORUM_REPLY_TO_TOPIC); query.addQueryItem("raw", FORUM_POST_TEMPLATE.arg(snapshotPath, notes)); forumUrl.setQuery(query); diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 8c23844f4e..9080e3cc53 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -36,16 +36,6 @@ const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false; -AccountManager& AccountManager::getInstance(bool forceReset) { - static std::unique_ptr sharedInstance(new AccountManager()); - - if (forceReset) { - sharedInstance.reset(new AccountManager()); - } - - return *sharedInstance; -} - Q_DECLARE_METATYPE(OAuthAccessToken) Q_DECLARE_METATYPE(DataServerAccountInfo) Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) @@ -79,7 +69,8 @@ QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply &requestReply) } } -AccountManager::AccountManager() : +AccountManager::AccountManager(UserAgentGetter userAgentGetter) : + _userAgentGetter(userAgentGetter), _authURL(), _pendingCallbackMap() { @@ -222,8 +213,9 @@ void AccountManager::sendRequest(const QString& path, QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest; - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - + + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); + QUrl requestURL = _authURL; if (path.startsWith("/")) { @@ -473,7 +465,7 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest request; - request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); QUrl grantURL = _authURL; grantURL.setPath("/oauth/token"); @@ -543,7 +535,7 @@ void AccountManager::requestProfile() { profileURL.setPath("/api/v1/user/profile"); QNetworkRequest profileRequest(profileURL); - profileRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + profileRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); profileRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, _accountInfo.getAccessToken().authorizationHeaderValue()); QNetworkReply* profileReply = networkAccessManager.get(profileRequest); diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 108b49f678..89a2240bbb 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -20,6 +20,9 @@ #include "NetworkAccessManager.h" #include "DataServerAccountInfo.h" +#include "SharedUtil.h" + +#include class JSONCallbackParameters { public: @@ -49,10 +52,14 @@ Q_DECLARE_METATYPE(AccountManagerAuth::Type); const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization"; -class AccountManager : public QObject { +using UserAgentGetter = std::function; + +const auto DEFAULT_USER_AGENT_GETTER = []() -> QString { return HIGH_FIDELITY_USER_AGENT; }; + +class AccountManager : public QObject, public Dependency { Q_OBJECT public: - static AccountManager& getInstance(bool forceReset = false); + AccountManager(UserAgentGetter userAgentGetter = DEFAULT_USER_AGENT_GETTER); Q_INVOKABLE void sendRequest(const QString& path, AccountManagerAuth::Type authType, @@ -109,7 +116,6 @@ private slots: void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); private: - AccountManager(); AccountManager(AccountManager const& other) = delete; void operator=(AccountManager const& other) = delete; @@ -119,6 +125,8 @@ private: void passSuccessToCallback(QNetworkReply* reply); void passErrorToCallback(QNetworkReply* reply); + UserAgentGetter _userAgentGetter; + QUrl _authURL; QMap _pendingCallbackMap; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 27647d2694..a97f4df35d 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -374,7 +374,7 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q // remember how this lookup was triggered for history storage handling later requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast(trigger)); - AccountManager::getInstance().sendRequest(GET_PLACE.arg(placeName), + DependencyManager::get()->sendRequest(GET_PLACE.arg(placeName), AccountManagerAuth::None, QNetworkAccessManager::GetOperation, apiCallbackParameters(), @@ -397,7 +397,7 @@ void AddressManager::attemptDomainIDLookup(const QString& lookupString, const QS // remember how this lookup was triggered for history storage handling later requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast(trigger)); - AccountManager::getInstance().sendRequest(GET_DOMAIN_ID.arg(domainID), + DependencyManager::get()->sendRequest(GET_DOMAIN_ID.arg(domainID), AccountManagerAuth::None, QNetworkAccessManager::GetOperation, apiCallbackParameters(), @@ -577,7 +577,6 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16 return false; } - bool AddressManager::setDomainInfo(const QString& hostname, quint16 port, LookupTrigger trigger) { bool hostChanged = setHost(hostname, trigger, port); @@ -600,7 +599,7 @@ void AddressManager::goToUser(const QString& username) { requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast(LookupTrigger::UserInput)); // this is a username - pull the captured name and lookup that user's location - AccountManager::getInstance().sendRequest(GET_USER_LOCATION.arg(formattedUsername), + DependencyManager::get()->sendRequest(GET_USER_LOCATION.arg(formattedUsername), AccountManagerAuth::Optional, QNetworkAccessManager::GetOperation, apiCallbackParameters(), diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index b2eb0cd680..44ce63e6c6 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -371,10 +371,10 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer(); if (!_hasCheckedForAccessToken) { - accountManager.checkAndSignalForAccessToken(); + accountManager->checkAndSignalForAccessToken(); _hasCheckedForAccessToken = true; } @@ -382,7 +382,7 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer= CONNECTION_DENIALS_FOR_KEYPAIR_REGEN) { - accountManager.generateNewUserKeypair(); + accountManager->generateNewUserKeypair(); _connectionDenialsSinceKeypairRegen = 0; } } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 25dfe884db..482d0366fd 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -80,16 +80,16 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned // send a ping punch immediately connect(&_domainHandler, &DomainHandler::icePeerSocketsReceived, this, &NodeList::pingPunchForDomainServer); - auto &accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); // assume that we may need to send a new DS check in anytime a new keypair is generated - connect(&accountManager, &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn); + connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn); // clear out NodeList when login is finished - connect(&accountManager, &AccountManager::loginComplete , this, &NodeList::reset); + connect(accountManager.data(), &AccountManager::loginComplete , this, &NodeList::reset); // clear our NodeList when logout is requested - connect(&accountManager, &AccountManager::logoutComplete , this, &NodeList::reset); + connect(accountManager.data(), &AccountManager::logoutComplete , this, &NodeList::reset); // anytime we get a new node we will want to attempt to punch to it connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch); @@ -273,7 +273,7 @@ void NodeList::sendDomainServerCheckIn() { } // check if we're missing a keypair we need to verify ourselves with the domain-server - auto& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); const QUuid& connectionToken = _domainHandler.getConnectionToken(); // we assume that we're on the same box as the DS if it has the same local address and @@ -283,10 +283,10 @@ void NodeList::sendDomainServerCheckIn() { bool requiresUsernameSignature = !_domainHandler.isConnected() && !connectionToken.isNull() && !localhostDomain; - if (requiresUsernameSignature && !accountManager.getAccountInfo().hasPrivateKey()) { + if (requiresUsernameSignature && !accountManager->getAccountInfo().hasPrivateKey()) { qWarning() << "A keypair is required to present a username signature to the domain-server" << "but no keypair is present. Waiting for keypair generation to complete."; - accountManager.generateNewUserKeypair(); + accountManager->generateNewUserKeypair(); // don't send the check in packet - wait for the keypair first return; @@ -318,12 +318,12 @@ void NodeList::sendDomainServerCheckIn() { packetStream << _ownerType << _publicSockAddr << _localSockAddr << _nodeTypesOfInterest.toList(); if (!_domainHandler.isConnected()) { - DataServerAccountInfo& accountInfo = accountManager.getAccountInfo(); + DataServerAccountInfo& accountInfo = accountManager->getAccountInfo(); packetStream << accountInfo.getUsername(); // if this is a connect request, and we can present a username signature, send it along - if (requiresUsernameSignature && accountManager.getAccountInfo().hasPrivateKey()) { - const QByteArray& usernameSignature = accountManager.getAccountInfo().getUsernameSignature(connectionToken); + if (requiresUsernameSignature && accountManager->getAccountInfo().hasPrivateKey()) { + const QByteArray& usernameSignature = accountManager->getAccountInfo().getUsernameSignature(connectionToken); packetStream << usernameSignature; } } diff --git a/libraries/networking/src/OAuthNetworkAccessManager.cpp b/libraries/networking/src/OAuthNetworkAccessManager.cpp index fa6f3b8340..92e7a2ff4f 100644 --- a/libraries/networking/src/OAuthNetworkAccessManager.cpp +++ b/libraries/networking/src/OAuthNetworkAccessManager.cpp @@ -32,14 +32,14 @@ OAuthNetworkAccessManager* OAuthNetworkAccessManager::getInstance() { QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& req, QIODevice* outgoingData) { - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); - if (accountManager.hasValidAccessToken() + if (accountManager->hasValidAccessToken() && req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL.host()) { QNetworkRequest authenticatedRequest(req); authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, - accountManager.getAccountInfo().getAccessToken().authorizationHeaderValue()); + accountManager->getAccountInfo().getAccessToken().authorizationHeaderValue()); return QNetworkAccessManager::createRequest(op, authenticatedRequest, outgoingData); } else { diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 0d7690840d..83c6eb304e 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -17,6 +17,7 @@ #include "NetworkLogging.h" #include "UserActivityLogger.h" +#include static const QString USER_ACTIVITY_URL = "/api/v1/user_activities"; @@ -34,7 +35,7 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall return; } - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType); // Adding the action name @@ -59,7 +60,7 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall params.errorCallbackMethod = "requestError"; } - accountManager.sendRequest(USER_ACTIVITY_URL, + accountManager->sendRequest(USER_ACTIVITY_URL, AccountManagerAuth::Optional, QNetworkAccessManager::PostOperation, params, NULL, multipart); diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index 9a6f81b19f..15b2576331 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -140,11 +140,11 @@ void XMLHttpRequestClass::open(const QString& method, const QString& url, bool a _async = async; if (url.toLower().left(METAVERSE_API_URL.length()) == METAVERSE_API_URL) { - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); - if (accountManager.hasValidAccessToken()) { + if (accountManager->hasValidAccessToken()) { QUrlQuery urlQuery(_url.query()); - urlQuery.addQueryItem("access_token", accountManager.getAccountInfo().getAccessToken().token); + urlQuery.addQueryItem("access_token", accountManager->getAccountInfo().getAccessToken().token); _url.setQuery(urlQuery); } diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 0c1ad69d72..4fb25e3e3f 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -53,8 +53,8 @@ QString fixupHifiUrl(const QString& urlString) { QUrl url(urlString); QUrlQuery query(url); if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { - AccountManager& accountManager = AccountManager::getInstance(); - query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token); + auto accountManager = DependencyManager::get(); + query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager->getAccountInfo().getAccessToken().token); url.setQuery(query.query()); return url.toString(); } diff --git a/libraries/ui/src/Tooltip.cpp b/libraries/ui/src/Tooltip.cpp index 56ba8a95b9..3c0902b378 100644 --- a/libraries/ui/src/Tooltip.cpp +++ b/libraries/ui/src/Tooltip.cpp @@ -84,16 +84,16 @@ void Tooltip::requestHyperlinkImage() { // should the network link be removed from UI at a later date. // we possibly have a valid place name - so ask the API for the associated info - AccountManager& accountManager = AccountManager::getInstance(); + auto accountManager = DependencyManager::get(); JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; callbackParams.jsonCallbackMethod = "handleAPIResponse"; - accountManager.sendRequest(GET_PLACE.arg(_title), - AccountManagerAuth::None, - QNetworkAccessManager::GetOperation, - callbackParams); + accountManager->sendRequest(GET_PLACE.arg(_title), + AccountManagerAuth::None, + QNetworkAccessManager::GetOperation, + callbackParams); } } }