Source

Target

Showing with 126 additions and 21 deletions
...@@ -142,7 +142,11 @@ WebEngineContext::WebEngineContext() ...@@ -142,7 +142,11 @@ WebEngineContext::WebEngineContext()
#if defined(OS_WIN) #if defined(OS_WIN)
parsedCommandLine->AppendSwitch(switches::kDisableD3D11); parsedCommandLine->AppendSwitch(switches::kDisableD3D11);
// ANGLE doesn't support multi-threading, doing texture upload from the GPU thread
// hasn't been causing problems yet but doing rendering there is conflicting with
// Qt's rendering of the scene graph.
parsedCommandLine->AppendSwitch(switches::kDisableExperimentalWebGL); parsedCommandLine->AppendSwitch(switches::kDisableExperimentalWebGL);
parsedCommandLine->AppendSwitch(switches::kDisableAccelerated2dCanvas);
#endif #endif
#if defined(QTWEBENGINE_MOBILE_SWITCHES) #if defined(QTWEBENGINE_MOBILE_SWITCHES)
......
...@@ -92,6 +92,39 @@ QString location(QLibraryInfo::LibraryLocation path) ...@@ -92,6 +92,39 @@ QString location(QLibraryInfo::LibraryLocation path)
return QLibraryInfo::location(path); return QLibraryInfo::location(path);
} }
#if defined(OS_MACOSX)
static inline CFBundleRef frameworkBundle()
{
return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.Qt.QtWebEngineCore"));
}
static QString getPath(CFBundleRef frameworkBundle)
{
QString path;
if (frameworkBundle) {
CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle);
CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle);
path = QString::fromCFString(bundlePath);
CFRelease(bundlePath);
CFRelease(bundleUrl);
}
return path;
}
static QString getResourcesPath(CFBundleRef frameworkBundle)
{
QString path;
if (frameworkBundle) {
CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle);
CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle);
path = getPath(frameworkBundle) % QLatin1Char('/') % QString::fromCFString(resourcesRelativePath);
CFRelease(resourcesRelativePath);
CFRelease(resourcesRelativeUrl);
}
return path;
}
#endif
QString subProcessPath() QString subProcessPath()
{ {
static bool initialized = false; static bool initialized = false;
...@@ -100,14 +133,19 @@ QString subProcessPath() ...@@ -100,14 +133,19 @@ QString subProcessPath()
#else #else
static QString processBinary (QLatin1String(QTWEBENGINEPROCESS_NAME)); static QString processBinary (QLatin1String(QTWEBENGINEPROCESS_NAME));
#endif #endif
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
static QString processPath (getPath(frameworkBundle())
% QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME));
#else
static QString processPath (location(QLibraryInfo::LibraryExecutablesPath) static QString processPath (location(QLibraryInfo::LibraryExecutablesPath)
% QDir::separator() % processBinary); % QDir::separator() % processBinary);
#endif
if (!initialized) { if (!initialized) {
// Allow overriding at runtime for the time being. // Allow overriding at runtime for the time being.
const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH"); const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH");
if (!fromEnv.isEmpty()) if (!fromEnv.isEmpty())
processPath = QString::fromLatin1(fromEnv); processPath = QString::fromLatin1(fromEnv);
if (processPath.isEmpty() || !QFileInfo(processPath).exists()) { if (!QFileInfo(processPath).exists()) {
qWarning("QtWebEngineProcess not found at location %s. Trying fallback path...", qPrintable(processPath)); qWarning("QtWebEngineProcess not found at location %s. Trying fallback path...", qPrintable(processPath));
processPath = QCoreApplication::applicationDirPath() % QDir::separator() % processBinary; processPath = QCoreApplication::applicationDirPath() % QDir::separator() % processBinary;
} }
...@@ -121,12 +159,20 @@ QString subProcessPath() ...@@ -121,12 +159,20 @@ QString subProcessPath()
QString pluginsPath() QString pluginsPath()
{ {
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
return getPath(frameworkBundle()) % QLatin1String("/Libraries");
#else
return location(QLibraryInfo::PluginsPath) % QDir::separator() % QLatin1String("qtwebengine"); return location(QLibraryInfo::PluginsPath) % QDir::separator() % QLatin1String("qtwebengine");
#endif
} }
QString localesPath() QString localesPath()
{ {
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
return getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_locales");
#else
return location(QLibraryInfo::TranslationsPath) % QLatin1String("/qtwebengine_locales"); return location(QLibraryInfo::TranslationsPath) % QLatin1String("/qtwebengine_locales");
#endif
} }
QString fallbackDir() { QString fallbackDir() {
...@@ -155,7 +201,11 @@ base::FilePath WebEngineLibraryInfo::getPath(int key) ...@@ -155,7 +201,11 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
QString directory; QString directory;
switch (key) { switch (key) {
case QT_RESOURCES_PAK: case QT_RESOURCES_PAK:
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
return toFilePath(getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_resources.pak"));
#else
return toFilePath(location(QLibraryInfo::DataPath) % QLatin1String("/qtwebengine_resources.pak")); return toFilePath(location(QLibraryInfo::DataPath) % QLatin1String("/qtwebengine_resources.pak"));
#endif
case base::FILE_EXE: case base::FILE_EXE:
case content::CHILD_PROCESS_EXE: case content::CHILD_PROCESS_EXE:
return toFilePath(subProcessPath()); return toFilePath(subProcessPath());
...@@ -171,7 +221,11 @@ base::FilePath WebEngineLibraryInfo::getPath(int key) ...@@ -171,7 +221,11 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
directory = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); directory = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
break; break;
case base::DIR_QT_LIBRARY_DATA: case base::DIR_QT_LIBRARY_DATA:
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
return toFilePath(getResourcesPath(frameworkBundle()));
#else
return toFilePath(location(QLibraryInfo::DataPath)); return toFilePath(location(QLibraryInfo::DataPath));
#endif
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
case base::DIR_SOURCE_ROOT: case base::DIR_SOURCE_ROOT:
case base::DIR_ANDROID_EXTERNAL_STORAGE: case base::DIR_ANDROID_EXTERNAL_STORAGE:
......
TARGET = $$QTWEBENGINEPROCESS_NAME TARGET = $$QTWEBENGINEPROCESS_NAME
TEMPLATE = app TEMPLATE = app
QT_PRIVATE += webenginecore load(qt_build_paths)
contains(QT_CONFIG, qt_framework) {
# Deploy the QtWebEngineProcess app bundle into the QtWebEngineCore framework.
DESTDIR = $$MODULE_BASE_OUTDIR/lib/QtWebEngineCore.framework/Versions/5/Helpers
CONFIG -= app_bundle # FIXME: We can remove those steps in Qt 5.5 once @rpath works
# "QT += webenginecore" would pull all dependencies that we'd also need to update
# with install_name_tool on OSX, but we only need access to the private
# QtWebEngine::processMain. qtAddModule will take care of finding where
# the library is without pulling additional librarie.
QT = core
qtAddModule(webenginecore, LIBS)
CONFIG -= link_prl
QMAKE_POST_LINK = \
"xcrun install_name_tool -change " \
"`xcrun otool -X -L $(TARGET) | grep QtWebEngineCore | cut -d ' ' -f 1` " \
"@executable_path/../../../../QtWebEngineCore " \
"$(TARGET); " \
"xcrun install_name_tool -change " \
"`xcrun otool -X -L $(TARGET) | grep QtCore | cut -d ' ' -f 1` " \
"@executable_path/../../../../../../../QtCore.framework/QtCore " \
"$(TARGET) "
} else {
CONFIG -= app_bundle
DESTDIR = $$MODULE_BASE_OUTDIR/libexec
load(qt_build_paths) QT_PRIVATE += webenginecore
DESTDIR = $$MODULE_BASE_OUTDIR/libexec }
INCLUDEPATH += ../core INCLUDEPATH += ../core
SOURCES = main.cpp SOURCES = main.cpp
target.path = $$[QT_INSTALL_LIBEXECS] contains(QT_CONFIG, qt_framework) {
target.path = $$[QT_INSTALL_LIBS]/QtWebEngineCore.framework/Versions/5/Helpers
} else {
target.path = $$[QT_INSTALL_LIBEXECS]
}
INSTALLS += target INSTALLS += target
...@@ -78,6 +78,7 @@ QQuickWebEngineSettings *QQuickWebEngineSettings::globalSettings() ...@@ -78,6 +78,7 @@ QQuickWebEngineSettings *QQuickWebEngineSettings::globalSettings()
QQuickWebEngineSettings::~QQuickWebEngineSettings() QQuickWebEngineSettings::~QQuickWebEngineSettings()
{ {
allSettings->removeAll(this->d_func());
} }
bool QQuickWebEngineSettings::autoLoadImages() const bool QQuickWebEngineSettings::autoLoadImages() const
......
...@@ -117,6 +117,12 @@ ...@@ -117,6 +117,12 @@
\li \l {Qt WebEngine Widgets C++ Classes} \li \l {Qt WebEngine Widgets C++ Classes}
\endlist \endlist
\section1 Examples
\list
\li \l {Qt WebEngine Widgets Examples}
\endlist
\section1 License Information \section1 License Information
This is a snapshot of the integration of Chromium into Qt. This is a snapshot of the integration of Chromium into Qt.
......
...@@ -42,38 +42,49 @@ ...@@ -42,38 +42,49 @@
import QtQuick 2.0 import QtQuick 2.0
import QtTest 1.0 import QtTest 1.0
import QtWebEngine 1.0 import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
TestWebEngineView { TestWebEngineView {
id: webEngineView id: webEngineView
width: 400 width: 400
height: 300 height: 300
property variant testUrl property variant unavailableUrl
SignalSpy {
id: spyIconChanged
target: webEngineView
signalName: "iconChanged"
}
TestCase { TestCase {
id: test id: test
name: "WebEngineViewLoadFail" name: "WebEngineViewLoadFail"
function initTestCase() {
WebEngine.settings.errorPageEnabled = false
}
function test_fail() { function test_fail() {
testUrl = Qt.resolvedUrl("file_that_does_not_exist.html") unavailableUrl = Qt.resolvedUrl("file_that_does_not_exist.html")
webEngineView.url = testUrl webEngineView.url = unavailableUrl
verify(webEngineView.waitForLoadFailed()) verify(webEngineView.waitForLoadFailed())
spyIconChanged.clear() }
// If this testcase finishes too early, we can not handle the received replacement content. function test_fail_url() {
// So we should wait to ignore this error page. var url = Qt.resolvedUrl("test1.html")
spyIconChanged.wait() webEngineView.url = url
compare(webEngineView.url, url)
verify(webEngineView.waitForLoadSucceeded())
compare(webEngineView.url, url)
unavailableUrl = Qt.resolvedUrl("file_that_does_not_exist.html")
webEngineView.url = unavailableUrl
compare(webEngineView.url, unavailableUrl)
verify(webEngineView.waitForLoadFailed())
// When error page is disabled in case of LoadFail the entry of the unavailable page is not stored.
// We expect the url of the previously loaded page here.
compare(webEngineView.url, url)
} }
} }
onLoadingChanged: { onLoadingChanged: {
if (loadRequest.status == WebEngineView.LoadFailedStatus) { if (loadRequest.status == WebEngineView.LoadFailedStatus) {
test.compare(loadRequest.url, testUrl) test.compare(loadRequest.url, unavailableUrl)
test.compare(loadRequest.errorDomain, WebEngineView.InternalErrorDomain) test.compare(loadRequest.errorDomain, WebEngineView.InternalErrorDomain)
} }
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
import QtQuick 2.0 import QtQuick 2.0
import QtTest 1.0 import QtTest 1.0
import QtWebEngine 1.0 import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
TestWebEngineView { TestWebEngineView {
id: webEngineView id: webEngineView
...@@ -106,6 +107,8 @@ TestWebEngineView { ...@@ -106,6 +107,8 @@ TestWebEngineView {
} }
function test_urlProperty() { function test_urlProperty() {
WebEngine.settings.errorPageEnabled = false
var url = Qt.resolvedUrl("test1.html") var url = Qt.resolvedUrl("test1.html")
webEngineView.url = url webEngineView.url = url
...@@ -117,7 +120,7 @@ TestWebEngineView { ...@@ -117,7 +120,7 @@ TestWebEngineView {
webEngineView.url = bogusSite webEngineView.url = bogusSite
compare(webEngineView.url, bogusSite) compare(webEngineView.url, bogusSite)
verify(webEngineView.waitForLoadFailed()) verify(webEngineView.waitForLoadFailed())
compare(webEngineView.url, bogusSite) compare(webEngineView.url, url)
webEngineView.url = "about:blank" // Reset from previous test webEngineView.url = "about:blank" // Reset from previous test
verify(webEngineView.waitForLoadSucceeded()) verify(webEngineView.waitForLoadSucceeded())
......