Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
4** Copyright (C) 2016 The Qt Company Ltd.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtWebEngine module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "web_engine_library_info.h"
42
43#include "base/base_paths.h"
44#include "base/command_line.h"
45#include "base/files/file_util.h"
46#include "components/spellcheck/spellcheck_buildflags.h"
47#include "content/public/common/content_paths.h"
48#include "ui/base/ui_base_paths.h"
49#include "ui/base/ui_base_switches.h"
50#include "type_conversion.h"
51
52#include <QByteArray>
53#include <QCoreApplication>
54#include <QDir>
55#include <QFileInfo>
56#include <QLibraryInfo>
57#include <QLocale>
58#include <QStandardPaths>
59#include <QString>
60
61#ifndef QTWEBENGINEPROCESS_NAME
62#error "No name defined for QtWebEngine's process"
63#endif
64
65using namespace QtWebEngineCore;
66
67namespace {
68
69QString fallbackDir() {
70 static QString directory = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName();
71 return directory;
72}
73
74#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
75static inline CFBundleRef frameworkBundle()
76{
77 return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.Qt.QtWebEngineCore"));
78}
79
80static QString getPath(CFBundleRef frameworkBundle)
81{
82 QString path;
83 // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
84 // We use it for the other OS X versions as well to make sure it works and because
85 // the directory structure should be the same.
86 if (qApp->applicationName() == QLatin1String(QTWEBENGINEPROCESS_NAME)) {
87 path = QDir::cleanPath(qApp->applicationDirPath() % QLatin1String("/../../../.."));
88 } else if (frameworkBundle) {
89 CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle);
90 CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle);
91 path = QString::fromCFString(bundlePath);
92 CFRelease(bundlePath);
93 CFRelease(bundleUrl);
94 }
95 return path;
96}
97
98static QString getResourcesPath(CFBundleRef frameworkBundle)
99{
100 QString path;
101 // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
102 // We use it for the other OS X versions as well to make sure it works and because
103 // the directory structure should be the same.
104 if (qApp->applicationName() == QLatin1String(QTWEBENGINEPROCESS_NAME)) {
105 path = getPath(frameworkBundle) % QLatin1String("/Resources");
106 } else if (frameworkBundle) {
107 CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle);
108 CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle);
109 path = getPath(frameworkBundle) % QLatin1Char('/') % QString::fromCFString(resourcesRelativePath);
110 CFRelease(resourcesRelativePath);
111 CFRelease(resourcesRelativeUrl);
112 }
113 return path;
114}
115#endif
116
117#if defined(OS_MACOSX)
118static QString getMainApplicationResourcesPath()
119{
120 QString resourcesPath;
121 CFBundleRef mainBundle = CFBundleGetMainBundle();
122 if (!mainBundle)
123 return resourcesPath;
124
125 // Will point to Resources inside an app bundle, or in case if the application is not packaged
126 // as a bundle, will point to the application directory, where the resources are assumed to be
127 // found.
128 CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(mainBundle);
129 if (!resourcesRelativeUrl)
130 return resourcesPath;
131
132 CFURLRef resourcesAbsoluteUrl = CFURLCopyAbsoluteURL(resourcesRelativeUrl);
133 CFStringRef resourcesAbolutePath = CFURLCopyFileSystemPath(resourcesAbsoluteUrl,
134 kCFURLPOSIXPathStyle);
135 resourcesPath = QString::fromCFString(resourcesAbolutePath);
136 CFRelease(resourcesAbolutePath);
137 CFRelease(resourcesAbsoluteUrl);
138 CFRelease(resourcesRelativeUrl);
139
140 return resourcesPath;
141}
142
143#endif
144
145QString subProcessPath()
146{
147 static QString processPath;
148 if (processPath.isEmpty()) {
149#if defined(OS_WIN)
150 const QString processBinary = QLatin1String(QTWEBENGINEPROCESS_NAME) % QLatin1String(".exe");
151#else
152 const QString processBinary = QLatin1String(QTWEBENGINEPROCESS_NAME);
153#endif
154
155 QStringList candidatePaths;
156 const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH");
157 if (!fromEnv.isEmpty()) {
158 // Only search in QTWEBENGINEPROCESS_PATH if set
159 candidatePaths << QString::fromLocal8Bit(fromEnv);
160 } else {
161#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
162 candidatePaths << getPath(frameworkBundle())
163 % QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME);
164#else
165 candidatePaths << QLibraryInfo::location(QLibraryInfo::LibraryExecutablesPath)
166 % QLatin1Char('/') % processBinary;
167#endif
168 candidatePaths << QCoreApplication::applicationDirPath()
169 % QLatin1Char('/') % processBinary;
170 }
171
172 for (const QString &candidate : qAsConst(candidatePaths)) {
173 if (QFileInfo::exists(candidate)) {
174 processPath = candidate;
175 break;
176 }
177 }
178 if (processPath.isEmpty())
179 qFatal("Could not find %s", processBinary.toUtf8().constData());
180
181 }
182
183
184 return processPath;
185}
186
187QString localesPath()
188{
189 static bool initialized = false;
190 static QString potentialLocalesPath =
191#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
192 getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_locales");
193#else
194 QLibraryInfo::location(QLibraryInfo::TranslationsPath) % QDir::separator() % QLatin1String("qtwebengine_locales");
195#endif
196
197 if (!initialized) {
198 initialized = true;
199 if (!QFileInfo::exists(potentialLocalesPath)) {
200 qWarning("Installed Qt WebEngine locales directory not found at location %s. Trying application directory...", qPrintable(potentialLocalesPath));
201 potentialLocalesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_locales");
202 }
203 if (!QFileInfo::exists(potentialLocalesPath)) {
204 qWarning("Qt WebEngine locales directory not found at location %s. Trying fallback directory... Translations MAY NOT not be correct.", qPrintable(potentialLocalesPath));
205 potentialLocalesPath = fallbackDir();
206 }
207 }
208
209 return potentialLocalesPath;
210}
211
212#if QT_CONFIG(webengine_spellchecker)
213QString dictionariesPath()
214{
215 static QString potentialDictionariesPath;
216 static bool initialized = false;
217 QStringList candidatePaths;
218 if (!initialized) {
219 initialized = true;
220
221 const QByteArray fromEnv = qgetenv("QTWEBENGINE_DICTIONARIES_PATH");
222 if (!fromEnv.isEmpty()) {
223 // Only search in QTWEBENGINE_DICTIONARIES_PATH if set
224 candidatePaths << QString::fromLocal8Bit(fromEnv);
225 } else {
226 // First try to find dictionaries near the application.
227#ifdef OS_MACOSX
228 QString resourcesDictionariesPath = getMainApplicationResourcesPath()
229 % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
230 candidatePaths << resourcesDictionariesPath;
231#endif
232 QString applicationDictionariesPath = QCoreApplication::applicationDirPath()
233 % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
234 candidatePaths << applicationDictionariesPath;
235
236 // Then try to find dictionaries near the installed library.
237#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
238 QString frameworkDictionariesPath = getResourcesPath(frameworkBundle())
239 % QLatin1String("/qtwebengine_dictionaries");
240 candidatePaths << frameworkDictionariesPath;
241#endif
242
243 QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath)
244 % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
245 candidatePaths << libraryDictionariesPath;
246 }
247
248 for (const QString &candidate : qAsConst(candidatePaths)) {
249 if (QFileInfo::exists(candidate)) {
250 potentialDictionariesPath = candidate;
251 break;
252 }
253 }
254 }
255
256 return potentialDictionariesPath;
257}
258#endif // QT_CONFIG(webengine_spellchecker)
259
260QString resourcesDataPath()
261{
262 static bool initialized = false;
263 static QString potentialResourcesPath =
264#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
265 getResourcesPath(frameworkBundle());
266#else
267 QLibraryInfo::location(QLibraryInfo::DataPath) % QLatin1String("/resources");
268#endif
269 if (!initialized) {
270 initialized = true;
271 if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
272 qWarning("Qt WebEngine resources not found at %s. Trying parent directory...", qPrintable(potentialResourcesPath));
273 potentialResourcesPath = QLibraryInfo::location(QLibraryInfo::DataPath);
274 }
275 if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
276 qWarning("Qt WebEngine resources not found at %s. Trying application directory...", qPrintable(potentialResourcesPath));
277 potentialResourcesPath = QCoreApplication::applicationDirPath();
278 }
279 if (!QFileInfo::exists(potentialResourcesPath % QLatin1String("/qtwebengine_resources.pak"))) {
280 qWarning("Qt WebEngine resources not found at %s. Trying fallback directory... The application MAY NOT work.", qPrintable(potentialResourcesPath));
281 potentialResourcesPath = fallbackDir();
282 }
283 }
284
285 return potentialResourcesPath;
286}
287} // namespace
288
289base::FilePath WebEngineLibraryInfo::getPath(int key)
290{
291 QString directory;
292 switch (key) {
293 case QT_RESOURCES_PAK:
294 return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources.pak"));
295 case QT_RESOURCES_100P_PAK:
296 return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources_100p.pak"));
297 case QT_RESOURCES_200P_PAK:
298 return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_resources_200p.pak"));
299 case QT_RESOURCES_DEVTOOLS_PAK:
300 return toFilePath(resourcesDataPath() % QLatin1String("/qtwebengine_devtools_resources.pak"));
301 case base::FILE_EXE:
302 case content::CHILD_PROCESS_EXE:
303 return toFilePath(subProcessPath());
304#if defined(OS_POSIX)
305 case base::DIR_CACHE:
306 directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
307 break;
308 case base::DIR_HOME:
309 directory = QDir::homePath();
310 break;
311#endif
312 case base::DIR_USER_DESKTOP:
313 directory = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
314 break;
315 case base::DIR_QT_LIBRARY_DATA:
316 return toFilePath(resourcesDataPath());
317 case ui::DIR_LOCALES:
318 return toFilePath(localesPath());
319#if QT_CONFIG(webengine_spellchecker)
320 case base::DIR_APP_DICTIONARIES:
321 return toFilePath(dictionariesPath());
322#endif
323 default:
324 // Note: the path system expects this function to override the default
325 // behavior. So no need to log an error if we don't support a given
326 // path. The system will just use the default.
327 return base::FilePath();
328 }
329
330 return toFilePath(directory.isEmpty() ? fallbackDir() : directory);
331}
332
333base::string16 WebEngineLibraryInfo::getApplicationName()
334{
335 return toString16(qApp->applicationName());
336}
337
338std::string WebEngineLibraryInfo::getApplicationLocale()
339{
340 base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
341 if (!parsedCommandLine->HasSwitch(switches::kLang)) {
342 const QString &locale = QLocale().bcp47Name();
343
344 // QLocale::bcp47Name returns "en" for American English locale. Chromium requires the "US" suffix
345 // to clarify the dialect and ignores the shorter version.
346 if (locale == "en")
347 return "en-US";
348
349 return locale.toStdString();
350 }
351
352 return parsedCommandLine->GetSwitchValueASCII(switches::kLang);
353}
354

Warning: That file was not part of the compilation database. It may have many parsing errors.