Merge pull request #9938 from kunalgosar/jsRenderBug

Stop WebEntities Running Files and Commands
This commit is contained in:
Seth Alves 2017-04-07 13:44:03 -07:00 committed by GitHub
commit 03065ee6c8
12 changed files with 237 additions and 28 deletions

View file

@ -2,6 +2,7 @@ import QtQuick 2.5
import QtQuick.Controls 1.2
import QtWebChannel 1.0
import QtWebEngine 1.2
import FileTypeProfile 1.0
import "controls-uit"
import "styles" as HifiStyles
@ -216,6 +217,11 @@ ScrollingWindow {
WebChannel.id: "eventBridgeWrapper"
property var eventBridge;
}
profile: FileTypeProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
webChannel.registeredObjects: [eventBridgeWrapper]

View file

@ -0,0 +1,22 @@
//
// WebEntityView.qml
//
// Created by Kunal Gosar on 16 March 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "."
import FileTypeProfile 1.0
WebView {
viewProfile: FileTypeProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
urlTag: "noDownload=true";
}

View file

@ -10,6 +10,7 @@ Item {
property alias eventBridge: eventBridgeWrapper.eventBridge
property alias canGoBack: root.canGoBack;
property var goBack: root.goBack;
property alias urlTag: root.urlTag
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
property bool keyboardRaised: false
property bool punctuationMode: false
@ -27,6 +28,8 @@ Item {
WebChannel.id: "eventBridgeWrapper"
property var eventBridge;
}
property alias viewProfile: root.profile
WebEngineView {
id: root
@ -66,6 +69,8 @@ Item {
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
worldId: WebEngineScript.MainWorld
}
property string urlTag: "noDownload=false";
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
@ -94,6 +99,7 @@ Item {
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
var url = loadRequest.url.toString();
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
root.stop();

View file

@ -142,6 +142,7 @@
#include "ModelPackager.h"
#include "networking/HFWebEngineProfile.h"
#include "networking/HFTabletWebEngineProfile.h"
#include "networking/FileTypeProfile.h"
#include "scripting/TestScriptingInterface.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AssetMappingsScriptingInterface.h"
@ -218,6 +219,7 @@ static const QString FST_EXTENSION = ".fst";
static const QString FBX_EXTENSION = ".fbx";
static const QString OBJ_EXTENSION = ".obj";
static const QString AVA_JSON_EXTENSION = ".ava.json";
static const QString WEB_VIEW_TAG = "noDownload=true";
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
@ -1934,6 +1936,7 @@ void Application::initializeUi() {
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_glWidget->qglContext());
@ -5545,7 +5548,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
bool Application::canAcceptURL(const QString& urlString) const {
QUrl url(urlString);
if (urlString.startsWith(HIFI_URL_SCHEME)) {
if (url.query().contains(WEB_VIEW_TAG)) {
return false;
} else if (urlString.startsWith(HIFI_URL_SCHEME)) {
return true;
}
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
@ -5653,7 +5658,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
QUrl scriptURL { scriptFilenameOrURL };
if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
shortName = shortName.mid(shortName.lastIndexOf('/') + 1);
int startIndex = shortName.lastIndexOf('/') + 1;
int endIndex = shortName.lastIndexOf('?');
shortName = shortName.mid(startIndex, endIndex - startIndex);
}
QString message = "Would you like to run this script:\n" + shortName;

View file

@ -0,0 +1,26 @@
//
// FileTypeProfile.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "FileTypeProfile.h"
#include "FileTypeRequestInterceptor.h"
static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine";
FileTypeProfile::FileTypeProfile(QObject* parent) :
QQuickWebEngineProfile(parent)
{
static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
setHttpUserAgent(WEB_ENGINE_USER_AGENT);
auto requestInterceptor = new FileTypeRequestInterceptor(this);
setRequestInterceptor(requestInterceptor);
}

View file

@ -0,0 +1,25 @@
//
// FileTypeProfile.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_FileTypeProfile_h
#define hifi_FileTypeProfile_h
#include <QtWebEngine/QQuickWebEngineProfile>
class FileTypeProfile : public QQuickWebEngineProfile {
public:
FileTypeProfile(QObject* parent = Q_NULLPTR);
};
#endif // hifi_FileTypeProfile_h

View file

@ -0,0 +1,21 @@
//
// FileTypeRequestInterceptor.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "FileTypeRequestInterceptor.h"
#include <QtCore/QDebug>
#include "RequestFilters.h"
void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
RequestFilters::interceptHFWebEngineRequest(info);
RequestFilters::interceptFileType(info);
}

View file

@ -0,0 +1,26 @@
//
// FileTypeRequestInterceptor.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_FileTypeRequestInterceptor_h
#define hifi_FileTypeRequestInterceptor_h
#include <QWebEngineUrlRequestInterceptor>
class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor {
public:
FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {};
virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override;
};
#endif // hifi_FileTypeRequestInterceptor_h

View file

@ -10,35 +10,12 @@
//
#include "HFWebEngineRequestInterceptor.h"
#include "NetworkingConstants.h"
#include <QtCore/QDebug>
#include <AccountManager.h>
bool isAuthableHighFidelityURL(const QUrl& url) {
static const QStringList HF_HOSTS = {
"highfidelity.com", "highfidelity.io",
"metaverse.highfidelity.com", "metaverse.highfidelity.io"
};
const auto& scheme = url.scheme();
const auto& host = url.host();
return (scheme == "https" && HF_HOSTS.contains(host)) ||
((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
}
#include "RequestFilters.h"
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
// check if this is a request to a highfidelity URL
if (isAuthableHighFidelityURL(info.requestUrl())) {
// if we have an access token, add it to the right HTTP header for authorization
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->hasValidAccessToken()) {
static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
}
}
RequestFilters::interceptHFWebEngineRequest(info);
}

View file

@ -0,0 +1,65 @@
//
// RequestFilters.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "RequestFilters.h"
#include "NetworkingConstants.h"
#include <QtCore/QDebug>
#include <AccountManager.h>
namespace {
bool isAuthableHighFidelityURL(const QUrl& url) {
static const QStringList HF_HOSTS = {
"highfidelity.com", "highfidelity.io",
"metaverse.highfidelity.com", "metaverse.highfidelity.io"
};
const auto& scheme = url.scheme();
const auto& host = url.host();
return (scheme == "https" && HF_HOSTS.contains(host)) ||
((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
}
bool isScript(const QString filename) {
return filename.endsWith(".js", Qt::CaseInsensitive);
}
bool isJSON(const QString filename) {
return filename.endsWith(".json", Qt::CaseInsensitive);
}
}
void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) {
// check if this is a request to a highfidelity URL
if (isAuthableHighFidelityURL(info.requestUrl())) {
// if we have an access token, add it to the right HTTP header for authorization
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->hasValidAccessToken()) {
static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
}
}
}
void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) {
QString filename = info.requestUrl().fileName();
if (isScript(filename) || isJSON(filename)) {
static const QString CONTENT_HEADER = "Accept";
static const QString TYPE_VALUE = "text/plain,text/html";
info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit());
}
}

View file

@ -0,0 +1,28 @@
//
// RequestFilters.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_RequestFilters_h
#define hifi_RequestFilters_h
#include <QObject>
#include <QWebEngineUrlRequestInfo>
class RequestFilters : public QObject {
Q_OBJECT
public:
static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info);
static void interceptFileType(QWebEngineUrlRequestInfo& info);
};
#endif // hifi_RequestFilters_h

View file

@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() {
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
}
_webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) {
_webSurface->load("WebEntityView.qml", [&](QQmlContext* context, QObject* obj) {
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject));
});