From a2b1cfc7acaddac60085121ca0375926ab86e089 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 29 Aug 2017 17:06:57 -0700 Subject: [PATCH] security image shows up in every qml engine now --- interface/src/Application.cpp | 7 ++---- interface/src/commerce/Wallet.cpp | 23 ++++++++++++------- interface/src/commerce/Wallet.h | 3 +++ .../ui}/src/ui/ImageProvider.cpp | 15 +++++++++++- .../ui}/src/ui/ImageProvider.h | 7 +++--- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 11 ++++++--- 6 files changed, 46 insertions(+), 20 deletions(-) rename {interface => libraries/ui}/src/ui/ImageProvider.cpp (66%) rename {interface => libraries/ui}/src/ui/ImageProvider.h (82%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d13b7880fa..277423051c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -183,7 +183,6 @@ #include "ui/UpdateDialog.h" #include "ui/overlays/Overlays.h" #include "ui/DomainConnectionModel.h" -#include "ui/ImageProvider.h" #include "Util.h" #include "InterfaceParentFinder.h" #include "ui/OctreeStatsProvider.h" @@ -264,7 +263,7 @@ private: switch ((int)event->type()) { case ApplicationEvent::Render: render(); - // Ensure we never back up the render events. Each render should be triggered only in response + // Ensure we never back up the render events. Each render should be triggered only in response // to the NEXT render event after the last render occured QCoreApplication::removePostedEvents(this, ApplicationEvent::Render); return true; @@ -2243,8 +2242,6 @@ void Application::initializeUi() { qApp->quit(); }); - // register the pixmap image provider (used only for security image, for now) - engine->addImageProvider(ImageProvider::PROVIDER_NAME, new ImageProvider()); setupPreferences(); @@ -5164,7 +5161,7 @@ void Application::update(float deltaTime) { } } else { // update the rendering without any simulation - getEntities()->update(false); + getEntities()->update(false); } // AvatarManager update diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 9e04694a24..4cbcb5f1d3 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -224,6 +224,12 @@ void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArra memcpy(ckey, hash.data(), 32); } +Wallet::~Wallet() { + if (_securityImage) { + delete _securityImage; + } +} + void Wallet::setPassphrase(const QString& passphrase) { if (_passphrase) { delete _passphrase; @@ -411,6 +417,13 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { return QString(); } +void Wallet::updateImageProvider() { + // inform the image provider. Note it doesn't matter which one you inform, as the + // images are statics + auto engine = DependencyManager::get()->getSurfaceContext()->engine(); + auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME)); + imageProvider->setSecurityImage(_securityImage); +} void Wallet::chooseSecurityImage(const QString& filename) { @@ -431,10 +444,7 @@ void Wallet::chooseSecurityImage(const QString& filename) { if (encryptFile(path, imageFilePath())) { qCDebug(commerce) << "emitting pixmap"; - // inform the image provider - auto engine = DependencyManager::get()->getSurfaceContext()->engine(); - auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME)); - imageProvider->setSecurityImage(_securityImage); + updateImageProvider(); emit securityImageResult(true); } else { @@ -460,10 +470,7 @@ void Wallet::getSecurityImage() { _securityImage->loadFromData(data, dataLen, "jpg"); qCDebug(commerce) << "created pixmap from encrypted file"; - // inform the image provider - auto engine = DependencyManager::get()->getSurfaceContext()->engine(); - auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME)); - imageProvider->setSecurityImage(_securityImage); + updateImageProvider(); delete[] data; emit securityImageResult(true); diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index b13d4368d9..03005bbbec 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -23,6 +23,8 @@ class Wallet : public QObject, public Dependency { SINGLETON_DEPENDENCY public: + + ~Wallet(); // These are currently blocking calls, although they might take a moment. bool createIfNeeded(); bool generateKeyPair(); @@ -59,6 +61,7 @@ private: QByteArray _salt {"iamsalt!"}; QString* _passphrase { new QString("pwd") }; + void updateImageProvider(); bool encryptFile(const QString& inputFilePath, const QString& outputFilePath); bool decryptFile(const QString& inputFilePath, unsigned char** outputBufferPtr, int* outputBufferLen); }; diff --git a/interface/src/ui/ImageProvider.cpp b/libraries/ui/src/ui/ImageProvider.cpp similarity index 66% rename from interface/src/ui/ImageProvider.cpp rename to libraries/ui/src/ui/ImageProvider.cpp index 4925cdf1e9..378b93527c 100644 --- a/interface/src/ui/ImageProvider.cpp +++ b/libraries/ui/src/ui/ImageProvider.cpp @@ -10,13 +10,26 @@ // #include "ImageProvider.h" -#include + +#include +#include const QString ImageProvider::PROVIDER_NAME = "security"; +QReadWriteLock ImageProvider::_rwLock; +QPixmap* ImageProvider::_securityImage = nullptr; + +void ImageProvider::setSecurityImage(QPixmap* pixmap) { + // we are responsible for the pointer so no need to copy + // but we do need to delete the old one. + QWriteLocker lock(&_rwLock); + // no need to delete old one, that is managed by the wallet + _securityImage = pixmap; +} QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) { // adjust the internal pixmap to have the requested size + QReadLocker lock(&_rwLock); if (id == "securityImage" && _securityImage) { *size = _securityImage->size(); if (requestedSize.width() > 0 && requestedSize.height() > 0) { diff --git a/interface/src/ui/ImageProvider.h b/libraries/ui/src/ui/ImageProvider.h similarity index 82% rename from interface/src/ui/ImageProvider.h rename to libraries/ui/src/ui/ImageProvider.h index c0b620585a..5bd2e254e7 100644 --- a/interface/src/ui/ImageProvider.h +++ b/libraries/ui/src/ui/ImageProvider.h @@ -13,6 +13,7 @@ #define hifi_ImageProvider_h #include +#include class ImageProvider: public QQuickImageProvider { public: @@ -22,10 +23,10 @@ public: QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override; - void setSecurityImage(QPixmap* pixmap) { _securityImage = pixmap; } - + void setSecurityImage(QPixmap* pixmap); protected: - QPixmap* _securityImage { nullptr }; + static QReadWriteLock _rwLock; + static QPixmap* _securityImage; }; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index be9a15b416..84466f41b0 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -6,6 +6,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "OffscreenQmlSurface.h" +#include "ImageProvider.h" // Has to come before Qt GL includes #include @@ -184,7 +185,7 @@ private: GLuint texture = textureAndFence.first; uvec2 size = _textureSizes[texture]; auto sizeKey = uvec2ToUint64(size); - // Textures can be returned after all surfaces of the given size have been destroyed, + // Textures can be returned after all surfaces of the given size have been destroyed, // in which case we just destroy the texture if (!_textures.count(sizeKey)) { destroy(textureAndFence); @@ -305,6 +306,9 @@ static size_t globalEngineRefCount{ 0 }; #endif void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) { + // register the pixmap image provider (used only for security image, for now) + engine->addImageProvider(ImageProvider::PROVIDER_NAME, new ImageProvider()); + engine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory); auto importList = engine->importPathList(); importList.insert(importList.begin(), PathUtils::resourcesPath()); @@ -464,8 +468,8 @@ std::function OffscreenQmlSurface::getDiscardLambda() { } bool OffscreenQmlSurface::allowNewFrame(uint8_t fps) { - // If we already have a pending texture, don't render another one - // i.e. don't render faster than the consumer context, since it wastes + // If we already have a pending texture, don't render another one + // i.e. don't render faster than the consumer context, since it wastes // GPU cycles on producing output that will never be seen if (0 != _latestTextureAndFence.first) { return false; @@ -526,6 +530,7 @@ void OffscreenQmlSurface::create() { // Create a QML engine. auto qmlEngine = acquireEngine(_quickWindow); + _qmlContext = new QQmlContext(qmlEngine->rootContext()); _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));