diff options
26 files changed, 269 insertions, 129 deletions
diff --git a/examples/webengine/quicknanobrowser/ApplicationRoot.qml b/examples/webengine/quicknanobrowser/ApplicationRoot.qml index b16ee0078..b409696be 100644 --- a/examples/webengine/quicknanobrowser/ApplicationRoot.qml +++ b/examples/webengine/quicknanobrowser/ApplicationRoot.qml @@ -39,9 +39,19 @@ ****************************************************************************/ import QtQuick 2.1 +import QtWebEngine 1.1 QtObject { id: root + + property QtObject defaultProfile: WebEngineProfile { + storageName: "Default" + } + + property QtObject otrProfile: WebEngineProfile { + offTheRecord: true + } + property Component browserWindowComponent: BrowserWindow { applicationRoot: root onClosing: destroy() @@ -49,10 +59,19 @@ QtObject { property Component browserDialogComponent: BrowserDialog { onClosing: destroy() } - function createWindow() { return browserWindowComponent.createObject(root) } - function createDialog() { return browserDialogComponent.createObject(root) } + function createWindow(profile) { + var newWindow = browserWindowComponent.createObject(root) + newWindow.currentWebView.profile = profile + profile.downloadRequested.connect(newWindow.onDownloadRequested) + return newWindow + } + function createDialog(profile) { + var newDialog = browserDialogComponent.createObject(root) + newDialog.currentWebView.profile = profile + return newDialog + } function load(url) { - var browserWindow = createWindow() + var browserWindow = createWindow(defaultProfile) browserWindow.currentWebView.url = url } } diff --git a/examples/webengine/quicknanobrowser/BrowserDialog.qml b/examples/webengine/quicknanobrowser/BrowserDialog.qml index 302833083..6202d02f7 100644 --- a/examples/webengine/quicknanobrowser/BrowserDialog.qml +++ b/examples/webengine/quicknanobrowser/BrowserDialog.qml @@ -40,7 +40,7 @@ import QtQuick 2.1 import QtQuick.Window 2.2 -import QtWebEngine 1.0 +import QtWebEngine 1.1 Window { property alias currentWebView: webView diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml index aa55bd889..0df17f0ee 100644 --- a/examples/webengine/quicknanobrowser/BrowserWindow.qml +++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml @@ -85,22 +85,6 @@ ApplicationWindow { property alias pluginsEnabled: pluginsEnabled.checked; } - WebEngineProfile { - id: defaultProfile - storageName: "Default" - httpCacheType: httpDiskCacheEnabled.checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache; - onDownloadRequested: { - downloadView.visible = true - downloadView.append(download) - download.accept() - } - } - - WebEngineProfile { - id: otrProfile - offTheRecord: true - } - Action { shortcut: "Ctrl+D" onTriggered: { @@ -125,7 +109,7 @@ ApplicationWindow { Action { shortcut: "Ctrl+T" onTriggered: { - tabs.createEmptyTab() + tabs.createEmptyTab(currentWebView.profile) tabs.currentIndex = tabs.count - 1 addressBar.forceActiveFocus(); addressBar.selectAll(); @@ -256,13 +240,15 @@ ApplicationWindow { id: offTheRecordEnabled text: "Off The Record" checkable: true - checked: false + checked: currentWebView.profile.offTheRecord + onToggled: currentWebView.profile = checked ? otrProfile : defaultProfile; } MenuItem { id: httpDiskCacheEnabled text: "HTTP Disk Cache" - checkable: true - checked: (defaultProfile.httpCacheType == WebEngineProfile.DiskHttpCache) + checkable: !currentWebView.profile.offTheRecord + checked: (currentWebView.profile.httpCacheType == WebEngineProfile.DiskHttpCache) + onToggled: currentWebView.profile.httpCacheType = checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache } } } @@ -289,23 +275,23 @@ ApplicationWindow { TabView { id: tabs - function createEmptyTab() { + function createEmptyTab(profile) { var tab = addTab("", tabComponent) // We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately. tab.active = true tab.title = Qt.binding(function() { return tab.item.title }) + tab.item.profile = profile return tab } anchors.fill: parent - Component.onCompleted: createEmptyTab() + Component.onCompleted: createEmptyTab(defaultProfile) Component { id: tabComponent WebEngineView { id: webEngineView focus: true - profile: offTheRecordEnabled.checked ? otrProfile : defaultProfile onLinkHovered: { if (hoveredUrl == "") @@ -344,17 +330,17 @@ ApplicationWindow { if (!request.userInitiated) print("Warning: Blocked a popup window.") else if (request.destination == WebEngineView.NewViewInTab) { - var tab = tabs.createEmptyTab() + var tab = tabs.createEmptyTab(currentWebView.profile) tabs.currentIndex = tabs.count - 1 request.openIn(tab.item) } else if (request.destination == WebEngineView.NewViewInBackgroundTab) { - var tab = tabs.createEmptyTab() + var tab = tabs.createEmptyTab(currentWebView.profile) request.openIn(tab.item) } else if (request.destination == WebEngineView.NewViewInDialog) { - var dialog = applicationRoot.createDialog() + var dialog = applicationRoot.createDialog(currentWebView.profile) request.openIn(dialog.currentWebView) } else { - var window = applicationRoot.createWindow() + var window = applicationRoot.createWindow(currentWebView.profile) request.openIn(window.currentWebView) } } @@ -409,6 +395,13 @@ ApplicationWindow { visible: false anchors.fill: parent } + + function onDownloadRequested(download) { + downloadView.visible = true + downloadView.append(download) + download.accept() + } + Rectangle { id: statusBubble color: "oldlace" diff --git a/src/3rdparty b/src/3rdparty -Subproject 6d7b9ab74288eab0f846e5fa92854c9a49bee19 +Subproject 0decf91700ad48612b885a549e79bb6252196d4 diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index c7c97e60c..ef574eccd 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -40,13 +40,15 @@ #include "chromium_gpu_helper.h" -#include "content/common/gpu/gpu_channel_manager.h" -#include "content/common/gpu/sync_point_manager.h" -#include "content/gpu/gpu_child_thread.h" +// Including gpu/command_buffer headers before content/gpu headers makes sure that +// guards are defined to prevent duplicate definition errors with forward declared +// GL typedefs cascading through content header includes. #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/texture_manager.h" -#include <QtGlobal> // We need this for the Q_OS_QNX define. +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/sync_point_manager.h" +#include "content/gpu/gpu_child_thread.h" #ifdef Q_OS_QNX #include "content/common/gpu/stream_texture_qnx.h" diff --git a/src/core/core_module.pro b/src/core/core_module.pro index afa11d31f..df868949e 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -67,13 +67,13 @@ plugins.files = $$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_ } !contains(QT_CONFIG, qt_framework): contains(QT_CONFIG, private_tests) { - ICU_TARGET = $$shell_path($$[QT_INSTALL_DATA]/icudtl.dat) + ICU_TARGET = $$shell_path($$[QT_INSTALL_DATA/get]/icudtl.dat) ICU_FILE = $$shell_path($$OUT_PWD/$$getConfigDir()/icudtl.dat) icu_rule.target = $$ICU_TARGET unix: icu_rule.commands = if [ -e $$ICU_FILE ] ; then $$QMAKE_COPY $$ICU_FILE $$ICU_TARGET ; fi win32: icu_rule.commands = if exist $$ICU_FILE ( $$QMAKE_COPY $$ICU_FILE $$ICU_TARGET ) - PLUGIN_DIR = $$shell_path($$[QT_INSTALL_PLUGINS]/qtwebengine) + PLUGIN_DIR = $$shell_path($$[QT_INSTALL_PLUGINS/get]/qtwebengine) PLUGIN_TARGET = $$shell_path($$PLUGIN_DIR/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_EXTENSION}) PLUGIN_FILE = $$shell_path($$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_EXTENSION}) plugins_rule.target = $$PLUGIN_TARGET diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 6469ad8c2..720cd1faf 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -70,7 +70,8 @@ std::vector<gfx::Display> DesktopScreenQt::GetAllDisplays() const gfx::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeView window) const { - Q_UNREACHABLE(); + // RenderViewHostImpl::OnStartDragging uses this to determine + // the scale factor for the view. return gfx::Display(); } diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index 4fe2f2137..5a27aa98f 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -49,8 +49,6 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "content/common/gpu/image_transport_surface.h" -#include "content/common/gpu/gpu_channel_manager.h" -#include "content/common/gpu/gpu_command_buffer_stub.h" #include "ui/gl/egl_util.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" @@ -544,7 +542,9 @@ GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window) } // namespace gfx namespace content { -scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(GpuChannelManager* manager, GpuCommandBufferStub* stub, const gfx::GLSurfaceHandle& handle) +class GpuCommandBufferStub; +class GpuChannelManager; +scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(GpuChannelManager*, GpuCommandBufferStub*, const gfx::GLSurfaceHandle&) { QT_NOT_USED return scoped_refptr<gfx::GLSurface>(); diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro index e1691faa6..4c6eb8c56 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -87,8 +87,8 @@ contains(QT_ARCH, "i386"): GYP_ARGS += "-D target_arch=ia32" contains(WEBENGINE_CONFIG, proprietary_codecs): GYP_ARGS += "-Dproprietary_codecs=1 -Dffmpeg_branding=Chrome -Duse_system_ffmpeg=0" !contains(QT_CONFIG, qt_framework): contains(QT_CONFIG, private_tests) { - GYP_ARGS += "-D qt_install_data=\"$$[QT_INSTALL_DATA]\"" - GYP_ARGS += "-D qt_install_translations=\"$$[QT_INSTALL_TRANSLATIONS]\"" + GYP_ARGS += "-D qt_install_data=\"$$[QT_INSTALL_DATA/get]\"" + GYP_ARGS += "-D qt_install_translations=\"$$[QT_INSTALL_TRANSLATIONS/get]\"" } !build_pass { diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index dec6b4dbb..4f893175a 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -124,6 +124,18 @@ void URLRequestContextGetterQt::generateStorage() { Q_ASSERT(m_urlRequestContext); + if (m_storage) { + // We must stop all requests before deleting their backends. + std::set<const net::URLRequest*>* url_requests = m_urlRequestContext->url_requests(); + std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); + std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); + for ( ; it != end; ++it) { + net::URLRequest* request = const_cast<net::URLRequest*>(*it); + if (request) + request->Cancel(); + } + } + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index 105f90746..0b8aaf9ba 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -57,25 +57,41 @@ URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *n : URLRequestJob(request, networkDelegate) , m_device(0) , m_schemeHandler(schemeHandler) + , m_error(0) + , m_started(false) , m_weakFactory(this) { } URLRequestCustomJob::~URLRequestCustomJob() { + QMutexLocker lock(&m_mutex); + if (m_delegate) { + m_delegate->m_job = 0; + m_delegate->deleteLater(); + } if (m_device && m_device->isOpen()) m_device->close(); } void URLRequestCustomJob::Start() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(&URLRequestCustomJob::startAsync, m_weakFactory.GetWeakPtr())); } void URLRequestCustomJob::Kill() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + QMutexLocker lock(&m_mutex); + if (m_delegate) { + m_delegate->m_job = 0; + m_delegate->deleteLater(); + } + m_delegate = 0; if (m_device && m_device->isOpen()) m_device->close(); + m_device = 0; m_weakFactory.InvalidateWeakPtrs(); URLRequestJob::Kill(); @@ -83,6 +99,7 @@ void URLRequestCustomJob::Kill() bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (m_mimeType.size() > 0) { *mimeType = m_mimeType; return true; @@ -92,6 +109,7 @@ bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const bool URLRequestCustomJob::GetCharset(std::string* charset) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (m_charset.size() > 0) { *charset = m_charset; return true; @@ -101,25 +119,35 @@ bool URLRequestCustomJob::GetCharset(std::string* charset) void URLRequestCustomJob::setReplyMimeType(const std::string &mimeType) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); m_mimeType = mimeType; } void URLRequestCustomJob::setReplyCharset(const std::string &charset) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); m_charset = charset; } void URLRequestCustomJob::setReplyDevice(QIODevice *device) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + QMutexLocker lock(&m_mutex); m_device = device; if (m_device && !m_device->isReadable()) m_device->open(QIODevice::ReadOnly); - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJob::notifyStarted, m_weakFactory.GetWeakPtr())); + + if (m_device && m_device->isReadable()) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJob::notifyStarted, m_weakFactory.GetWeakPtr())); + else + fail(ERR_INVALID_URL); } bool URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize, int *bytesRead) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); Q_ASSERT(bytesRead); + QMutexLocker lock(&m_mutex); qint64 rv = m_device ? m_device->read(buf->data(), bufSize) : -1; if (rv >= 0) { *bytesRead = static_cast<int>(rv); @@ -132,16 +160,41 @@ bool URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize, int *bytesRead void URLRequestCustomJob::notifyStarted() { - if (m_device && m_device->isReadable()) - NotifyHeadersComplete(); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + Q_ASSERT(!m_started); + m_started = true; + NotifyHeadersComplete(); +} + +void URLRequestCustomJob::fail(int error) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + QMutexLocker lock(&m_mutex); + m_error = error; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJob::notifyFailure, m_weakFactory.GetWeakPtr())); +} + +void URLRequestCustomJob::notifyFailure() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + QMutexLocker lock(&m_mutex); + if (m_device) + m_device->close(); + if (m_started) + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, m_error)); else - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, m_error)); } void URLRequestCustomJob::startAsync() { - m_delegate.reset(new URLRequestCustomJobDelegate(this)); - m_schemeHandler->handleJob(m_delegate.get()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + Q_ASSERT(!m_started); + Q_ASSERT(!m_delegate); + QMutexLocker lock(&m_mutex); + m_delegate = new URLRequestCustomJobDelegate(this); + lock.unlock(); + m_schemeHandler->handleJob(m_delegate); } } // namespace diff --git a/src/core/url_request_custom_job.h b/src/core/url_request_custom_job.h index 448bfe6af..ca20c719d 100644 --- a/src/core/url_request_custom_job.h +++ b/src/core/url_request_custom_job.h @@ -41,6 +41,8 @@ #include "net/url_request/url_request_job.h" #include <QtCore/qglobal.h> +#include <QtCore/QMutex> +#include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) @@ -63,19 +65,27 @@ public: void setReplyCharset(const std::string &); void setReplyDevice(QIODevice *); + void fail(int); + protected: virtual ~URLRequestCustomJob(); void startAsync(); void notifyStarted(); + void notifyFailure(); private: - QIODevice *m_device; - scoped_ptr<URLRequestCustomJobDelegate> m_delegate; + QMutex m_mutex; + QPointer<QIODevice> m_device; + QPointer<URLRequestCustomJobDelegate> m_delegate; CustomUrlSchemeHandler *m_schemeHandler; std::string m_mimeType; std::string m_charset; + int m_error; + bool m_started; base::WeakPtrFactory<URLRequestCustomJob> m_weakFactory; + friend class URLRequestCustomJobDelegate; + DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); }; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 4050dc789..671002538 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -122,9 +122,6 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content WebContentsAdapter *newAdapter = createWindow(new_contents, disposition, initial_pos, user_gesture); if (was_blocked) *was_blocked = !newAdapter; - - if (content::RenderWidgetHostImpl *impl = content::RenderWidgetHostImpl::From(new_contents->GetRenderViewHost())) - impl->WasShown(ui::LatencyInfo()); } void WebContentsDelegateQt::CloseContents(content::WebContents *source) diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index e78ab09e7..4a12e732c 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -67,39 +67,6 @@ QString fallbackDir() { return directory; } -QString location(QLibraryInfo::LibraryLocation path) -{ -#if defined(Q_OS_BLACKBERRY) - // On BlackBerry, the qtwebengine may live in /usr/lib/qtwebengine. - // If so, the QTWEBENGINEPROCESS_PATH env var is set to /usr/lib/qtwebengine/bin/QTWEBENGINEPROCESS_NAME. - static QString webEnginePath; - static bool initialized = false; - if (!initialized) { - const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH"); - if (!fromEnv.isEmpty()) { - QDir dir = QFileInfo(QString::fromLatin1(fromEnv)).dir(); - if (dir.cdUp()) - webEnginePath = dir.absolutePath(); - } - initialized = true; - } - switch (path) { - case QLibraryInfo::TranslationsPath: - if (!webEnginePath.isEmpty()) - return webEnginePath % QLatin1String("/translations"); - break; - case QLibraryInfo::DataPath: - if (!webEnginePath.isEmpty()) - return webEnginePath; - break; - default: - break; - } -#endif - - return QLibraryInfo::location(path); -} - #if defined(OS_MACOSX) static inline CFBundleRef frameworkBundle() { @@ -155,7 +122,7 @@ QString subProcessPath() static QString processPath (getPath(frameworkBundle()) % QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME)); #else - static QString processPath (location(QLibraryInfo::LibraryExecutablesPath) + static QString processPath (QLibraryInfo::location(QLibraryInfo::LibraryExecutablesPath) % QLatin1Char('/') % processBinary); #endif if (!initialized) { @@ -181,7 +148,7 @@ QString pluginsPath() return getPath(frameworkBundle()) % QLatin1String("/Libraries"); #else static bool initialized = false; - static QString potentialPluginsPath = location(QLibraryInfo::PluginsPath) % QDir::separator() % QLatin1String("qtwebengine"); + static QString potentialPluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath) % QDir::separator() % QLatin1String("qtwebengine"); if (!initialized) { initialized = true; @@ -205,7 +172,7 @@ QString localesPath() return getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_locales"); #else static bool initialized = false; - static QString potentialLocalesPath = location(QLibraryInfo::TranslationsPath) % QDir::separator() % QLatin1String("qtwebengine_locales"); + static QString potentialLocalesPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath) % QDir::separator() % QLatin1String("qtwebengine_locales"); if (!initialized) { initialized = true; @@ -229,7 +196,7 @@ QString libraryDataPath() return getResourcesPath(frameworkBundle()); #else static bool initialized = false; - static QString potentialDataPath = location(QLibraryInfo::DataPath); + static QString potentialDataPath = QLibraryInfo::location(QLibraryInfo::DataPath); if (!initialized) { initialized = true; if (!QFileInfo::exists(potentialDataPath)) { @@ -255,7 +222,7 @@ base::FilePath WebEngineLibraryInfo::getPath(int key) #if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) return toFilePath(getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_resources.pak")); #else - return toFilePath(location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_resources.pak")); + return toFilePath(QLibraryInfo::location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_resources.pak")); #endif case base::FILE_EXE: case content::CHILD_PROCESS_EXE: diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 7bca4e3cd..e80a36736 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -725,9 +725,12 @@ QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineView::userScripts() void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile) { + Q_Q(QQuickWebEngineView); + if (profile == m_profile) return; m_profile = profile; + Q_EMIT q->profileChanged(); m_settings->setParentSettings(profile->settings()); if (adapter && adapter->browserContext() != browserContextAdapter()->browserContext()) { diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 4539ad34b..40299c1c5 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -84,7 +84,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY urlChanged) Q_PROPERTY(bool isFullScreen READ isFullScreen NOTIFY isFullScreenChanged REVISION 1) Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged REVISION 1) - Q_PROPERTY(QQuickWebEngineProfile *profile READ profile WRITE setProfile FINAL REVISION 1) + Q_PROPERTY(QQuickWebEngineProfile *profile READ profile WRITE setProfile NOTIFY profileChanged FINAL REVISION 1) Q_PROPERTY(QQuickWebEngineSettings *settings READ settings REVISION 1) Q_PROPERTY(QQuickWebEngineHistory *navigationHistory READ navigationHistory CONSTANT FINAL REVISION 1) Q_PROPERTY(QQmlWebChannel *webChannel READ webChannel WRITE setWebChannel NOTIFY webChannelChanged REVISION 1) @@ -228,6 +228,7 @@ Q_SIGNALS: Q_REVISION(1) void featurePermissionRequested(const QUrl &securityOrigin, Feature feature); Q_REVISION(1) void newViewRequested(QQuickWebEngineNewViewRequest *request); Q_REVISION(1) void zoomFactorChanged(qreal arg); + Q_REVISION(1) void profileChanged(); Q_REVISION(1) void webChannelChanged(); diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index e63519d2c..adccfca2a 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -494,6 +494,10 @@ void QWebEngineProfilePrivate::installUrlSchemeHandler(QWebEngineUrlSchemeHandle return; } + if (m_urlSchemeHandlers.contains(scheme)) { + qWarning() << "URL scheme handler already installed for the scheme: " << scheme; + return; + } m_urlSchemeHandlers.insert(scheme, handler); browserContext()->customUrlSchemeHandlers().append(handler->d_func()); browserContext()->updateCustomUrlSchemeHandlers(); diff --git a/src/webenginewidgets/api/qwebengineurlrequestjob.cpp b/src/webenginewidgets/api/qwebengineurlrequestjob.cpp index cb8b200a2..323cdcc72 100644 --- a/src/webenginewidgets/api/qwebengineurlrequestjob.cpp +++ b/src/webenginewidgets/api/qwebengineurlrequestjob.cpp @@ -42,21 +42,51 @@ QT_BEGIN_NAMESPACE +/*! + \class QWebEngineUrlRequestJob + \brief The QWebEngineUrlRequestJob class represents a custom URL request. + \since 5.5 + \internal + + A QWebEngineUrlRequestJob is given to QWebEngineUrlSchemeHandler::requestStarted() and must + be handled by the derived implementations of class. + + A job can be handled by calling setReply(). + + The class is owned by QtWebEngine and does not need to be deleted. Note QtWebEngine may delete + the job when it is no longer needed, so the signal QObject::destroyed() must be monitored if + a pointer to the object is stored. + + \inmodule QtWebEngineWidgets +*/ + +/*! + \internal + */ QWebEngineUrlRequestJob::QWebEngineUrlRequestJob(QtWebEngineCore::URLRequestCustomJobDelegate * p) : QObject(p) // owned by the jobdelegate and deleted when the job is done , d_ptr(p) { } +/*! + \internal + */ QWebEngineUrlRequestJob::~QWebEngineUrlRequestJob() { } +/*! + Returns the url requested. + */ QUrl QWebEngineUrlRequestJob::requestUrl() const { return d_ptr->url(); } +/*! + Sets the reply for the request to \a device with the mime-type \a contentType. + */ void QWebEngineUrlRequestJob::setReply(const QByteArray &contentType, QIODevice *device) { d_ptr->setReply(contentType, device); diff --git a/src/webenginewidgets/api/qwebengineurlschemehandler.cpp b/src/webenginewidgets/api/qwebengineurlschemehandler.cpp index 16ad220b2..65dd8f000 100644 --- a/src/webenginewidgets/api/qwebengineurlschemehandler.cpp +++ b/src/webenginewidgets/api/qwebengineurlschemehandler.cpp @@ -43,6 +43,23 @@ QT_BEGIN_NAMESPACE +/*! + \class QWebEngineUrlSchemeHandler + \brief The QWebEngineUrlSchemeHandler Base class for handling custom URL schemes. + \since 5.5 + \internal + + To implement a custom URL scheme for QtWebEngine you must write a class derived from this class, + and reimplement requestStarted(). + + To install a custom URL scheme handler into a QtWebProfile, you only need to call the constructor + with the correct profile. Each instance of a QWebEngineUrlSchemeHandler can only handle requests + from a single profile. + + \inmodule QtWebEngineWidgets + +*/ + QWebEngineUrlSchemeHandlerPrivate::QWebEngineUrlSchemeHandlerPrivate(const QByteArray &scheme, QWebEngineUrlSchemeHandler *q, QWebEngineProfile *profile) : CustomUrlSchemeHandler(scheme) , q_ptr(q) @@ -61,6 +78,12 @@ bool QWebEngineUrlSchemeHandlerPrivate::handleJob(QtWebEngineCore::URLRequestCus return true; } +/*! + Constructs a new URL scheme handler. + + The handler is created for \a scheme and for the \a profile. + + */ QWebEngineUrlSchemeHandler::QWebEngineUrlSchemeHandler(const QByteArray &scheme, QWebEngineProfile *profile, QObject *parent) : QObject(parent) , d_ptr(new QWebEngineUrlSchemeHandlerPrivate(scheme, this, profile)) @@ -74,9 +97,23 @@ QWebEngineUrlSchemeHandler::~QWebEngineUrlSchemeHandler() d_ptr->m_profile->d_func()->removeUrlSchemeHandler(this); } +/*! + Returns the custom URL scheme handled. +*/ QByteArray QWebEngineUrlSchemeHandler::scheme() const { return d_ptr->scheme(); } +/*! + \fn void QWebEngineUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) + + This method is called whenever a request for the registered scheme is started. + + This method must be reimplemented by all custom URL scheme handlers. + The request is asynchronous and does not need to be handled right away. + + \sa QWebEngineUrlRequestJob +*/ + QT_END_NAMESPACE diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index d615b0f9c..dba37cea7 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -81,7 +81,7 @@ void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient* if (pagePrivate->view) { pagePrivate->view->layout()->addWidget(this); pagePrivate->view->setFocusProxy(this); - QOpenGLWidget::show(); + show(); } else setParent(0); } diff --git a/tests/quicktestbrowser/ApplicationRoot.qml b/tests/quicktestbrowser/ApplicationRoot.qml index b16ee0078..71737694d 100644 --- a/tests/quicktestbrowser/ApplicationRoot.qml +++ b/tests/quicktestbrowser/ApplicationRoot.qml @@ -39,9 +39,19 @@ ****************************************************************************/ import QtQuick 2.1 +import QtWebEngine 1.1 QtObject { id: root + + property QtObject testProfile: WebEngineProfile { + storageName: "Test" + } + + property QtObject otrProfile: WebEngineProfile { + offTheRecord: true + } + property Component browserWindowComponent: BrowserWindow { applicationRoot: root onClosing: destroy() @@ -49,10 +59,19 @@ QtObject { property Component browserDialogComponent: BrowserDialog { onClosing: destroy() } - function createWindow() { return browserWindowComponent.createObject(root) } - function createDialog() { return browserDialogComponent.createObject(root) } + function createWindow(profile) { + var newWindow = browserWindowComponent.createObject(root) + newWindow.currentWebView.profile = profile + profile.downloadRequested.connect(newWindow.onDownloadRequested) + return newWindow + } + function createDialog(profile) { + var newDialog = browserDialogComponent.createObject(root) + newDialog.currentWebView.profile = profile + return newDialog + } function load(url) { - var browserWindow = createWindow() + var browserWindow = createWindow(testProfile) browserWindow.currentWebView.url = url } } diff --git a/tests/quicktestbrowser/BrowserDialog.qml b/tests/quicktestbrowser/BrowserDialog.qml index 302833083..6202d02f7 100644 --- a/tests/quicktestbrowser/BrowserDialog.qml +++ b/tests/quicktestbrowser/BrowserDialog.qml @@ -40,7 +40,7 @@ import QtQuick 2.1 import QtQuick.Window 2.2 -import QtWebEngine 1.0 +import QtWebEngine 1.1 Window { property alias currentWebView: webView diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml index 6dfe36761..e626f00c7 100644 --- a/tests/quicktestbrowser/BrowserWindow.qml +++ b/tests/quicktestbrowser/BrowserWindow.qml @@ -79,22 +79,6 @@ ApplicationWindow { property alias pluginsEnabled: pluginsEnabled.checked; } - WebEngineProfile { - id: testProfile - storageName: "Test" - httpCacheType: httpDiskCacheEnabled.checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache; - onDownloadRequested: { - downloadView.visible = true - downloadView.append(download) - download.accept() - } - } - - WebEngineProfile { - id: otrProfile - offTheRecord: true - } - // Make sure the Qt.WindowFullscreenButtonHint is set on OS X. Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint @@ -128,7 +112,7 @@ ApplicationWindow { Action { shortcut: "Ctrl+T" onTriggered: { - tabs.createEmptyTab() + tabs.createEmptyTab(currentWebView.profile) tabs.currentIndex = tabs.count - 1 addressBar.forceActiveFocus(); addressBar.selectAll(); @@ -271,13 +255,15 @@ ApplicationWindow { id: offTheRecordEnabled text: "Off The Record" checkable: true - checked: false + checked: currentWebView.profile.offTheRecord + onToggled: currentWebView.profile = checked ? otrProfile : testProfile; } MenuItem { id: httpDiskCacheEnabled text: "HTTP Disk Cache" - checkable: true - checked: (testProfile.httpCacheType == WebEngineProfile.DiskHttpCache) + checkable: !currentWebView.profile.offTheRecord + checked: (currentWebView.profile.httpCacheType == WebEngineProfile.DiskHttpCache) + onToggled: currentWebView.profile.httpCacheType = checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache; } } } @@ -304,16 +290,17 @@ ApplicationWindow { TabView { id: tabs - function createEmptyTab() { + function createEmptyTab(profile) { var tab = addTab("", tabComponent) // We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately. tab.active = true tab.title = Qt.binding(function() { return tab.item.title }) + tab.item.webView.profile = profile return tab } anchors.fill: parent - Component.onCompleted: createEmptyTab() + Component.onCompleted: createEmptyTab(testProfile) Component { id: tabComponent @@ -342,7 +329,6 @@ ApplicationWindow { WebEngineView { id: webEngineView - profile: offTheRecordEnabled.checked ? otrProfile : testProfile anchors { fill: parent @@ -383,17 +369,17 @@ ApplicationWindow { if (!request.userInitiated) print("Warning: Blocked a popup window.") else if (request.destination == WebEngineView.NewViewInTab) { - var tab = tabs.createEmptyTab() + var tab = tabs.createEmptyTab(currentWebView.profile) tabs.currentIndex = tabs.count - 1 request.openIn(tab.item.webView) } else if (request.destination == WebEngineView.NewViewInBackgroundTab) { - var tab = tabs.createEmptyTab() + var tab = tabs.createEmptyTab(currentWebView.profile) request.openIn(tab.item.webView) } else if (request.destination == WebEngineView.NewViewInDialog) { - var dialog = applicationRoot.createDialog() + var dialog = applicationRoot.createDialog(currentWebView.profile) request.openIn(dialog.currentWebView) } else { - var window = applicationRoot.createWindow() + var window = applicationRoot.createWindow(currentWebView.profile) request.openIn(window.currentWebView) } } @@ -514,6 +500,12 @@ ApplicationWindow { anchors.fill: parent } + function onDownloadRequested(download) { + downloadView.visible = true + downloadView.append(download) + download.accept() + } + ZoomController { id: zoomController y: parent.mapFromItem(currentWebView, 0 , 0).y - 4 diff --git a/tools/buildscripts/find-included-moc-files b/tools/buildscripts/find-included-moc-files index c76360299..e55f3824c 100755 --- a/tools/buildscripts/find-included-moc-files +++ b/tools/buildscripts/find-included-moc-files @@ -10,4 +10,4 @@ for f in filter(os.path.isfile, sys.argv[1:]): if m: includedMocs.add(m.group(1)) for moc in includedMocs: - print(moc) + print moc diff --git a/tools/buildscripts/find-mocables b/tools/buildscripts/find-mocables index 6c709399c..7c383cfec 100755 --- a/tools/buildscripts/find-mocables +++ b/tools/buildscripts/find-mocables @@ -23,4 +23,4 @@ for f in filter(os.path.isfile, sys.argv[1:]): if re.match(".*Q_OBJECT", line): mocables.add(f) for mocable in mocables: - print(mocable) + print mocable diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf index e1864f7b3..ef0320da1 100644 --- a/tools/qmake/mkspecs/features/functions.prf +++ b/tools/qmake/mkspecs/features/functions.prf @@ -22,8 +22,8 @@ defineTest(isPlatformSupported) { } defineTest(isPythonVersionSupported) { - python_major_version = $$system('python -c "import sys; print(sys.version_info.major)"') - python_minor_version = $$system('python -c "import sys; print(sys.version_info.minor)"') + python_major_version = $$system('python -c "import sys; print sys.version_info.major"') + python_minor_version = $$system('python -c "import sys; print sys.version_info.minor"') lessThan(python_major_version, 3): greaterThan(python_major_version, 1): greaterThan(python_minor_version, 6): return(true) skipBuild("Using Python version "$$python_major_version"."$$python_minor_version", but Python version 2 (2.7 or later) is required to build Qt WebEngine.") return(false) |