summaryrefslogtreecommitdiffstats
path: root/src/core/web_engine_library_info.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/web_engine_library_info.cpp')
-rw-r--r--src/core/web_engine_library_info.cpp311
1 files changed, 201 insertions, 110 deletions
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index 9c99e7e22..e71153899 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qtwebenginecoreglobal_p.h"
#include "web_engine_library_info.h"
#include "base/base_paths.h"
@@ -45,8 +10,11 @@
#include "base/files/file_util.h"
#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/common/content_paths.h"
+#include "sandbox/policy/switches.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
+
#include "type_conversion.h"
#include <QByteArray>
@@ -55,8 +23,12 @@
#include <QFileInfo>
#include <QLibraryInfo>
#include <QLocale>
+#include <QLoggingCategory>
#include <QStandardPaths>
-#include <QString>
+
+#if defined(Q_OS_WIN)
+#include <windows.h>
+#endif
#ifndef QTWEBENGINEPROCESS_NAME
#error "No name defined for QtWebEngine's process"
@@ -64,6 +36,8 @@
using namespace QtWebEngineCore;
+Q_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo")
+
namespace {
QString fallbackDir() {
@@ -71,19 +45,19 @@ QString fallbackDir() {
return directory;
}
-#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
static inline CFBundleRef frameworkBundle()
{
- return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.Qt.QtWebEngineCore"));
+ return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.QtWebEngineCore"));
}
-static QString getPath(CFBundleRef frameworkBundle)
+static QString getBundlePath(CFBundleRef frameworkBundle)
{
QString path;
// The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
// We use it for the other OS X versions as well to make sure it works and because
// the directory structure should be the same.
- if (qApp->applicationName() == QLatin1String(QTWEBENGINEPROCESS_NAME)) {
+ if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) {
path = QDir::cleanPath(qApp->applicationDirPath() % QLatin1String("/../../../.."));
} else if (frameworkBundle) {
CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle);
@@ -101,12 +75,12 @@ static QString getResourcesPath(CFBundleRef frameworkBundle)
// The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
// We use it for the other OS X versions as well to make sure it works and because
// the directory structure should be the same.
- if (qApp->applicationName() == QLatin1String(QTWEBENGINEPROCESS_NAME)) {
- path = getPath(frameworkBundle) % QLatin1String("/Resources");
+ if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) {
+ path = getBundlePath(frameworkBundle) % QLatin1String("/Resources");
} else if (frameworkBundle) {
CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle);
CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle);
- path = getPath(frameworkBundle) % QLatin1Char('/') % QString::fromCFString(resourcesRelativePath);
+ path = getBundlePath(frameworkBundle) % QLatin1Char('/') % QString::fromCFString(resourcesRelativePath);
CFRelease(resourcesRelativePath);
CFRelease(resourcesRelativeUrl);
}
@@ -114,7 +88,7 @@ static QString getResourcesPath(CFBundleRef frameworkBundle)
}
#endif
-#if defined(OS_MACOSX)
+#if defined(Q_OS_DARWIN)
static QString getMainApplicationResourcesPath()
{
QString resourcesPath;
@@ -146,10 +120,10 @@ QString subProcessPath()
{
static QString processPath;
if (processPath.isEmpty()) {
-#if defined(OS_WIN)
- const QString processBinary = QLatin1String(QTWEBENGINEPROCESS_NAME) % QLatin1String(".exe");
+#if defined(Q_OS_WIN)
+ const QString processBinary = QLatin1String(qWebEngineProcessName()) % QLatin1String(".exe");
#else
- const QString processBinary = QLatin1String(QTWEBENGINEPROCESS_NAME);
+ const QString processBinary = QLatin1String(qWebEngineProcessName());
#endif
QStringList candidatePaths;
@@ -158,25 +132,50 @@ QString subProcessPath()
// Only search in QTWEBENGINEPROCESS_PATH if set
candidatePaths << fromEnv;
} else {
-#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
- candidatePaths << getPath(frameworkBundle())
- % QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME);
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
+ candidatePaths << getBundlePath(frameworkBundle()) % QStringLiteral("/Helpers/")
+ % qWebEngineProcessName() % QStringLiteral(".app/Contents/MacOS/")
+ % qWebEngineProcessName();
#else
- candidatePaths << QLibraryInfo::location(QLibraryInfo::LibraryExecutablesPath)
+ candidatePaths << QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath)
+ % QLatin1Char('/') % processBinary;
+ candidatePaths << QLibraryInfo::path(QLibraryInfo::BinariesPath)
% QLatin1Char('/') % processBinary;
#endif
candidatePaths << QCoreApplication::applicationDirPath()
% QLatin1Char('/') % processBinary;
}
- for (const QString &candidate : qAsConst(candidatePaths)) {
+ for (const QString &candidate : std::as_const(candidatePaths)) {
if (QFileInfo::exists(candidate)) {
processPath = candidate;
+ qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %s",
+ qPrintable(candidate));
break;
}
}
- if (processPath.isEmpty())
- qFatal("Could not find %s", processBinary.toUtf8().constData());
+ if (processPath.isEmpty()) {
+ QStringList errorMessage;
+ errorMessage.append(
+ QStringLiteral("The following paths were searched for Qt WebEngine Process:"));
+ for (const QString &candidate : std::as_const(candidatePaths))
+ errorMessage.append(QStringLiteral(" ") % candidate);
+ errorMessage.append(QStringLiteral("but could not find it."));
+ if (fromEnv.isEmpty()) {
+ errorMessage.append(
+ QStringLiteral("You may override the default search path by using "
+ "QTWEBENGINEPROCESS_PATH environment variable."));
+ }
+ qFatal("%s", qPrintable(errorMessage.join('\n')));
+ }
+
+#if defined(Q_OS_WIN)
+ base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
+ if (!parsedCommandLine->HasSwitch(sandbox::policy::switches::kNoSandbox)) {
+ if (WebEngineLibraryInfo::isUNCPath(processPath) || WebEngineLibraryInfo::isRemoteDrivePath(processPath))
+ qCritical("Can not launch QtWebEngineProcess from network path if sandbox is enabled: %s.", processPath.toUtf8().constData());
+ }
+#endif
}
@@ -186,23 +185,55 @@ QString subProcessPath()
QString localesPath()
{
- static bool initialized = false;
- static QString potentialLocalesPath =
-#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
- getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_locales");
+ static QString potentialLocalesPath;
+ if (potentialLocalesPath.isEmpty()) {
+ QStringList candidatePaths;
+ const QString translationPakFilename =
+#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
+ QLatin1String(WebEngineLibraryInfo::getResolvedLocale() + ".pak");
#else
- QLibraryInfo::location(QLibraryInfo::TranslationsPath) % QDir::separator() % QLatin1String("qtwebengine_locales");
+ QLatin1String((WebEngineLibraryInfo::getResolvedLocale() + ".pak").c_str());
#endif
+ const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH");
+ if (!fromEnv.isEmpty()) {
+ // Only search in QTWEBENGINE_LOCALES_PATH if set
+ candidatePaths << fromEnv;
+ } else {
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
+ candidatePaths << getResourcesPath(frameworkBundle()) % QDir::separator()
+ % QLatin1String("qtwebengine_locales");
+#endif
+ candidatePaths << QLibraryInfo::path(QLibraryInfo::TranslationsPath) % QDir::separator()
+ % QLatin1String("qtwebengine_locales");
+ candidatePaths << fallbackDir();
+ }
- if (!initialized) {
- initialized = true;
- if (!QFileInfo::exists(potentialLocalesPath)) {
- qWarning("Installed Qt WebEngine locales directory not found at location %s. Trying application directory...", qPrintable(potentialLocalesPath));
- potentialLocalesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_locales");
+ for (const QString &candidate : std::as_const(candidatePaths)) {
+ if (QFileInfo::exists(candidate % QDir::separator() % translationPakFilename)) {
+ potentialLocalesPath = candidate;
+ qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %s",
+ qPrintable(candidate));
+ break;
+ }
}
- if (!QFileInfo::exists(potentialLocalesPath)) {
- qWarning("Qt WebEngine locales directory not found at location %s. Trying fallback directory... Translations MAY NOT not be correct.", qPrintable(potentialLocalesPath));
- potentialLocalesPath = fallbackDir();
+
+ if (potentialLocalesPath.isEmpty()) {
+ QStringList warningMessage;
+ warningMessage.append(
+ QStringLiteral("The following paths were searched for Qt WebEngine locales:"));
+ for (const QString &candidate : std::as_const(candidatePaths))
+ warningMessage.append(QStringLiteral(" ") % candidate);
+ warningMessage.append(
+ QStringLiteral(
+ "but could not find the translation file for the current locale: ")
+ % translationPakFilename);
+ if (fromEnv.isEmpty()) {
+ warningMessage.append(
+ QStringLiteral("You may override the default search paths by using "
+ "QTWEBENGINE_LOCALES_PATH environment variable."));
+ }
+ warningMessage.append(QStringLiteral("Translations WILL NOT be correct."));
+ qWarning("%s", qPrintable(warningMessage.join('\n')));
}
}
@@ -224,7 +255,7 @@ QString dictionariesPath()
candidatePaths << fromEnv;
} else {
// First try to find dictionaries near the application.
-#ifdef OS_MACOSX
+#ifdef Q_OS_DARWIN
QString resourcesDictionariesPath = getMainApplicationResourcesPath()
% QDir::separator() % QLatin1String("qtwebengine_dictionaries");
candidatePaths << resourcesDictionariesPath;
@@ -234,51 +265,80 @@ QString dictionariesPath()
candidatePaths << applicationDictionariesPath;
// Then try to find dictionaries near the installed library.
-#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
QString frameworkDictionariesPath = getResourcesPath(frameworkBundle())
% QLatin1String("/qtwebengine_dictionaries");
candidatePaths << frameworkDictionariesPath;
#endif
- QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath)
+ QString libraryDictionariesPath = QLibraryInfo::path(QLibraryInfo::DataPath)
% QDir::separator() % QLatin1String("qtwebengine_dictionaries");
candidatePaths << libraryDictionariesPath;
}
- for (const QString &candidate : qAsConst(candidatePaths)) {
+ for (const QString &candidate : std::as_const(candidatePaths)) {
if (QFileInfo::exists(candidate)) {
potentialDictionariesPath = candidate;
+ qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %s",
+ qPrintable(candidate));
break;
}
}
+
+ if (potentialDictionariesPath.isEmpty()) {
+ // return path for error message
+ potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator()
+ % QLatin1String("qtwebengine_dictionaries");
+ }
}
return potentialDictionariesPath;
}
#endif // QT_CONFIG(webengine_spellchecker)
-QString resourcesDataPath()
+QString resourcesPath()
{
- static bool initialized = false;
- static QString potentialResourcesPath =
-#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
- getResourcesPath(frameworkBundle());
-#else
- QLibraryInfo::location(QLibraryInfo::DataPath) % QLatin1String("/resources");
+ static QString potentialResourcesPath;
+ if (potentialResourcesPath.isEmpty()) {
+ QStringList candidatePaths;
+ const QString resourcesPakFilename = QLatin1String("qtwebengine_resources.pak");
+ const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH");
+ if (!fromEnv.isEmpty()) {
+ // Only search in QTWEBENGINE_RESOURCES_PATH if set
+ candidatePaths << fromEnv;
+ } else {
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
+ candidatePaths << getResourcesPath(frameworkBundle());
#endif
- if (!initialized) {
- initialized = true;
- if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
- qWarning("Qt WebEngine resources not found at %s. Trying parent directory...", qPrintable(potentialResourcesPath));
- potentialResourcesPath = QLibraryInfo::location(QLibraryInfo::DataPath);
+ candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath) % QDir::separator()
+ % QLatin1String("resources");
+ candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath);
+ candidatePaths << QCoreApplication::applicationDirPath();
+ candidatePaths << fallbackDir();
}
- if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
- qWarning("Qt WebEngine resources not found at %s. Trying application directory...", qPrintable(potentialResourcesPath));
- potentialResourcesPath = QCoreApplication::applicationDirPath();
+
+ for (const QString &candidate : std::as_const(candidatePaths)) {
+ if (QFileInfo::exists(candidate % QDir::separator() % resourcesPakFilename)) {
+ potentialResourcesPath = candidate;
+ qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %s",
+ qPrintable(candidate));
+ break;
+ }
}
- if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
- qWarning("Qt WebEngine resources not found at %s. Trying fallback directory... The application MAY NOT work.", qPrintable(potentialResourcesPath));
- potentialResourcesPath = fallbackDir();
+
+ if (potentialResourcesPath.isEmpty()) {
+ QStringList errorMessage;
+ errorMessage.append(QStringLiteral(
+ "The following paths were searched for Qt WebEngine resources:"));
+ for (const QString &candidate : std::as_const(candidatePaths))
+ errorMessage.append(QStringLiteral(" ") % candidate);
+ errorMessage.append(QStringLiteral("but could not find any."));
+ if (fromEnv.isEmpty()) {
+ errorMessage.append(
+ QStringLiteral("You may override the default search paths by using "
+ "QTWEBENGINE_RESOURCES_PATH environment variable."));
+ }
+ qFatal("%s", qPrintable(errorMessage.join('\n')));
}
}
@@ -291,17 +351,21 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
QString directory;
switch (key) {
case QT_RESOURCES_PAK:
- return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources.pak"));
+ return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources.pak"));
case QT_RESOURCES_100P_PAK:
- return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources_100p.pak"));
+ return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_100p.pak"));
case QT_RESOURCES_200P_PAK:
- return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources_200p.pak"));
+ return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_200p.pak"));
case QT_RESOURCES_DEVTOOLS_PAK:
- return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_devtools_resources.pak"));
+ return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_devtools_resources.pak"));
+#if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
+ case QT_FRAMEWORK_BUNDLE:
+ return toFilePath(getBundlePath(frameworkBundle()));
+#endif
case base::FILE_EXE:
case content::CHILD_PROCESS_EXE:
return toFilePath(subProcessPath());
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
case base::DIR_CACHE:
directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
break;
@@ -313,13 +377,15 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
directory = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
break;
case base::DIR_QT_LIBRARY_DATA:
- return toFilePath(resourcesDataPath());
+ return toFilePath(resourcesPath());
case ui::DIR_LOCALES:
return toFilePath(localesPath());
#if QT_CONFIG(webengine_spellchecker)
case base::DIR_APP_DICTIONARIES:
return toFilePath(dictionariesPath());
#endif
+ case base::DIR_ASSETS:
+ return toFilePath(resourcesPath());
default:
// Note: the path system expects this function to override the default
// behavior. So no need to log an error if we don't support a given
@@ -330,24 +396,49 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
return toFilePath(directory.isEmpty() ? fallbackDir() : directory);
}
-base::string16 WebEngineLibraryInfo::getApplicationName()
+std::u16string WebEngineLibraryInfo::getApplicationName()
{
return toString16(qApp->applicationName());
}
-std::string WebEngineLibraryInfo::getApplicationLocale()
+std::string WebEngineLibraryInfo::getResolvedLocale()
{
base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
- if (!parsedCommandLine->HasSwitch(switches::kLang)) {
- const QString &locale = QLocale().bcp47Name();
+ std::string locale;
+ if (parsedCommandLine->HasSwitch(switches::kLang))
+ locale = parsedCommandLine->GetSwitchValueASCII(switches::kLang);
+ else
+ locale = QLocale().bcp47Name().toStdString();
- // QLocale::bcp47Name returns "en" for American English locale. Chromium requires the "US" suffix
- // to clarify the dialect and ignores the shorter version.
- if (locale == "en")
- return "en-US";
+ std::string resolvedLocale;
+ if (l10n_util::CheckAndResolveLocale(locale, &resolvedLocale))
+ return resolvedLocale;
- return locale.toStdString();
- }
+ return "en-US";
+}
- return parsedCommandLine->GetSwitchValueASCII(switches::kLang);
+std::string WebEngineLibraryInfo::getApplicationLocale()
+{
+ base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
+ return parsedCommandLine->HasSwitch(switches::kLang)
+ ? parsedCommandLine->GetSwitchValueASCII(switches::kLang)
+ : QLocale().bcp47Name().toStdString();
}
+
+#if defined(Q_OS_WIN)
+bool WebEngineLibraryInfo::isRemoteDrivePath(const QString &path)
+{
+ WCHAR wDriveLetter[4] = { 0 };
+ swprintf(wDriveLetter, L"%S", path.mid(0, 3).toStdString().c_str());
+ return GetDriveType(wDriveLetter) == DRIVE_REMOTE;
+}
+
+bool WebEngineLibraryInfo::isUNCPath(const QString &path)
+{
+ return (base::FilePath::IsSeparator(path.at(0).toLatin1())
+ && base::FilePath::IsSeparator(path.at(1).toLatin1())
+ && path.at(2) != QLatin1Char('.') && path.at(2) != QLatin1Char('?')
+ && path.at(2).isLetter() && path.at(3) != QLatin1Char(':'));
+}
+
+#endif