summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-11-03 07:31:53 +0100
committerLiang Qi <liang.qi@qt.io>2017-11-03 07:31:53 +0100
commitb045cf0ab9756a67a5a1037c231199ee9bf2d074 (patch)
tree43831df602905b64552cf31a233127bed9904fc8 /src
parent0bbaf0d5d7b2d406eda57d40370b00fb79cc0aeb (diff)
parent7f7af6290a63bdab76855da5866881c8a53f045c (diff)
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts: src/3rdparty Change-Id: Ie6b1922db2269e0e0561022162228a7c8609c9ba
Diffstat (limited to 'src')
m---------src/3rdparty0
-rw-r--r--src/buildtools/gn.pro2
-rw-r--r--src/core/api/core_api.pro8
-rw-r--r--src/core/content_main_delegate_qt.cpp34
-rw-r--r--src/core/core_module.pro4
-rw-r--r--src/core/delegated_frame_node.cpp45
-rw-r--r--src/core/delegated_frame_node.h3
-rw-r--r--src/core/gn_run.pro2
-rw-r--r--src/core/render_widget_host_view_qt.cpp24
-rw-r--r--src/core/render_widget_host_view_qt.h4
-rw-r--r--src/core/surface_factory_qt.cpp30
-rw-r--r--src/core/type_conversion.h5
-rw-r--r--src/core/url_request_context_getter_qt.cpp19
-rw-r--r--src/core/url_request_context_getter_qt.h2
-rw-r--r--src/core/url_request_custom_job.cpp62
-rw-r--r--src/core/url_request_custom_job.h4
-rw-r--r--src/core/url_request_custom_job_delegate.cpp11
-rw-r--r--src/core/url_request_custom_job_delegate.h3
-rw-r--r--src/core/url_request_custom_job_proxy.cpp7
-rw-r--r--src/core/url_request_custom_job_proxy.h6
-rw-r--r--src/core/web_event_factory.cpp48
-rw-r--r--src/core/web_event_factory.h1
-rw-r--r--src/src.pro2
-rw-r--r--src/tools/qwebengine_convert_dict/main.cpp6
-rw-r--r--src/webengine/api/qquickwebenginefaviconprovider.cpp6
-rw-r--r--src/webengine/webengine.pro2
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp32
-rw-r--r--src/webenginewidgets/api/qwebengineprofile_p.h19
-rw-r--r--src/webenginewidgets/webenginewidgets.pro1
29 files changed, 332 insertions, 60 deletions
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 04cd5620124dc05c019a582363a93a78665b181
+Subproject 0c43a097b39603be90162b519927a7e47f15ae9
diff --git a/src/buildtools/gn.pro b/src/buildtools/gn.pro
index 02d3df652..9d9af9eb8 100644
--- a/src/buildtools/gn.pro
+++ b/src/buildtools/gn.pro
@@ -4,7 +4,7 @@ option(host_build)
!debug_and_release: CONFIG += release
include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
-QT_FOR_CONFIG += webengine-private
+QT_FOR_CONFIG += webengine webengine-private
build_pass|!debug_and_release {
!qtConfig(system-gn): CONFIG(release, debug|release) {
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 05166536e..270595378 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -55,3 +55,11 @@ unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!static {
SOURCES += qtbug-60565.cpp \
qtbug-61521.cpp
}
+
+msvc {
+ # Create a list of object files that can be used as response file for the linker.
+ # This is done to simulate -whole-archive on MSVC.
+ QMAKE_POST_LINK = \
+ "if exist $(DESTDIR_TARGET).objects del $(DESTDIR_TARGET).objects$$escape_expand(\\n\\t)" \
+ "for %%a in ($(OBJECTS)) do echo $$shell_quote($$shell_path($$OUT_PWD))\\%%a >> $(DESTDIR_TARGET).objects"
+}
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 720db77bf..359e0b3d9 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -40,19 +40,23 @@
#include "content_main_delegate_qt.h"
#include "base/command_line.h"
+#include <base/i18n/rtl.h>
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
+#include <chrome/grit/generated_resources.h>
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/resource/resource_bundle.h"
+#include <ui/base/webui/jstemplate_builder.h>
#include "net/grit/net_resources.h"
#include "net/base/net_module.h"
#include "content_client_qt.h"
#include "renderer/content_renderer_client_qt.h"
+#include "type_conversion.h"
#include "web_engine_library_info.h"
#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
@@ -63,12 +67,38 @@
#include "ui/base/ui_base_switches.h"
#endif
+#include <QtCore/qcoreapplication.h>
+
namespace QtWebEngineCore {
+// The logic of this function is based on chrome/common/net/net_resource_provider.cc
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.Chromium file.
+static std::string constructDirHeaderHTML()
+{
+ base::DictionaryValue dict;
+ dict.SetString("header", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_HEADER));
+ dict.SetString("parentDirText", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_PARENT));
+ dict.SetString("headerName", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_NAME));
+ dict.SetString("headerSize", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_SIZE));
+ dict.SetString("headerDateModified",
+ l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_DATE_MODIFIED));
+ dict.SetString("language", l10n_util::GetLanguage(base::i18n::GetConfiguredLocale()));
+ dict.SetString("listingParsingErrorBoxText",
+ l10n_util::GetStringFUTF16(IDS_DIRECTORY_LISTING_PARSING_ERROR_BOX_TEXT,
+ toString16(QCoreApplication::applicationName())));
+ dict.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
+ std::string html = webui::GetI18nTemplateHtml(
+ ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML),
+ &dict);
+ return html;
+}
+
static base::StringPiece PlatformResourceProvider(int key) {
if (key == IDR_DIR_HEADER_HTML) {
- base::StringPiece html_data = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML);
- return html_data;
+ static std::string html_data = constructDirHeaderHTML();
+ return base::StringPiece(html_data);
}
return base::StringPiece();
}
diff --git a/src/core/core_module.pro b/src/core/core_module.pro
index 55b20cda2..78bb8baee 100644
--- a/src/core/core_module.pro
+++ b/src/core/core_module.pro
@@ -61,7 +61,9 @@ osx {
QMAKE_LFLAGS_DEBUG -= /DEBUG
QMAKE_LFLAGS_DEBUG += /DEBUG:FASTLINK
}
- QMAKE_LFLAGS += /WHOLEARCHIVE:$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib
+ # Simulate -whole-archive by passing the list of object files that belong to the public
+ # API library as response file to the linker.
+ QMAKE_LFLAGS += @$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib.objects
} else {
LIBS_PRIVATE += -Wl,-whole-archive -l$$api_library_name -Wl,-no-whole-archive
}
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index d0d840ecb..d6ee87950 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -849,8 +849,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// countering the scale of devicePixel-scaled tiles when rendering them
// to the final surface.
QMatrix4x4 matrix;
- matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio,
- 1 / m_chromiumCompositorData->frameDevicePixelRatio);
+ const float devicePixelRatio = m_chromiumCompositorData->frameDevicePixelRatio;
+ matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio);
if (QSGTransformNode::matrix() != matrix)
setMatrix(matrix);
@@ -872,11 +872,19 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
frameData->resource_list.clear();
QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
+ const QSizeF viewportSizeInPt = apiDelegate->screenRect().size();
+ const QSize viewportSize = (viewportSizeInPt * devicePixelRatio).toSize();
+
// We first compare if the render passes from the previous frame data are structurally
// equivalent to the render passes in the current frame data. If they are, we are going
// to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree.
- cc::CompositorFrame *previousFrameData = &m_chromiumCompositorData->previousFrameData;
- const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData) || m_sceneGraphNodes.empty();
+ //
+ // Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside
+ // of the visible area, we also have to rebuild the tree whenever the window is resized.
+ const bool buildNewTree =
+ !areRenderPassStructuresEqual(frameData, &m_chromiumCompositorData->previousFrameData) ||
+ m_sceneGraphNodes.empty() ||
+ viewportSize != m_previousViewportSize;
m_chromiumCompositorData->previousFrameData = cc::CompositorFrame();
SGObjects previousSGObjects;
@@ -904,10 +912,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// All RenderPasses except the last one are rendered to an FBO.
cc::RenderPass *rootRenderPass = frameData->render_pass_list.back().get();
- QRectF screenRectQt = apiDelegate->screenRect();
- gfx::Size thisSize(int(screenRectQt.width() * m_chromiumCompositorData->frameDevicePixelRatio),
- int(screenRectQt.height() * m_chromiumCompositorData->frameDevicePixelRatio));
-
+ gfx::Rect viewportRect(toGfx(viewportSize));
for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
cc::RenderPass *pass = frameData->render_pass_list.at(i).get();
@@ -939,12 +944,14 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
scissorRect = pass->output_rect;
} else {
renderPassParent = this;
- scissorRect = gfx::Rect(thisSize);
+ scissorRect = viewportRect;
scissorRect += rootRenderPass->output_rect.OffsetFromOrigin();
}
- if (scissorRect.IsEmpty())
+ if (scissorRect.IsEmpty()) {
+ holdResources(pass, resourceCandidates);
continue;
+ }
QSGNode *renderPassChain = nullptr;
if (buildNewTree)
@@ -967,8 +974,10 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
if (quadState->is_clipped)
targetRect.Intersect(quadState->clip_rect);
targetRect.Intersect(scissorRect);
- if (targetRect.IsEmpty())
+ if (targetRect.IsEmpty()) {
+ holdResources(quad, resourceCandidates);
continue;
+ }
if (quadState->sorting_context_id != currentSortingContextId) {
flushPolygons(&polygonQueue, renderPassChain,
@@ -1007,6 +1016,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
ResourceHolderIterator end = resourceCandidates.constEnd();
for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it)
resourcesToRelease->push_back((*it)->returnResource());
+
+ m_previousViewportSize = viewportSize;
}
void DelegatedFrameNode::flushPolygons(
@@ -1224,6 +1235,18 @@ ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHa
return resource.data();
}
+void DelegatedFrameNode::holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
+{
+ for (auto resource : quad->resources)
+ findAndHoldResource(resource, candidates);
+}
+
+void DelegatedFrameNode::holdResources(const cc::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
+{
+ for (const auto &quad : pass->quad_list)
+ holdResources(quad, candidates);
+}
+
QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate)
{
// QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree,
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index b83f4682a..c627cdf95 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -126,6 +126,8 @@ private:
static void fenceAndUnlockQt(DelegatedFrameNode *frameNode);
ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
+ void holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
+ void holdResources(const cc::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
QSGTexture *initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0);
QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData;
@@ -143,6 +145,7 @@ private:
bool m_contextShared;
QScopedPointer<QOffscreenSurface> m_offsurface;
#endif
+ QSize m_previousViewportSize;
};
} // namespace QtWebEngineCore
diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro
index c565b99a4..a9089c569 100644
--- a/src/core/gn_run.pro
+++ b/src/core/gn_run.pro
@@ -1,5 +1,5 @@
include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
-QT_FOR_CONFIG += webengine-private
+QT_FOR_CONFIG += webengine webengine-private
TEMPLATE = aux
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 7ce71a81d..a12dea6ad 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -282,6 +282,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
, m_cursorPositionWithinSelection(-1)
, m_cursorPosition(0)
, m_emptyPreviousSelection(true)
+ , m_wheelAckPending(false)
{
m_host->SetView(this);
#ifndef QT_NO_ACCESSIBILITY
@@ -1315,7 +1316,28 @@ void RenderWidgetHostViewQt::accessibilityActiveChanged(bool active)
void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev)
{
- m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale()));
+ if (!m_wheelAckPending) {
+ Q_ASSERT(m_pendingWheelEvents.isEmpty());
+ m_wheelAckPending = true;
+ m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale()));
+ return;
+ }
+ if (!m_pendingWheelEvents.isEmpty()) {
+ // Try to combine with this wheel event with the last pending one.
+ if (WebEventFactory::coalesceWebWheelEvent(m_pendingWheelEvents.last(), ev, dpiScale()))
+ return;
+ }
+ m_pendingWheelEvents.append(WebEventFactory::toWebWheelEvent(ev, dpiScale()));
+}
+
+void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &/*event*/, content::InputEventAckState /*ack_result*/)
+{
+ m_wheelAckPending = false;
+ if (!m_pendingWheelEvents.isEmpty()) {
+ m_wheelAckPending = true;
+ m_host->ForwardWheelEvent(m_pendingWheelEvents.takeFirst());
+ }
+ // TODO: We could forward unhandled wheelevents to our parent.
}
void RenderWidgetHostViewQt::clearPreviousTouchMotionState()
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 74f14d0d4..c896cf058 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -153,6 +153,7 @@ public:
bool HasAcceleratedSurface(const gfx::Size&) override;
void DidCreateNewRendererCompositorFrameSink(cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override;
void SubmitCompositorFrame(const viz::LocalSurfaceId&, cc::CompositorFrame) override;
+ void WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState ack_result) override;
void GetScreenInfo(content::ScreenInfo* results);
gfx::Rect GetBoundsInRootWindow() override;
@@ -274,6 +275,9 @@ private:
QString m_surroundingText;
bool m_imeHasHiddenTextCapability;
+
+ bool m_wheelAckPending;
+ QList<blink::WebMouseWheelEvent> m_pendingWheelEvents;
};
} // namespace QtWebEngineCore
diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp
index d0741506a..c976e8b04 100644
--- a/src/core/surface_factory_qt.cpp
+++ b/src/core/surface_factory_qt.cpp
@@ -56,7 +56,13 @@
#if defined(USE_OZONE)
#include <EGL/egl.h>
-#include <dlfcn.h>
+
+#ifndef QT_LIBDIR_EGL
+#define QT_LIBDIR_EGL "/usr/lib"
+#endif
+#ifndef QT_LIBDIR_GLES2
+#define QT_LIBDIR_GLES2 QT_LIBDIR_EGL
+#endif
namespace QtWebEngineCore {
@@ -92,21 +98,29 @@ base::NativeLibrary LoadLibrary(const base::FilePath& filename) {
bool GLOzoneQt::LoadGLES2Bindings(gl::GLImplementation /*implementation*/)
{
- base::NativeLibrary eglgles2Library = dlopen(NULL, RTLD_LAZY);
- if (!eglgles2Library) {
- LOG(ERROR) << "Failed to open EGL/GLES2 context " << dlerror();
+ base::FilePath libEGLPath = QtWebEngineCore::toFilePath(QT_LIBDIR_EGL);
+ libEGLPath = libEGLPath.Append("libEGL.so.1");
+ base::NativeLibrary eglLibrary = LoadLibrary(libEGLPath);
+ if (!eglLibrary)
+ return false;
+
+ base::FilePath libGLES2Path = QtWebEngineCore::toFilePath(QT_LIBDIR_GLES2);
+ libGLES2Path = libGLES2Path.Append("libGLESv2.so.2");
+ base::NativeLibrary gles2Library = LoadLibrary(libGLES2Path);
+ if (!gles2Library)
return false;
- }
- gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglgles2Library, "eglGetProcAddress"));
+ gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglLibrary, "eglGetProcAddress"));
if (!get_proc_address) {
LOG(ERROR) << "eglGetProcAddress not found.";
- base::UnloadNativeLibrary(eglgles2Library);
+ base::UnloadNativeLibrary(eglLibrary);
+ base::UnloadNativeLibrary(gles2Library);
return false;
}
gl::SetGLGetProcAddressProc(get_proc_address);
- gl::AddGLNativeLibrary(eglgles2Library);
+ gl::AddGLNativeLibrary(eglLibrary);
+ gl::AddGLNativeLibrary(gles2Library);
return true;
}
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index d9ba735bd..eb7c9d48b 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -142,6 +142,11 @@ inline QRectF toQt(const gfx::RectF &rect)
return QRectF(rect.x(), rect.y(), rect.width(), rect.height());
}
+inline gfx::Size toGfx(const QSize &size)
+{
+ return gfx::Size(size.width(), size.height());
+}
+
inline QSize toQt(const gfx::Size &size)
{
return QSize(size.width(), size.height());
diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp
index 4f30881c8..b77cd50f9 100644
--- a/src/core/url_request_context_getter_qt.cpp
+++ b/src/core/url_request_context_getter_qt.cpp
@@ -59,6 +59,8 @@
#include "net/dns/mapped_host_resolver.h"
#include "net/extras/sqlite/sqlite_channel_id_store.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_auth_preferences.h"
+#include "net/http/http_auth_scheme.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties_impl.h"
@@ -209,6 +211,13 @@ void URLRequestContextGetterQt::generateAllStorage()
m_updateAllStorage = false;
}
+static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme,
+ net::kDigestAuthScheme,
+#if defined(USE_KERBEROS) && !defined(OS_ANDROID)
+ net::kNegotiateAuthScheme,
+#endif
+ net::kNtlmAuthScheme };
+
void URLRequestContextGetterQt::generateStorage()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -251,7 +260,15 @@ void URLRequestContextGetterQt::generateStorage()
m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(new net::TransportSecurityState()));
- m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
+ if (!m_httpAuthPreferences) {
+ std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes));
+ m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+ , std::string() /* gssapi library name */
+#endif
+ ));
+ }
+ m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(), host_resolver.get()));
m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl));
// Give |m_storage| ownership at the end in case it's |mapped_host_resolver|.
diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h
index 511d9eb04..495c9eb28 100644
--- a/src/core/url_request_context_getter_qt.h
+++ b/src/core/url_request_context_getter_qt.h
@@ -62,6 +62,7 @@
#include <QtCore/qsharedpointer.h>
namespace net {
+class HttpAuthPreferences;
class MappedHostResolver;
class ProxyConfigService;
}
@@ -126,6 +127,7 @@ private:
scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate;
content::URLRequestInterceptorScopedVector m_requestInterceptors;
std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession;
+ std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences;
QList<QByteArray> m_installedCustomSchemes;
QWebEngineUrlRequestInterceptor* m_requestInterceptor;
diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp
index 47c9b3b4c..b49135f79 100644
--- a/src/core/url_request_custom_job.cpp
+++ b/src/core/url_request_custom_job.cpp
@@ -56,6 +56,9 @@ URLRequestCustomJob::URLRequestCustomJob(URLRequest *request,
, m_proxy(new URLRequestCustomJobProxy(this, scheme, adapter))
, m_device(nullptr)
, m_error(0)
+ , m_pendingReadSize(0)
+ , m_pendingReadPos(0)
+ , m_pendingReadBuffer(nullptr)
{
}
@@ -83,6 +86,12 @@ void URLRequestCustomJob::Kill()
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (m_device && m_device->isOpen())
m_device->close();
+ if (m_pendingReadBuffer) {
+ m_pendingReadBuffer->Release();
+ m_pendingReadBuffer = nullptr;
+ m_pendingReadSize = 0;
+ m_pendingReadPos = 0;
+ }
m_device = nullptr;
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&URLRequestCustomJobProxy::release,
@@ -127,13 +136,64 @@ int URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize)
if (m_error)
return m_error;
qint64 rv = m_device ? m_device->read(buf->data(), bufSize) : -1;
- if (rv >= 0) {
+ if (rv > 0) {
return static_cast<int>(rv);
+ } else if (rv == 0) {
+ // Returning zero is interpreted as EOF by Chromium, so only
+ // return zero if we are the end of the file.
+ if (m_device->atEnd())
+ return 0;
+ // Otherwise return IO_PENDING and call ReadRawDataComplete when we have data
+ // for them.
+ buf->AddRef();
+ m_pendingReadPos = 0;
+ m_pendingReadSize = bufSize;
+ m_pendingReadBuffer = buf;
+ return ERR_IO_PENDING;
} else {
// QIODevice::read might have called fail on us.
if (m_error)
return m_error;
+ if (m_device && m_device->atEnd())
+ return 0;
return ERR_FAILED;
}
}
+
+void URLRequestCustomJob::notifyReadyRead()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (!m_device)
+ return;
+ if (!m_pendingReadSize)
+ return;
+ Q_ASSERT(m_pendingReadBuffer);
+ if (!m_pendingReadBuffer)
+ return;
+
+ qint64 rv = m_device->read(m_pendingReadBuffer->data() + m_pendingReadPos, m_pendingReadSize - m_pendingReadPos);
+ if (rv == 0)
+ return;
+ if (rv < 0) {
+ if (m_error)
+ rv = m_error;
+ else if (m_device->atEnd())
+ rv = 0;
+ else
+ rv = ERR_FAILED;
+ } else {
+ m_pendingReadPos += rv;
+ if (m_pendingReadPos < m_pendingReadSize && !m_device->atEnd())
+ return;
+ rv = m_pendingReadPos;
+ }
+ // killJob may be called from ReadRawDataComplete
+ net::IOBuffer *buf = m_pendingReadBuffer;
+ m_pendingReadBuffer = nullptr;
+ m_pendingReadSize = 0;
+ m_pendingReadPos = 0;
+ ReadRawDataComplete(rv);
+ buf->Release();
+}
+
} // namespace
diff --git a/src/core/url_request_custom_job.h b/src/core/url_request_custom_job.h
index 68a834d48..021cf3204 100644
--- a/src/core/url_request_custom_job.h
+++ b/src/core/url_request_custom_job.h
@@ -70,12 +70,16 @@ protected:
virtual ~URLRequestCustomJob();
private:
+ void notifyReadyRead();
scoped_refptr<URLRequestCustomJobProxy> m_proxy;
std::string m_mimeType;
std::string m_charset;
GURL m_redirect;
QIODevice *m_device;
int m_error;
+ int m_pendingReadSize;
+ int m_pendingReadPos;
+ net::IOBuffer *m_pendingReadBuffer;
friend class URLRequestCustomJobProxy;
diff --git a/src/core/url_request_custom_job_delegate.cpp b/src/core/url_request_custom_job_delegate.cpp
index 14de9a812..6b82cebb5 100644
--- a/src/core/url_request_custom_job_delegate.cpp
+++ b/src/core/url_request_custom_job_delegate.cpp
@@ -73,16 +73,23 @@ QByteArray URLRequestCustomJobDelegate::method() const
void URLRequestCustomJobDelegate::reply(const QByteArray &contentType, QIODevice *device)
{
+ if (device)
+ QObject::connect(device, &QIODevice::readyRead, this, &URLRequestCustomJobDelegate::slotReadyRead);
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
base::Bind(&URLRequestCustomJobProxy::reply,
m_proxy,contentType.toStdString(),device));
}
+void URLRequestCustomJobDelegate::slotReadyRead()
+{
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&URLRequestCustomJobProxy::readyRead, m_proxy));
+}
+
void URLRequestCustomJobDelegate::abort()
{
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::abort,
- m_proxy));
+ base::Bind(&URLRequestCustomJobProxy::abort, m_proxy));
}
void URLRequestCustomJobDelegate::redirect(const QUrl &url)
diff --git a/src/core/url_request_custom_job_delegate.h b/src/core/url_request_custom_job_delegate.h
index eb99f3576..3f5e6d591 100644
--- a/src/core/url_request_custom_job_delegate.h
+++ b/src/core/url_request_custom_job_delegate.h
@@ -74,6 +74,9 @@ public:
void abort();
void fail(Error);
+private Q_SLOTS:
+ void slotReadyRead();
+
private:
URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy,
const QUrl &url,
diff --git a/src/core/url_request_custom_job_proxy.cpp b/src/core/url_request_custom_job_proxy.cpp
index d53602c85..832d3d11e 100644
--- a/src/core/url_request_custom_job_proxy.cpp
+++ b/src/core/url_request_custom_job_proxy.cpp
@@ -144,6 +144,13 @@ void URLRequestCustomJobProxy::fail(int error)
// else we fail on the next read, or the read that might already be in progress
}
+void URLRequestCustomJobProxy::readyRead()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (m_job)
+ m_job->notifyReadyRead();
+}
+
void URLRequestCustomJobProxy::initialize(GURL url, std::string method)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/src/core/url_request_custom_job_proxy.h b/src/core/url_request_custom_job_proxy.h
index df7171f5e..3ea30a4e1 100644
--- a/src/core/url_request_custom_job_proxy.h
+++ b/src/core/url_request_custom_job_proxy.h
@@ -63,6 +63,7 @@ public:
QWeakPointer<const BrowserContextAdapter> adapter);
~URLRequestCustomJobProxy();
+ // Called from URLRequestCustomJobDelegate via post:
//void setReplyCharset(const std::string &);
void reply(std::string mimeType, QIODevice *device);
void redirect(GURL url);
@@ -70,12 +71,13 @@ public:
void fail(int error);
void release();
void initialize(GURL url, std::string method);
+ void readyRead();
- //IO thread owned
+ // IO thread owned:
URLRequestCustomJob *m_job;
bool m_started;
- //UI thread owned
+ // UI thread owned:
std::string m_scheme;
URLRequestCustomJobDelegate *m_delegate;
QWeakPointer<const BrowserContextAdapter> m_adapter;
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index b785adec0..2e0323f6d 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -1289,38 +1289,56 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub
}
#endif
-blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, double dpiScale)
+static void setBlinkWheelEventDelta(blink::WebMouseWheelEvent &webEvent)
{
- WebMouseWheelEvent webEvent;
- webEvent.delta_x = 0;
- webEvent.delta_y = 0;
- webEvent.wheel_ticks_x = 0;
- webEvent.wheel_ticks_y = 0;
- webEvent.SetType(webEventTypeForEvent(ev));
- webEvent.SetModifiers(modifiersForEvent(ev));
- webEvent.SetTimeStampSeconds(currentTimeForEvent(ev));
-
- webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep;
- webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep;
-
// We can't use the device specific QWheelEvent::pixelDelta(), so we calculate
// a pixel delta based on ticks and scroll per line.
static const float cDefaultQtScrollStep = 20.f;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
- const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines();
+ static const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines();
#else
- const int wheelScrollLines = 3;
+ static const int wheelScrollLines = 3;
#endif
webEvent.delta_x = webEvent.wheel_ticks_x * wheelScrollLines * cDefaultQtScrollStep;
webEvent.delta_y = webEvent.wheel_ticks_y * wheelScrollLines * cDefaultQtScrollStep;
+}
+
+blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, double dpiScale)
+{
+ WebMouseWheelEvent webEvent;
+ webEvent.SetType(webEventTypeForEvent(ev));
+ webEvent.SetModifiers(modifiersForEvent(ev));
+ webEvent.SetTimeStampSeconds(currentTimeForEvent(ev));
webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale);
webEvent.SetPositionInScreen(ev->globalX(), ev->globalY());
+ webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep;
+ webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep;
+ setBlinkWheelEventDelta(webEvent);
+
return webEvent;
}
+bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, QWheelEvent *ev, double dpiScale)
+{
+ if (webEventTypeForEvent(ev) != webEvent.GetType())
+ return false;
+ if (modifiersForEvent(ev) != webEvent.GetModifiers())
+ return false;
+
+ webEvent.SetTimeStampSeconds(currentTimeForEvent(ev));
+ webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale);
+ webEvent.SetPositionInScreen(ev->globalX(), ev->globalY());
+
+ webEvent.wheel_ticks_x += static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep;
+ webEvent.wheel_ticks_y += static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep;
+ setBlinkWheelEventDelta(webEvent);
+
+ return true;
+}
+
content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev)
{
content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev));
diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h
index c9ae86a73..ca0f6035f 100644
--- a/src/core/web_event_factory.h
+++ b/src/core/web_event_factory.h
@@ -70,6 +70,7 @@ public:
static blink::WebGestureEvent toWebGestureEvent(QNativeGestureEvent *, double dpiScale);
#endif
static blink::WebMouseWheelEvent toWebWheelEvent(QWheelEvent*, double dpiScale);
+ static bool coalesceWebWheelEvent(blink::WebMouseWheelEvent &, QWheelEvent*, double dpiScale);
static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*);
};
diff --git a/src/src.pro b/src/src.pro
index 1cd23f9fa..76d342c8d 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,5 +1,5 @@
include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
-QT_FOR_CONFIG += webengine-private
+QT_FOR_CONFIG += webengine webengine-private
TEMPLATE = subdirs
diff --git a/src/tools/qwebengine_convert_dict/main.cpp b/src/tools/qwebengine_convert_dict/main.cpp
index e7dcc22d9..3a1a1ff64 100644
--- a/src/tools/qwebengine_convert_dict/main.cpp
+++ b/src/tools/qwebengine_convert_dict/main.cpp
@@ -30,6 +30,7 @@
#include <QTextStream>
#include <QLibraryInfo>
#include <QDir>
+#include <QCoreApplication>
// see also src/core/type_conversion.h
inline base::FilePath::StringType toFilePathString(const QString &str)
@@ -117,6 +118,11 @@ QString frameworkIcuDataPath()
int main(int argc, char *argv[])
{
+ // Required only for making QLibraryInfo::location() return a valid path, when the application
+ // picks up a qt.conf file (which is the case for official Qt packages).
+ QCoreApplication app(argc, argv);
+ Q_UNUSED(app);
+
QTextStream out(stdout);
if (argc != 3) {
diff --git a/src/webengine/api/qquickwebenginefaviconprovider.cpp b/src/webengine/api/qquickwebenginefaviconprovider.cpp
index b5ad6960a..3255f22be 100644
--- a/src/webengine/api/qquickwebenginefaviconprovider.cpp
+++ b/src/webengine/api/qquickwebenginefaviconprovider.cpp
@@ -70,7 +70,11 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url)
QUrl providerUrl;
providerUrl.setScheme(QStringLiteral("image"));
providerUrl.setHost(identifier());
- providerUrl.setPath(QStringLiteral("/%1").arg(url.toString()));
+ providerUrl.setPath(QStringLiteral("/%1").arg(url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment)));
+ if (url.hasQuery())
+ providerUrl.setQuery(url.query(QUrl::FullyDecoded));
+ if (url.hasFragment())
+ providerUrl.setFragment(url.fragment(QUrl::FullyDecoded));
return providerUrl;
}
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 4b2170cbc..24fa2d9d8 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -1,5 +1,5 @@
include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
-QT_FOR_CONFIG += webengine-private
+QT_FOR_CONFIG += webengine webengine-private
TARGET = QtWebEngine
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index f844ddcd6..c4de46b67 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -145,24 +145,35 @@ using QtWebEngineCore::BrowserContextAdapter;
\sa QWebEngineDownloadItem, QWebEnginePage::download()
*/
-QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext)
+QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile)
+ : QObject(BrowserContextAdapter::globalQObjectRoot())
+ , browserContextRef(browserContext)
+ , m_profile(profile)
+{
+ browserContextRef->addClient(m_profile);
+}
+
+QWebEngineBrowserContext::~QWebEngineBrowserContext()
+{
+ Q_ASSERT(m_profile);
+ // In the case the user sets this profile as the parent of the interceptor
+ // it can be deleted before the browser-context still referencing it is.
+ browserContextRef->setRequestInterceptor(nullptr);
+ browserContextRef->removeClient(m_profile);
+}
+
+QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext)
: m_settings(new QWebEngineSettings())
, m_scriptCollection(new QWebEngineScriptCollection(new QWebEngineScriptCollectionPrivate(browserContext->userResourceController())))
- , m_browserContextRef(browserContext)
+ , m_browserContext(new QWebEngineBrowserContext(browserContext, this))
{
- m_browserContextRef->addClient(this);
m_settings->d_ptr->initDefaults();
}
QWebEngineProfilePrivate::~QWebEngineProfilePrivate()
{
- // In the case the user sets this profile as the parent of the interceptor
- // it can be deleted before the browser-context still referencing it is.
- m_browserContextRef->setRequestInterceptor(nullptr);
-
delete m_settings;
m_settings = 0;
- m_browserContextRef->removeClient(this);
Q_FOREACH (QWebEngineDownloadItem* download, m_ongoingDownloads) {
if (download)
@@ -172,6 +183,11 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate()
m_ongoingDownloads.clear();
}
+QSharedPointer<QtWebEngineCore::BrowserContextAdapter> QWebEngineProfilePrivate::browserContext() const
+{
+ return m_browserContext->browserContextRef;
+}
+
void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
{
m_ongoingDownloads.remove(downloadId);
diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h
index ffb28ec6d..8cbf241f3 100644
--- a/src/webenginewidgets/api/qwebengineprofile_p.h
+++ b/src/webenginewidgets/api/qwebengineprofile_p.h
@@ -65,15 +65,30 @@ class BrowserContextAdapter;
QT_BEGIN_NAMESPACE
+class QWebEngineProfilePrivate;
class QWebEngineSettings;
+// This is a wrapper class for BrowserContextAdapter. BrowserContextAdapter must be destructed before WebEngineContext
+// is destructed. Therefore access it via the QWebEngineBrowserContext which parent is the WebEngineContext::globalQObject.
+// This guarantees the destruction together with the WebEngineContext.
+class QWebEngineBrowserContext : public QObject {
+public:
+ QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile);
+ ~QWebEngineBrowserContext();
+
+ QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextRef;
+
+private:
+ QWebEngineProfilePrivate *m_profile;
+};
+
class QWebEngineProfilePrivate : public QtWebEngineCore::BrowserContextAdapterClient {
public:
Q_DECLARE_PUBLIC(QWebEngineProfile)
QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext);
~QWebEngineProfilePrivate();
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; }
+ QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const;
QWebEngineSettings *settings() const { return m_settings; }
void downloadDestroyed(quint32 downloadId);
@@ -85,7 +100,7 @@ private:
QWebEngineProfile *q_ptr;
QWebEngineSettings *m_settings;
QScopedPointer<QWebEngineScriptCollection> m_scriptCollection;
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef;
+ QPointer<QWebEngineBrowserContext> m_browserContext;
QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads;
};
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index 29c961c80..958dec07b 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -1,4 +1,3 @@
-include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
QT_FOR_CONFIG += webengine-private
TARGET = QtWebEngineWidgets