Merge pull request #311 from odysseus654/pr/webpage-restrict-from-polling

[shutdown-deadlock] Restructure ContextAwareProfile from polling to notifications
This commit is contained in:
kasenvr 2020-09-12 22:17:50 -04:00 committed by GitHub
commit e6f3ba4458
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 17 deletions

View file

@ -12,7 +12,9 @@
#include "ContextAwareProfile.h" #include "ContextAwareProfile.h"
#include <cassert> #include <cassert>
#include <QtCore/QReadLocker>
#include <QtCore/QThread> #include <QtCore/QThread>
#include <QtCore/QWriteLocker>
#include <QtQml/QQmlContext> #include <QtQml/QQmlContext>
#include <shared/QtHelpers.h> #include <shared/QtHelpers.h>
@ -20,20 +22,63 @@
static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess";
ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : QReadWriteLock ContextAwareProfile::_contextMapProtect;
ContextAwareProfileParent(context), _context(context) { ContextAwareProfile::ContextMap ContextAwareProfile::_contextMap;
ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) {
assert(context); assert(context);
{ // register our object for future updates
QWriteLocker guard(&_contextMapProtect);
ContextMap::iterator setLookup = _contextMap.find(_context);
if (setLookup == _contextMap.end()) {
setLookup = _contextMap.insert(_context, ContextAwareProfileSet());
}
assert(setLookup != _contextMap.end());
ContextAwareProfileSet& profileSet = setLookup.value();
assert(profileSet.find(this) == profileSet.end());
profileSet.insert(this);
} }
_isRestricted.store(isRestrictedGetProperty());
}
ContextAwareProfile::~ContextAwareProfile() {
// deregister our object
QWriteLocker guard(&_contextMapProtect);
ContextMap::iterator setLookup = _contextMap.find(_context);
assert(setLookup != _contextMap.end());
if (setLookup != _contextMap.end()) {
ContextAwareProfileSet& profileSet = setLookup.value();
assert(profileSet.find(this) != profileSet.end());
profileSet.remove(this);
if (profileSet.isEmpty()) {
_contextMap.erase(setLookup);
}
}
}
void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) {
// set the QML property
context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict);
// broadcast the new value to any registered ContextAwareProfile objects
QReadLocker guard(&_contextMapProtect);
ContextMap::const_iterator setLookup = _contextMap.find(context);
if (setLookup != _contextMap.end()) {
const ContextAwareProfileSet& profileSet = setLookup.value();
for (ContextAwareProfileSet::const_iterator profileIterator = profileSet.begin();
profileIterator != profileSet.end(); profileIterator++) {
(*profileIterator)->_isRestricted.store(restrict);
}
}
} }
bool ContextAwareProfile::isRestrictedInternal() { bool ContextAwareProfile::isRestrictedGetProperty() {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
bool restrictedResult = false; bool restrictedResult = false;
BLOCKING_INVOKE_METHOD(this, "isRestrictedInternal", Q_RETURN_ARG(bool, restrictedResult)); BLOCKING_INVOKE_METHOD(this, "isRestrictedGetProperty", Q_RETURN_ARG(bool, restrictedResult));
return restrictedResult; return restrictedResult;
} }
@ -48,10 +93,5 @@ bool ContextAwareProfile::isRestrictedInternal() {
} }
bool ContextAwareProfile::isRestricted() { bool ContextAwareProfile::isRestricted() {
auto now = usecTimestampNow(); return _isRestricted.load();
if (now > _cacheExpiry) {
_cachedValue = isRestrictedInternal();
_cacheExpiry = now + MAX_CACHE_AGE;
}
return _cachedValue;
} }

View file

@ -11,7 +11,11 @@
#ifndef hifi_ContextAwareProfile_h #ifndef hifi_ContextAwareProfile_h
#define hifi_ContextAwareProfile_h #define hifi_ContextAwareProfile_h
#include <QtCore/QtGlobal> #include <atomic>
#include <QtCore/QHash>
#include <QtCore/QReadWriteLock>
#include <QtCore/QSet>
#include <QtCore/QSharedPointer>
#if !defined(Q_OS_ANDROID) #if !defined(Q_OS_ANDROID)
#include <QtWebEngine/QQuickWebEngineProfile> #include <QtWebEngine/QQuickWebEngineProfile>
@ -26,8 +30,6 @@ using ContextAwareProfileParent = QObject;
using RequestInterceptorParent = QObject; using RequestInterceptorParent = QObject;
#endif #endif
#include <NumericalConstants.h>
class QQmlContext; class QQmlContext;
class ContextAwareProfile : public ContextAwareProfileParent { class ContextAwareProfile : public ContextAwareProfileParent {
@ -35,7 +37,7 @@ class ContextAwareProfile : public ContextAwareProfileParent {
public: public:
static void restrictContext(QQmlContext* context, bool restrict = true); static void restrictContext(QQmlContext* context, bool restrict = true);
bool isRestricted(); bool isRestricted();
Q_INVOKABLE bool isRestrictedInternal(); Q_INVOKABLE bool isRestrictedGetProperty();
protected: protected:
class RequestInterceptor : public RequestInterceptorParent { class RequestInterceptor : public RequestInterceptorParent {
@ -47,10 +49,17 @@ protected:
}; };
ContextAwareProfile(QQmlContext* parent); ContextAwareProfile(QQmlContext* parent);
~ContextAwareProfile();
private:
typedef QSet<ContextAwareProfile*> ContextAwareProfileSet;
typedef QHash<QQmlContext*, ContextAwareProfileSet> ContextMap;
QQmlContext* _context{ nullptr }; QQmlContext* _context{ nullptr };
bool _cachedValue{ false }; std::atomic<bool> _isRestricted{ false };
quint64 _cacheExpiry{ 0 };
constexpr static quint64 MAX_CACHE_AGE = MSECS_PER_SECOND; static QReadWriteLock _contextMapProtect;
static ContextMap _contextMap;
}; };
#endif // hifi_FileTypeProfile_h #endif // hifi_FileTypeProfile_h