From 033ad7ebeb900ca44a56371c4ff0ac19f22d268e Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 4 Feb 2024 17:45:05 +0100 Subject: [PATCH] Rewriting QWebEngine configuration for Qt >= 5.15.0 (security); adding macOS build targets to Makefile #1506 --- app/src/qt/mindforger.cpp | 155 +++++++++++-------------------- app/src/qt/note_view.h | 5 + app/src/qt/outline_header_view.h | 4 + build/Makefile | 47 ++++++++-- lib/src/debug.h | 1 - 5 files changed, 105 insertions(+), 107 deletions(-) diff --git a/app/src/qt/mindforger.cpp b/app/src/qt/mindforger.cpp index fb129d67..f64e3a3f 100644 --- a/app/src/qt/mindforger.cpp +++ b/app/src/qt/mindforger.cpp @@ -130,42 +130,53 @@ int main(int argc, char* argv[]) // default terminal macOS environment: TERM=xterm-256color DISPLAY= #endif - // Stupid & ugly: QWebEngine @ macOS requires extra parameter(s) to - // allow access to local files (like images) to QApplication (security). - // Parameter differ Qt version to Qt version as diffent versions - // bundle different Chromium versions. - // - // Qt 5.9.9 - // --disable-web-security ... same origin // - // Qt 5.15.2 ~ Chrome 83 ~ I did NOT find params to enable filesystem access - // --user-data-dir= ... user data dir - // --disable-web-security ... same origin - // --disable-site-isolation-trials + // SECURITY: WebKit vs WebEngine in Qt // - // QApplication args assembly: - // - order in ^ examples matters + // Stupid & ugly: QWebEngine @ macOS/Win requires extra parameter(s) to + // allow access to local files (like images) to QApplication (security). + // MindForger generates HTML from Markdown and uses QWebEngine to render it, + // so it needs to allow access to files (like images) references from the HTML. + // Qt parameters to QWebEngine differ Qt version to Qt version as different + // versions bundle different Chromium versions. (Qt uses QWebKit on Linux) // - // Additional hints: - // - HTML is rendered by QWebEngine on macOS - // - QWebEngine is Chromium wrapper - // https://doc.qt.io/qt-5/qtwebengine-overview.html - // https://doc.qt.io/qt-5/qtwebengine-features.html + // Qt 5.9.9 + // * --disable-web-security ... same origin // - // Debugging: + // Qt 5.15.2 + // * --disable-web-security ... can go AWAY + // * base URL: file:// // - // - DEBUG_WEBENGINE_SECURITY_QT_5_15 -//#define DEBUG_WEBENGINE_SECURITY_QT_5_15 + // If DESPERATE in the future, then get SHA which edited this line from Git history. + // (it removed code which can debug WebEngine security parameters on macOS/Win) // // Resources: - // - https://doc.qt.io/qt-5/qtwebengine-index.html - // - https://doc.qt.io/qt-5/qtwebengine-debugging.html#using-command-line-arguments - // - https://wiki.qt.io/QtWebEngine/ChromiumVersions - // - https://stackoverflow.com/questions/35432749/disable-web-security-in-chrome-48 - // ^ changes in required parameters with disable-web-security + // * https://github.com/dvorka/mindforger/issues/1506 + // explanation of the problem and solution + // * https://github.com/dvorka/mindforger/compare/dev/1.55.1...shlemiel:mindforger_poc0:dev/1.55.1 + // POC of the solution (what to change for Qt 5.15.0+): + // - note_view.h (baseURL) and outline_header_view.h (baseURL) QUrl from "" to "file://" // -#if defined(__APPLE__) || defined(_WIN32) - #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + // Additional resources: + // - QWebEngine as Chromium wrapper: + // - https://doc.qt.io/qt-5/qtwebengine-index.html + // - https://doc.qt.io/qt-5/qtwebengine-overview.html + // - https://doc.qt.io/qt-5/qtwebengine-features.html + // - QWebEngine debugging: + // - https://doc.qt.io/qt-5/qtwebengine-debugging.html#using-command-line-arguments + // - https://wiki.qt.io/QtWebEngine/ChromiumVersions + // - Chromium command line: + // - switches: + // - --disable-web-security + // - --allow-file-access-from-files + // - --no-sandbox + // - --user-data-dir + // - --single-process + // - --disable-site-isolation-trials + // - https://stackoverflow.com/questions/35432749/disable-web-security-in-chrome-48 + // ^ changes in required parameters with disable-web-security + +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) && (defined(__APPLE__) || defined(_WIN32)) char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security"; int newArgc = argc + 1 + 1; char** newArgv = new char*[static_cast(newArgc)]; @@ -175,79 +186,27 @@ int main(int argc, char* argv[]) newArgv[i] = argv[i-1]; } newArgv[newArgc-1] = nullptr; - #else - // IMPROVE: new Chromium @ QWebEngine requires more parameters, but - // I didn't find working configuration which would allow loading - // of images on macOS BigSur - char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security"; - char ARG_USER_DATA_DIR[] = "--user-data-dir=/Users/dvorka/tmp"; - char ARG_SINGLE_PROCESS[] = "--single-process"; - char ARG_NO_SANDBOX[] = "--no-sandbox"; - char ARG_DISABLE_ISOLATION_TRIALS[] = "--disable-site-isolation-trials"; - char ARG_ALLOW_FILE_ACCESS_FROM_FILES[] = "--allow-file-access-from-files"; - - #ifdef DEBUG_WEBENGINE_SECURITY_QT_5_15 - int newArgc = 6; - char** newArgv = new char*[static_cast(newArgc)]; - newArgv[0] = argv[0]; - newArgv[1] = "--args"; - newArgv[2] = ARG_USER_DATA_DIR; - newArgv[3] = ARG_DISABLE_WEB_SECURITY; - newArgv[4] = "/Users/dvorka/mf-devel/mf-copy"; - newArgv[5] = NULL; - - #else // DEBUG_WEBENGINE_SECURITY_QT_5_15 - char* injectWebEngineArgv[] = { - ARG_USER_DATA_DIR, - ARG_DISABLE_WEB_SECURITY, - ARG_DISABLE_ISOLATION_TRIALS, - ARG_SINGLE_PROCESS, - ARG_NO_SANDBOX, - ARG_ALLOW_FILE_ACCESS_FROM_FILES - }; - int injectWebEngineArgc = 6; - - int newArgc = argc + injectWebEngineArgc + 1; - char** newArgv = new char*[static_cast(newArgc)]; - newArgv[0] = argv[0]; - int i=1; - for (int v=0; v= 5.15.0 + #endif // APPLE or WIN + QCommandLineOption versionOption=parser.addVersionOption(); QCommandLineOption helpOption=parser.addHelpOption(); // process the actual command line arguments given by the user @@ -341,11 +301,6 @@ int main(int argc, char* argv[]) } } // else there are no parameters and options > simply load GUI -# else // DEBUG_WEBENGINE_SECURITY_QT_5_15 - QString configurationFilePath{"/Users/dvorka/.mindforger.md"}; - QString themeOptionValue{}; - std::string useRepository{}; -#endif // DEBUG_WEBENGINE_SECURITY_QT_5_15 // load configuration m8r::MarkdownConfigurationRepresentation mdConfigRepresentation{}; diff --git a/app/src/qt/note_view.h b/app/src/qt/note_view.h index d794a8e7..f4cf5906 100644 --- a/app/src/qt/note_view.h +++ b/app/src/qt/note_view.h @@ -95,7 +95,12 @@ class NoteView : public QWidget void setZoomFactor(qreal factor) { noteViewer->setZoomFactor(factor); } + // IMPORTANT: file:// base URL is IMPORTANT for QtWebEngine to load local images on Qt >=5.12.0 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) && (defined(__APPLE__) || defined(_WIN32)) + void setHtml(const QString& html, const QUrl& baseUrl = QUrl("file://")) { +#else void setHtml(const QString& html, const QUrl& baseUrl = QUrl()) { +#endif noteViewer->setHtml(html, baseUrl); } void giveViewerFocus() { diff --git a/app/src/qt/outline_header_view.h b/app/src/qt/outline_header_view.h index e9f32e14..fa12b57d 100644 --- a/app/src/qt/outline_header_view.h +++ b/app/src/qt/outline_header_view.h @@ -96,7 +96,11 @@ class OutlineHeaderView : public QWidget void setZoomFactor(qreal factor) { headerViewer->setZoomFactor(factor); } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) && (defined(__APPLE__) || defined(_WIN32)) + void setHtml(const QString& html, const QUrl& baseUrl = QUrl("file://")) { +#else void setHtml(const QString& html, const QUrl& baseUrl = QUrl()) { +#endif headerViewer->setHtml(html, baseUrl); } void giveViewerFocus() { diff --git a/build/Makefile b/build/Makefile index 44378981..b086f4a9 100644 --- a/build/Makefile +++ b/build/Makefile @@ -36,12 +36,42 @@ MF_LANG := "en" DISTRO := "bionic" # CPU cores thant can be used to build the project CPU_CORES := 7 +# Qt version to be used by MindForger +# MF_QT_VERSION := 5.9.9 +MF_QT_VERSION := 5.15.2 + +# +# OS detection +# + +# uname returns the operating system name: Darwin, Linux, etc. +UNAME := $(shell uname) +ifeq ($(UNAME), Darwin) + # this sets QTDIR and PATH shell (!) and make environment variables on macOS + QTDIR := /Users/dvorka/Qt/$(MF_QT_VERSION)/clang_64 + PATH := /Users/dvorka/Qt/$(MF_QT_VERSION)/clang_64/bin:/Library/Developer/CommandLineTools/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$(PATH) +endif + # # targets # +.PHONY: diagnostics +diagnostics: + @echo "MindForger diagnostics:" + @echo " MINDFORGER_VERSION: $(MINDFORGER_VERSION)" + @echo " MINDFORGER_RELEASE_DIR: $(MINDFORGER_RELEASE_DIR)" + @echo " MF_MAKER_WORKING_DIR: $(MF_MAKER_WORKING_DIR)" + @echo " CLASS_NAME: $(CLASS_NAME)" + @echo " MF_LANG: $(MF_LANG)" + @echo " DISTRO: $(DISTRO)" + @echo " CPU_CORES: $(CPU_CORES)" + @echo " PATH: ${PATH}" + @echo " QTDIR: ${QTDIR}" + + .PHONY: help help: ## make targets help @echo "MindForger Swiss knife help:" @@ -103,7 +133,7 @@ gen-ui-class: ## generate UI C++ class skeleton: CLASS_NAME=My_Class ../app/mindforger: ../Makefile @echo "Building PRODUCTION MindForger executable..." - cd .. && make -j $(CPU_CORES) ; cd build + cd .. && make -j $(VENDOR) ; cd build @echo "If build succeeded, then MindForger executable can be found in:\n app/mindforger" ls -al ../app/mindforger @@ -116,11 +146,13 @@ build: clean-app ../app/mindforger ## build production MindForger application bi build-dev: clean-app ## build development MindForger application binary @echo "Building DEV MindForger executable..." cd .. && qmake -r mindforger.pro DEFINES+=DO_MF_DEBUG && make -j $(CPU_CORES) ; cd .. - @echo "If build succeeded, then MindForger executable can be found in:\n app/mindforger" +ifeq ($(UNAME), Darwin) + @echo "\nIf build succeeded, then MindForger executable can be found in:\n app/mindforger.app/Contents/MacOS/mindforger" + ls -al ../app/mindforger.app/Contents/MacOS/mindforger +else + @echo "\nIf build succeeded, then MindForger executable can be found in:\n app/mindforger" ls -al ../app/mindforger - - -# TODO: build-dev-clang +endif .PHONY: build-rc @@ -160,10 +192,13 @@ run-ci: build-ci ## run MindForger CI build run-dev: build-dev ## run MindForger development build +ifeq ($(UNAME), Darwin) + cd ../app/mindforger.app/Contents/MacOS && ./mindforger /Users/dvorka/mf-devel/mf-copy +else cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/library-trainer # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/computer-hw.md # cd ../app && pwd && ./mindforger /home/dvorka/mf-devel/bug-copy-image - +endif # # install diff --git a/lib/src/debug.h b/lib/src/debug.h index df62faee..59a12987 100644 --- a/lib/src/debug.h +++ b/lib/src/debug.h @@ -34,7 +34,6 @@ // enable/disable verbose debug of particular components //#define MF_DEBUG_HTML //#define MF_DEBUG_ASYNC_TASKS - //#define MF_DEBUG_QRC //#define MF_DEBUG_L10N //#define MF_DEBUG_AUTOLINKING //#define MF_DEBUG_LIBRARY