Merge branch 'kasen/core' into feature/inspect

This commit is contained in:
David Rowe 2020-01-12 15:39:52 +13:00
commit f5c1906479
20 changed files with 195 additions and 98 deletions

View file

@ -164,7 +164,7 @@ endif()
if downloadVcpkg:
if "HIFI_VCPKG_BOOTSTRAP" in os.environ:
print("Cloning vcpkg from github to {}".format(self.path))
hifi_utils.executeSubprocess(['git', 'clone', 'git@github.com:microsoft/vcpkg.git', self.path])
hifi_utils.executeSubprocess(['git', 'clone', 'https://github.com/microsoft/vcpkg', self.path])
print("Bootstrapping vcpkg")
hifi_utils.executeSubprocess([self.bootstrapCmd], folder=self.path)
else:

View file

@ -15,9 +15,9 @@ set(CUSTOM_INTERFACE_QRC_PATHS "")
find_npm()
#if (BUILD_TOOLS AND NPM_EXECUTABLE)
# add_custom_qrc_path(CUSTOM_INTERFACE_QRC_PATHS "${CMAKE_SOURCE_DIR}/tools/jsdoc/out/hifiJSDoc.json" "auto-complete/hifiJSDoc.json")
#endif ()
if (BUILD_TOOLS AND NPM_EXECUTABLE)
add_custom_qrc_path(CUSTOM_INTERFACE_QRC_PATHS "${CMAKE_SOURCE_DIR}/tools/jsdoc/out/hifiJSDoc.json" "auto-complete/hifiJSDoc.json")
endif ()
set(RESOURCES_QRC ${CMAKE_CURRENT_BINARY_DIR}/resources.qrc)
set(RESOURCES_RCC ${CMAKE_CURRENT_SOURCE_DIR}/compiledResources/resources.rcc)
@ -182,10 +182,10 @@ else ()
endif ()
#if (BUILD_TOOLS AND NPM_EXECUTABLE)
if (BUILD_TOOLS AND NPM_EXECUTABLE)
# require JSDoc to be build before interface is deployed
# add_dependencies(resources jsdoc)
#endif()
add_dependencies(resources jsdoc)
endif()
add_dependencies(${TARGET_NAME} resources)
@ -326,9 +326,9 @@ if (APPLE)
"${CMAKE_SOURCE_DIR}/scripts"
"${RESOURCES_DEV_DIR}/scripts"
# copy JSDoc files beside the executable
#COMMAND "${CMAKE_COMMAND}" -E copy_directory
# "${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
# "${RESOURCES_DEV_DIR}/jsdoc"
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
"${RESOURCES_DEV_DIR}/jsdoc"
# copy the resources files beside the executable
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${RESOURCES_RCC}"
@ -381,9 +381,9 @@ else()
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
# copy JSDoc files beside the executable
#COMMAND "${CMAKE_COMMAND}" -E copy_directory
# "${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
# "${INTERFACE_EXEC_DIR}/jsdoc"
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
"${INTERFACE_EXEC_DIR}/jsdoc"
)
# link target to external libraries

View file

@ -40,7 +40,7 @@ Controls.WebView {
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
function onWebEventReceived(event) {
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof event === "string" && event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
}
}

View file

@ -229,7 +229,7 @@ Item {
}
function openDocs() {
Qt.openUrlExternally("https://docs.highfidelity.com/create/avatars/package-avatar.html");
Qt.openUrlExternally("https://docs.projectathena.dev/create/avatars/package-avatar.html");
}
function openVideo() {

View file

@ -128,6 +128,8 @@ ShadowRectangle {
}
}
// FIXME: Link to a Project Athena version of the video.
/*
RalewayButton {
id: video
visible: false
@ -141,6 +143,12 @@ ShadowRectangle {
onClicked: videoButtonClicked()
}
*/
// Temporary placeholder for video button.
Rectangle {
id: video
visible: false
}
RalewayButton {
id: docs

View file

@ -44,7 +44,11 @@ Item {
HifiControls.Button {
id: uploadButton
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: AvatarPackagerCore.currentAvatarProject && !AvatarPackagerCore.currentAvatarProject.fst.hasMarketplaceID && !root.hasSuccessfullyUploaded
*/
visible: false
enabled: Account.loggedIn
anchors.verticalCenter: parent.verticalCenter
@ -62,7 +66,11 @@ Item {
HifiControls.Button {
id: updateButton
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.fst.hasMarketplaceID && !root.hasSuccessfullyUploaded
*/
visible: false
enabled: Account.loggedIn
anchors.verticalCenter: parent.verticalCenter
@ -79,7 +87,12 @@ Item {
}
Item {
anchors.fill: parent
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: root.hasSuccessfullyUploaded
*/
visible: false;
HifiControls.Button {
enabled: Account.loggedIn
@ -115,6 +128,22 @@ Item {
onClicked: AvatarPackagerCore.currentAvatarProject.openInInventory()
}
}
// FIXME: Remove if "Upload" button is reinstated.
HifiControls.Button {
id: openDirectoryButton
visible: AvatarPackagerCore.currentAvatarProject
enabled: true
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Open Project Folder")
color: hifi.buttons.blue
colorScheme: root.colorScheme
width: 200
height: 40
onClicked: {
fileDialogHelper.openDirectory(fileDialogHelper.pathToUrl(AvatarPackagerCore.currentAvatarProject.projectFolderPath));
}
}
}
Rectangle {
@ -263,13 +292,58 @@ Item {
color: 'white'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorsGlyph.bottom
wrapMode: Text.Wrap
}
RalewayRegular {
id: notForSaleMessage
visible: root.hasSuccessfullyUploaded
color: 'white'
linkColor: '#00B4EF'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.top: doctorStatusMessage.bottom
anchors.topMargin: 10
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "This item is not for sale yet, <a href='#'>learn more</a>."
onLinkActivated: {
Qt.openUrlExternally("https://docs.projectathena.dev/sell/add-item/upload-avatar.html");
}
}
RalewayRegular {
id: showErrorsLink
color: 'white'
linkColor: '#00B4EF'
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.hasErrors
anchors {
top: notForSaleMessage.bottom
horizontalCenter: parent.horizontalCenter
}
size: 28
text: "<a href='toggle'>View all errors</a>"
onLinkActivated: {
avatarPackager.state = AvatarPackagerState.avatarDoctorErrorReport;
}
}
RalewayRegular {
id: infoMessage
@ -297,60 +371,14 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: doctorStatusMessage.bottom
anchors.bottom: showFilesText.top
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "You can upload your files to our servers to always access them, and to make your avatar visible to other users."
}
RalewayRegular {
id: notForSaleMessage
visible: root.hasSuccessfullyUploaded
color: 'white'
linkColor: '#00B4EF'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.top: infoMessage.bottom
anchors.topMargin: 10
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "This item is not for sale yet, <a href='#'>learn more</a>."
onLinkActivated: {
Qt.openUrlExternally("https://docs.highfidelity.com/sell/add-item/upload-avatar.html");
}
}
RalewayRegular {
id: showErrorsLink
color: 'white'
linkColor: '#00B4EF'
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.hasErrors
anchors {
top: notForSaleMessage.visible ? notForSaleMessage.bottom : infoMessage .bottom
bottom: showFilesText.top
horizontalCenter: parent.horizontalCenter
}
size: 28
text: "<a href='toggle'>View all errors</a>"
onLinkActivated: {
avatarPackager.state = AvatarPackagerState.avatarDoctorErrorReport;
}
// FIXME: Restore original text if ability to upload to hosted location is added.
//text: "You can upload your files to our servers to always access them, and to make your avatar visible to other users."
text: "Your files are ready to be uploaded to a server to make your avatar visible to other users."
}
HifiControls.Button {
@ -389,8 +417,13 @@ Item {
Rectangle {
id: loginRequiredMessage
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: !Account.loggedIn
height: !Account.loggedIn ? loginRequiredTextRow.height + 20 : 0
*/
visible: false
height: 0
anchors {
bottom: parent.bottom

View file

@ -200,7 +200,7 @@ Rectangle {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof message === "string" && message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}

View file

@ -118,7 +118,7 @@ Windows.ScrollingWindow {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof message === "string" && message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}

View file

@ -55,7 +55,7 @@ static QStringList HAND_MAPPING_SUFFIXES = {
"HandThumb1",
};
const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.highfidelity.com/create/avatars/package-avatar.html");
const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.projectathena.dev/create/avatars/package-avatar.html");
AvatarDoctor::AvatarDoctor(const QUrl& avatarFSTFileUrl) :
_avatarFSTFileUrl(avatarFSTFileUrl) {

View file

@ -95,7 +95,7 @@ public:
static bool isValidNewProjectName(const QString& projectPath, const QString& projectName);
static QString getDefaultProjectsPath() {
return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/High Fidelity Projects";
return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Project Athena Projects";
}
signals:

View file

@ -85,9 +85,9 @@
#include "MIDIEvent.h"
#include "SettingHandle.h"
// #include "SettingManager.h"
// #include "SettingInterface.h"
// #include "SettingHelpers.h"
#include <AddressManager.h>
#include <NetworkingConstants.h>
const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS {
"com.highfidelity.experimental.enableExtendedJSExceptions"
@ -2361,32 +2361,58 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
} else if (testConstructor.isError()) {
exception = testConstructor;
}
}
else {
// ENTITY SCRIPT WHITELIST STARTS HERE
} else {
// ENTITY SCRIPT WHITELIST STARTS HERE
auto nodeList = DependencyManager::get<NodeList>();
bool passList = false; // assume unsafe
QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
QList<QString> safeURLS = { "" };
safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);
QList<QString> safeURLPrefixes = { "file:///", "atp:", "cache:" };
safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);
// PULL SAFEURLS FROM INTERFACE.JSON Settings
// IF WHITELIST IS DISABLED IN SETTINGS
bool whitelistEnabled = Setting::Handle<bool>("private/whitelistEnabled", true).get();
if (!whitelistEnabled) {
passList = true;
}
// PULL SAFEURLS FROM INTERFACE.JSON Settings
QVariant raw = Setting::Handle<QVariant>("private/settingsSafeURLS").get();
QStringList settingsSafeURLS = raw.toString().trimmed().split(QRegExp("\\s*[,\r\n]+\\s*"), QString::SkipEmptyParts);
safeURLS += settingsSafeURLS;
safeURLPrefixes += settingsSafeURLS;
// END PULL SAFEURLS FROM INTERFACE.JSON Settings
bool isInWhitelist = false; // assume unsafe
for (const auto& str : safeURLS) {
qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
<< scriptOrURL.startsWith(str);
if (!str.isEmpty() && scriptOrURL.startsWith(str)) {
isInWhitelist = true;
qCDebug(scriptengine) << whitelistPrefix << "Script approved.";
break; // bail early since we found a match
// GET CURRENT DOMAIN WHITELIST BYPASS, IN CASE AN ENTIRE DOMAIN IS WHITELISTED
QString currentDomain = DependencyManager::get<AddressManager>()->getDomainURL().host();
QString domainSafeIP = nodeList->getDomainHandler().getHostname();
QString domainSafeURL = URL_SCHEME_HIFI + "://" + currentDomain;
for (const auto& str : safeURLPrefixes) {
if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) {
qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed. Current Domain Host: "
<< nodeList->getDomainHandler().getHostname()
<< "Current Domain: " << currentDomain;
passList = true;
}
}
if (!isInWhitelist) {
// END CURRENT DOMAIN WHITELIST BYPASS
// START CHECKING AGAINST THE WHITELIST
if (ScriptEngine::getContext() == "entity_server") { // If running on the server, do not engage whitelist.
passList = true;
} else if (!passList) { // If waved through, do not engage whitelist.
for (const auto& str : safeURLPrefixes) {
qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
<< scriptOrURL.startsWith(str);
if (!str.isEmpty() && scriptOrURL.startsWith(str)) {
passList = true;
qCDebug(scriptengine) << whitelistPrefix << "Script approved.";
break; // bail early since we found a match
}
}
}
// END CHECKING AGAINST THE WHITELIST
if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown.
qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0");
} else {

View file

@ -16,6 +16,8 @@
#include "ScriptEngine.h"
#include "ScriptEngineLogging.h"
WebSocketClass::WebSocketClass(QScriptEngine* engine, QString url) :
_webSocket(new QWebSocket()),
_engine(engine)
@ -34,10 +36,11 @@ WebSocketClass::WebSocketClass(QScriptEngine* engine, QWebSocket* qWebSocket) :
void WebSocketClass::initialize() {
connect(_webSocket, &QWebSocket::disconnected, this, &WebSocketClass::handleOnClose);
connect(_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketClass::handleOnMessage);
connect(_webSocket, &QWebSocket::binaryMessageReceived, this, &WebSocketClass::handleOnBinaryMessage);
connect(_webSocket, &QWebSocket::connected, this, &WebSocketClass::handleOnOpen);
connect(_webSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error), this,
&WebSocketClass::handleOnError);
_binaryType = QStringLiteral("blob");
_binaryType = QStringLiteral("arraybuffer");
}
QScriptValue WebSocketClass::constructor(QScriptContext* context, QScriptEngine* engine) {
@ -53,7 +56,12 @@ WebSocketClass::~WebSocketClass() {
}
void WebSocketClass::send(QScriptValue message) {
_webSocket->sendTextMessage(message.toString());
if (message.isObject()) {
QByteArray ba = qscriptvalue_cast<QByteArray>(message);
_webSocket->sendBinaryMessage(ba);
} else {
_webSocket->sendTextMessage(message.toString());
}
}
void WebSocketClass::close() {
@ -97,6 +105,25 @@ void WebSocketClass::handleOnMessage(const QString& message) {
}
}
void WebSocketClass::handleOnBinaryMessage(const QByteArray& message) {
if (_onMessageEvent.isFunction()) {
QScriptValueList args;
QScriptValue arg = _engine->newObject();
QScriptValue data = _engine->newVariant(QVariant::fromValue(message));
QScriptValue ctor = _engine->globalObject().property("ArrayBuffer");
auto array = qscriptvalue_cast<ArrayBufferClass*>(ctor.data());
QScriptValue arrayBuffer;
if (!array) {
qCWarning(scriptengine) << "WebSocketClass::handleOnBinaryMessage !ArrayBuffer";
} else {
arrayBuffer = _engine->newObject(array, data);
}
arg.setProperty("data", arrayBuffer);
args << arg;
_onMessageEvent.call(QScriptValue(), args);
}
}
void WebSocketClass::handleOnOpen() {
if (_onOpenEvent.isFunction()) {
_onOpenEvent.call();

View file

@ -123,6 +123,7 @@ private slots:
void handleOnClose();
void handleOnError(QAbstractSocket::SocketError error);
void handleOnMessage(const QString& message);
void handleOnBinaryMessage(const QByteArray& message);
void handleOnOpen();
};

View file

@ -1,4 +1,4 @@
The High Fidelity JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the High Fidelity metaverse. With it, you can build great content, customize avatars, play audio and so much more.
The Project Athena JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the High Fidelity metaverse. With it, you can build great content, customize avatars, play audio and so much more.
You are most likely to interact with these APIs:
@ -6,4 +6,4 @@ You are most likely to interact with these APIs:
* The **[AvatarList](AvatarList.html)**, **[MyAvatar](MyAvatar.html)**, and **[Avatar](Avatar.html)** namespaces affect your personal avatars, and lets you get information on other people's avatars.
* The **[Script](Script.html)** namespace lets you to connect callbacks from your client to script, such as functionality that is dependent on time (`Script.update`, `Script.setTimeout`, `Script.setInterval`, etc), connect paths relatively to assets (`Script.resolvePath`), refer to other scripts (`Script.require`, `Script.include`), or connect functions to events which occur when the script is turned off (`Script.scriptEnding`).
To learn more about using High Fidelity and exploring the metaverse, visit the [High Fidelity Documentation](https://docs.highfidelity.com).
To learn more about using High Fidelity and exploring the metaverse, visit the [Project Athena Documentation](https://docs.projectathena.dev).

View file

@ -697,7 +697,7 @@ exports.publish = function(taffyData, opts, tutorials) {
var files = find({kind: 'file'});
var packages = find({kind: 'package'});
generate('', 'High Fidelity API Reference',
generate('', 'Project Athena API Reference',
packages.concat(
[{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
).concat(files),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View file

@ -67,6 +67,7 @@ h1
font-size: 3.25rem;
text-align: center;
margin: 50px 25px 25px;
line-height: 100%;
}
h2

View file

@ -12,15 +12,16 @@
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<link href="images/fav-icon.ico" rel="shortcut icon">
</head>
<body>
<div class="nav-header">
<p><a href="https://www.highfidelity.com"><img src="images/white-logo.png" width="214px" /></a></p>
<p><a href="https://projectathena.io"><img src="images/project-athena-logo.png" width="214px" /></a></p>
<?js if (env.conf.docdash.search) { ?>
<input type="text" class="search-input" id="nav-search" placeholder="Search API Docs ..." />
<?js } ?>
<p><a href="https://docs.highfidelity.com">Looking for <strong>High Fidelity</strong><br /> Documentation?</a></p>
<p><a href="https://docs.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p>
</div>
<nav>