From c65cc9570d5d846855b963cdbdc00adcc89aed78 Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Sun, 6 Sep 2020 23:10:23 +0200 Subject: [PATCH] Prototype for moving content away from hifi infrastructure --- interface/src/Application.cpp | 11 ++ .../ScreenshareScriptingInterface.cpp | 5 +- libraries/networking/src/ExternalResource.cpp | 56 +++++++ libraries/networking/src/ExternalResource.h | 141 ++++++++++++++++++ scripts/system/create/edit.js | 4 +- 5 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 libraries/networking/src/ExternalResource.cpp create mode 100644 libraries/networking/src/ExternalResource.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 643600f5d5..bbbc51ecf1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -253,6 +253,7 @@ #include #include "AboutUtil.h" +#include "ExternalResource.h" #if defined(Q_OS_WIN) #include @@ -3294,6 +3295,7 @@ void Application::initializeUi() { qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); qmlRegisterType("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine"); + // qmlRegisterType("ExternalResource", 1, 0, "ExternalResource"); { auto tabletScriptingInterface = DependencyManager::get(); @@ -7535,6 +7537,15 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); // Deprecated. scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get().data()); + // This is obviously wrong -- FIXME! + scriptEngine->registerValue("Bucket.Public", static_cast(ExternalResource::Bucket::Public)); + scriptEngine->registerValue("Bucket.Content", static_cast(ExternalResource::Bucket::Content)); + scriptEngine->registerValue("Bucket.MPAssets", static_cast(ExternalResource::Bucket::MPAssets)); + scriptEngine->registerValue("Bucket.Assets", static_cast(ExternalResource::Bucket::Assets)); + + + scriptEngine->registerGlobalObject("ExternalResource", ExternalResource::getInstance()); + registerInteractiveWindowMetaType(scriptEngine.data()); auto pickScriptingInterface = DependencyManager::get(); diff --git a/interface/src/scripting/ScreenshareScriptingInterface.cpp b/interface/src/scripting/ScreenshareScriptingInterface.cpp index 7ef437a609..21d19f6466 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.cpp +++ b/interface/src/scripting/ScreenshareScriptingInterface.cpp @@ -23,6 +23,7 @@ #include "EntityScriptingInterface.h" #include "ScreenshareScriptingInterface.h" +#include "ExternalResource.h" static const int SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS = 300; ScreenshareScriptingInterface::ScreenshareScriptingInterface() { @@ -128,8 +129,8 @@ static const uint8_t LOCAL_SCREENSHARE_WEB_ENTITY_FPS = 30; // The `z` value here is dynamic. static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION(0.0128f, -0.0918f, 0.0f); static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS(3.6790f, 2.0990f, 0.0100f); -static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL = - "https://content.highfidelity.com/Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html"; +static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL = ExternalResource::getInstance()->getUrl(ExternalResource::Bucket::Content, + "Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html"); static const QString LOCAL_SCREENSHARE_WEB_ENTITY_HOST_TYPE = "local"; void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZoneID, const QUuid& smartboardEntityID, diff --git a/libraries/networking/src/ExternalResource.cpp b/libraries/networking/src/ExternalResource.cpp new file mode 100644 index 0000000000..9b816ece9f --- /dev/null +++ b/libraries/networking/src/ExternalResource.cpp @@ -0,0 +1,56 @@ +// +// ExternalResource.h +// +// Created by Dale Glass on 6 Sep 2020 +// Copyright 2020 Vircadia contributors. +// +// Flexible management for external resources (eg, on S3) +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include "ExternalResource.h" +#include +#include + + +Q_LOGGING_CATEGORY(external_resource, "vircadia.networking.external_resource") + + +ExternalResource::ExternalResource(QObject *parent) : QObject(parent) { + +} + + +ExternalResource * ExternalResource::getInstance() { + static ExternalResource instance; + return &instance; +} + +QUrl ExternalResource::getQUrl(Bucket bucket, const QUrl &relative_path) { + qCDebug(external_resource) << "Requested URL for bucket " << bucket << ", path " << relative_path; + + if ( !_bucketBases.contains(bucket)) { + qCCritical(external_resource) << "External resource " << relative_path << " was requested from unrecognized bucket " << bucket; + return QUrl(); + } + + if ( !relative_path.isValid() ) { + qCCritical(external_resource) << "External resource " << relative_path << " was requested from bucket " << bucket << " with an invalid path. Error: " << relative_path.errorString(); + return QUrl(); + } + + if ( !relative_path.isRelative() ) { + qCWarning(external_resource) << "External resource " << relative_path << " was requested from bucket " << bucket << " without using a relative path, returning as-is."; + return relative_path; + } + + QUrl base = _bucketBases[bucket]; + QUrl merged = base.resolved(relative_path); + + + qCDebug(external_resource) << "External resource resolved to " << merged; + + return merged; +} + diff --git a/libraries/networking/src/ExternalResource.h b/libraries/networking/src/ExternalResource.h new file mode 100644 index 0000000000..c07208c452 --- /dev/null +++ b/libraries/networking/src/ExternalResource.h @@ -0,0 +1,141 @@ +// +// ExternalResource.h +// +// Created by Dale Glass on 6 Sep 2020 +// Copyright 2020 Vircadia contributors. +// +// Flexible management for external resources (eg, on S3) +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#ifndef vircadia_ExternalResource_h +#define vircadia_ExternalResource_h + +#include +#include +#include + + +/** + * Flexible management for external resources + * + * With the death of the original High Fidelity and the transition of the project to a community-managed + * one, it became necessary to deal with that the various assets that used to be located under the + * highfidelity.com domain will disappear, and there won't be a fixed place for them afterwards. Data + * hosted by community members may not remain forever, reorganization may be necessary, people may want + * to run mirrors, and some might want to run without external internet access at all. + * + * This class makes it possible to deal with this in a more flexible manner: rather than hardcoding URLs + * all over the codebase, now it's possible to easily change where all those things are downloaded from. + * + * + */ +class ExternalResource : public QObject { + Q_OBJECT + + public: + + static ExternalResource *getInstance(); + ~ExternalResource() {}; + + + /** + * Bucket from which to retrieve the resource + * + * The original High Fidelity used the Public, Content and MPAssets buckets. The intention is that the + * community-run versions of these will keep the original data and structure, and any new additions + * will be done to the Assets bucket instead. This should ease the transition and ensure a clean + * separation. + */ + enum class Bucket { + /** Assets that used to be in the hifi-public S3 bucket */ + Public, + + /** Assets that used to be in the hifi-content S3 bucket */ + Content, + + /** Assets that used to be in the mpassets S3 bucket (hifi marketplace) */ + MPAssets, + + /** Vircadia assets */ + Assets + }; + + Q_ENUM(Bucket) + + /** + * Returns the location of a resource as a QUrl + * + * Returns the location of the resource \p relative_path in bucket \p bucket + * + * @note The resulting path will be sanitized by condensing multiple instances of '/' to one. + * This is done for easier usage with Amazon S3 and compatible systems. + * + * @param bucket The bucket in which the resource is found + * @param relative_path The path of the resource within the bucket + * @returns The resulting URL as a QUrl + */ + Q_INVOKABLE QUrl getQUrl(Bucket bucket, const QUrl& relative_path); + + + /** + * Returns the location of a resource as a QUrl + * + * Returns the location of the resource \p relative_path in bucket \p bucket + * + * @note The resulting path will be sanitized by condensing multiple instances of '/' to one. + * This is done for easier usage with Amazon S3 and compatible systems. + * + * @param bucket The bucket in which the resource is found + * @param relative_path The path of the resource within the bucket + * @returns The resulting URL as a QUrl + */ + Q_INVOKABLE QUrl getQUrl(Bucket bucket, QString path) { + return getQUrl(bucket, QUrl(path)); + } + + /** + * Returns the location of a resource as a QString + * + * Returns the location of the resource \p relative_path in bucket \p bucket + * + * @note The resulting path will be sanitized by condensing multiple instances of '/' to one. + * This is done for easier usage with Amazon S3 and compatible systems. + * + * @param bucket The bucket in which the resource is found + * @param relative_path The path of the resource within the bucket + * @returns The resulting URL as a QString + */ + Q_INVOKABLE QString getUrl(Bucket bucket, const QUrl &relative_path) { + return ExternalResource::getQUrl(bucket, relative_path).toString(); + }; + + /** + * Returns the location of a resource as a QString + * + * Returns the location of the resource \p relative_path in bucket \p bucket + * + * @note The resulting path will be sanitized by condensing multiple instances of '/' to one. + * This is done for easier usage with Amazon S3 and compatible systems. + * + * @param bucket The bucket in which the resource is found + * @param relative_path The path of the resource within the bucket + * @returns The resulting URL as a QString + */ + Q_INVOKABLE QString getUrl(Bucket bucket, const QString &relative_path) { + return ExternalResource::getQUrl(bucket, QUrl(relative_path)).toString(); + }; + + private: + ExternalResource(QObject* parent = nullptr); + + QMap _bucketBases { + { Bucket::Public, QUrl("https://public.vircadia.com")}, + { Bucket::Content, QUrl("https://content.vircadia.com")}, + { Bucket::Assets, QUrl("https://assets.vircadia.com")}, + { Bucket::MPAssets, QUrl("https://mpassets.vircadia.com")}, + }; +}; + +#endif \ No newline at end of file diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index e01e761cb4..9b071c2b73 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -44,8 +44,8 @@ var CREATE_TOOLS_WIDTH = 490; var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; var ENTIRE_DOMAIN_SCAN_RADIUS = 27713; -var DEFAULT_IMAGE = "http://eu-central-1.linodeobjects.com/vircadia-assets/interface/default/default_image.jpg"; -var DEFAULT_PARTICLE = "http://eu-central-1.linodeobjects.com/vircadia-assets/interface/default/default_particle.png"; +var DEFAULT_IMAGE = ExternalResource.getUrl(Bucket.Assets, "interface/default/default_image.jpg"); +var DEFAULT_PARTICLE = ExternalResource.getUrl(Bucket.Assets, "interface/default/default_particle.png"); var createToolsWindow = new CreateWindow( Script.resolvePath("qml/EditTools.qml"),