Skip to content

Commit

Permalink
Rewriting QWebEngine configuration for Qt >= 5.15.0 (security); addin…
Browse files Browse the repository at this point in the history
…g macOS build targets to Makefile #1506
  • Loading branch information
dvorka committed Feb 4, 2024
1 parent f5bb19e commit 033ad7e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 107 deletions.
155 changes: 55 additions & 100 deletions app/src/qt/mindforger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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=<HOME> ... 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<size_t>(newArgc)];
Expand All @@ -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<size_t>(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<size_t>(newArgc)];
newArgv[0] = argv[0];
int i=1;
for (int v=0; v<injectWebEngineArgc; i++, v++) {
newArgv[i] = injectWebEngineArgv[v];
}
for(int v=1; v<argc; v++, i++) {
newArgv[i] = argv[v];
}
newArgv[newArgc-1] = nullptr;
#endif // DEBUG_WEBENGINE_SECURITY_QT_5_15
#endif // Qt version

#ifdef DO_MF_DEBUG
MF_DEBUG("argv: " << newArgc << endl);
for(int i=0; i<newArgc; i++) {
if(newArgv[i] == nullptr) {
MF_DEBUG(" " << i << " NULL" << endl);
break;
}
MF_DEBUG(" " << i << " " << newArgv[i] << endl);
}
#endif

#ifdef DO_MF_DEBUG
MF_DEBUG("argv: " << newArgc << endl);
for(int i=0; i<newArgc; i++) {
if(newArgv[i] == nullptr) {
MF_DEBUG(" " << i << " NULL" << endl);
break;
}
MF_DEBUG(" " << i << " " << newArgv[i] << endl);
}
#endif

QApplication mindforgerApplication(newArgc, newArgv);
#else
QApplication mindforgerApplication(argc, argv);
#endif

#ifdef MF_DEBUG_QRC
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
MF_DEBUG(it.next() << endl);
}
#endif
QApplication::setApplicationName("MindForger");
QApplication::setApplicationVersion(MINDFORGER_VERSION);
mindforgerApplication.setWindowIcon(QIcon(":/icons/mindforger-icon.png"));

#ifndef DEBUG_WEBENGINE_SECURITY_QT_5_15
std::string useRepository{};
QString themeOptionValue{};
QString configurationFilePath{};
Expand Down Expand Up @@ -277,8 +236,8 @@ int main(int argc, char* argv[])
);
parser.addOption(configPathOption);

#if defined(__APPLE__) || defined(_WIN32)
// command line options passed to WebEngine to disable security
#if defined(__APPLE__) || defined(_WIN32)
// command line options which might be passed to WebEngine to control the security
QCommandLineOption macosDisableSecurityOption(QStringList() << "S" << "disable-web-security",
QCoreApplication::translate("main", "Disable WebEngine security to allow loading of images on macOS.")
);
Expand Down Expand Up @@ -307,8 +266,9 @@ int main(int argc, char* argv[])
QCoreApplication::translate("main", "Disable WebEngine security via acess file from file on macOS.")
);
parser.addOption(macosAcessFileFromFile);
#endif
#endif
#endif // >= 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
Expand Down Expand Up @@ -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{};
Expand Down
5 changes: 5 additions & 0 deletions app/src/qt/note_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
4 changes: 4 additions & 0 deletions app/src/qt/outline_header_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
47 changes: 41 additions & 6 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion lib/src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 033ad7e

Please sign in to comment.