Merge pull request #16113 from jherico/fix/bugz-1363

BUGZ-1363: crash when checking for web content restrictions
This commit is contained in:
Bradley Austin Davis 2019-08-30 13:09:49 -07:00 committed by GitHub
commit 29424ca971
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 35 deletions

View file

@ -18,6 +18,7 @@
#include <QtQuick/QQuickWindow> #include <QtQuick/QQuickWindow>
#include <QQuickView> #include <QQuickView>
#include <ui/types/ContextAwareProfile.h>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <DockWidget.h> #include <DockWidget.h>
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
@ -228,9 +229,15 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
_dockWidget->setObjectName("DockedWidget"); _dockWidget->setObjectName("DockedWidget");
mainWindow->addDockWidget(dockArea, _dockWidget.get()); mainWindow->addDockWidget(dockArea, _dockWidget.get());
} else { } else {
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto contextInitLambda = [&](QQmlContext* context) {
// Build the event bridge and wrapper on the main thread #if !defined(Q_OS_ANDROID)
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) { // If the restricted flag is on, override the FileTypeProfile and HFWebEngineProfile objects in the
// QML surface root context with local ones
ContextAwareProfile::restrictContext(context, false);
#endif
};
auto objectInitLambda = [&](QQmlContext* context, QObject* object) {
_qmlWindowProxy = std::shared_ptr<QmlWindowProxy>(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter); _qmlWindowProxy = std::shared_ptr<QmlWindowProxy>(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter);
context->setContextProperty(EVENT_BRIDGE_PROPERTY, _interactiveWindowProxy.get()); context->setContextProperty(EVENT_BRIDGE_PROPERTY, _interactiveWindowProxy.get());
if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) { if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) {
@ -286,7 +293,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
} }
object->setObjectName("InteractiveWindow"); object->setObjectName("InteractiveWindow");
object->setProperty(SOURCE_PROPERTY, sourceURL); object->setProperty(SOURCE_PROPERTY, sourceURL);
}); };
auto offscreenUi = DependencyManager::get<OffscreenUi>();
// Build the event bridge and wrapper on the main thread
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, objectInitLambda, contextInitLambda);
} }
} }

View file

@ -136,10 +136,8 @@ void QmlWindowClass::initQml(QVariantMap properties) {
#if !defined(Q_OS_ANDROID) #if !defined(Q_OS_ANDROID)
// If the restricted flag is on, override the FileTypeProfile and HFWebEngineProfile objects in the // If the restricted flag is on, override the FileTypeProfile and HFWebEngineProfile objects in the
// QML surface root context with local ones // QML surface root context with local ones
qDebug() << "Context initialization lambda"; ContextAwareProfile::restrictContext(context, _restricted);
if (_restricted) { if (_restricted) {
qDebug() << "Restricting web content";
ContextAwareProfile::restrictContext(context);
FileTypeProfile::registerWithContext(context); FileTypeProfile::registerWithContext(context);
HFWebEngineProfile::registerWithContext(context); HFWebEngineProfile::registerWithContext(context);
} }

View file

@ -11,22 +11,39 @@
#include "ContextAwareProfile.h" #include "ContextAwareProfile.h"
#if !defined(Q_OS_ANDROID) #include <cassert>
#include <QtCore/QThread>
#include <QtQml/QQmlContext> #include <QtQml/QQmlContext>
#include <shared/QtHelpers.h>
#include <SharedUtil.h>
static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess";
ContextAwareProfile::ContextAwareProfile(QQmlContext* parent) : ContextAwareProfile::ContextAwareProfile(QQmlContext* context) :
QQuickWebEngineProfile(parent), _context(parent) { } ContextAwareProfileParent(context), _context(context) {
assert(context);
void ContextAwareProfile::restrictContext(QQmlContext* context) {
context->setContextProperty(RESTRICTED_FLAG_PROPERTY, true);
} }
bool ContextAwareProfile::isRestricted(QQmlContext* context) {
return context->contextProperty(RESTRICTED_FLAG_PROPERTY).toBool(); void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) {
context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict);
} }
#endif bool ContextAwareProfile::isRestrictedInternal() {
if (QThread::currentThread() != thread()) {
bool restrictedResult = false;
BLOCKING_INVOKE_METHOD(this, "isRestrictedInternal", Q_RETURN_ARG(bool, restrictedResult));
return restrictedResult;
}
return _context->contextProperty(RESTRICTED_FLAG_PROPERTY).toBool();
}
bool ContextAwareProfile::isRestricted() {
auto now = usecTimestampNow();
if (now > _cacheExpiry) {
_cachedValue = isRestrictedInternal();
_cacheExpiry = now + MAX_CACHE_AGE;
}
return _cachedValue;
}

View file

@ -17,26 +17,40 @@
#include <QtWebEngine/QQuickWebEngineProfile> #include <QtWebEngine/QQuickWebEngineProfile>
#include <QtWebEngineCore/QWebEngineUrlRequestInterceptor> #include <QtWebEngineCore/QWebEngineUrlRequestInterceptor>
using ContextAwareProfileParent = QQuickWebEngineProfile;
using RequestInterceptorParent = QWebEngineUrlRequestInterceptor;
#else
#include <QtCore/QObject>
using ContextAwareProfileParent = QObject;
using RequestInterceptorParent = QObject;
#endif
#include <NumericalConstants.h>
class QQmlContext; class QQmlContext;
class ContextAwareProfile : public QQuickWebEngineProfile { class ContextAwareProfile : public ContextAwareProfileParent {
Q_OBJECT
public: public:
static void restrictContext(QQmlContext* context); static void restrictContext(QQmlContext* context, bool restrict = true);
static bool isRestricted(QQmlContext* context); bool isRestricted();
QQmlContext* getContext() const { return _context; } Q_INVOKABLE bool isRestrictedInternal();
protected: protected:
class RequestInterceptor : public QWebEngineUrlRequestInterceptor { class RequestInterceptor : public RequestInterceptorParent {
public: public:
RequestInterceptor(ContextAwareProfile* parent) : QWebEngineUrlRequestInterceptor(parent), _profile(parent) {} RequestInterceptor(ContextAwareProfile* parent) : RequestInterceptorParent(parent), _profile(parent) { }
QQmlContext* getContext() const { return _profile->getContext(); } bool isRestricted() { return _profile->isRestricted(); }
protected: protected:
ContextAwareProfile* _profile; ContextAwareProfile* _profile;
}; };
ContextAwareProfile(QQmlContext* parent); ContextAwareProfile(QQmlContext* parent);
QQmlContext* _context; QQmlContext* _context{ nullptr };
bool _cachedValue{ false };
quint64 _cacheExpiry{ 0 };
constexpr static quint64 MAX_CACHE_AGE = MSECS_PER_SECOND;
}; };
#endif
#endif // hifi_FileTypeProfile_h #endif // hifi_FileTypeProfile_h

View file

@ -29,8 +29,8 @@ FileTypeProfile::FileTypeProfile(QQmlContext* parent) :
} }
void FileTypeProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { void FileTypeProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
RequestFilters::interceptHFWebEngineRequest(info, getContext()); RequestFilters::interceptHFWebEngineRequest(info, isRestricted());
RequestFilters::interceptFileType(info, getContext()); RequestFilters::interceptFileType(info);
} }
void FileTypeProfile::registerWithContext(QQmlContext* context) { void FileTypeProfile::registerWithContext(QQmlContext* context) {

View file

@ -28,7 +28,7 @@ HFWebEngineProfile::HFWebEngineProfile(QQmlContext* parent) : Parent(parent)
} }
void HFWebEngineProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { void HFWebEngineProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
RequestFilters::interceptHFWebEngineRequest(info, getContext()); RequestFilters::interceptHFWebEngineRequest(info, isRestricted());
} }
void HFWebEngineProfile::registerWithContext(QQmlContext* context) { void HFWebEngineProfile::registerWithContext(QQmlContext* context) {

View file

@ -63,8 +63,8 @@ namespace {
} }
} }
void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, QQmlContext* context) { void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, bool restricted) {
if (ContextAwareProfile::isRestricted(context) && blockLocalFiles(info)) { if (restricted && blockLocalFiles(info)) {
return; return;
} }
@ -90,7 +90,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info,
info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit());
} }
void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info, QQmlContext* context) { void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) {
QString filename = info.requestUrl().fileName(); QString filename = info.requestUrl().fileName();
if (isScript(filename) || isJSON(filename)) { if (isScript(filename) || isJSON(filename)) {
static const QString CONTENT_HEADER = "Accept"; static const QString CONTENT_HEADER = "Accept";

View file

@ -24,8 +24,8 @@ class QQmlContext;
class RequestFilters : public QObject { class RequestFilters : public QObject {
public: public:
static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, QQmlContext* context); static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, bool restricted);
static void interceptFileType(QWebEngineUrlRequestInfo& info, QQmlContext* context); static void interceptFileType(QWebEngineUrlRequestInfo& info);
}; };
#endif #endif