diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-12 12:41:40 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-16 12:03:57 +0100 |
commit | 3c544a5d0d59b0533f507a6131fbbc093ed223ea (patch) | |
tree | c64d3ae8e17280350037ff1d6687ec797ca4715c /src | |
parent | e7c869c225075d898cb5d20b194af4b939d2dbc1 (diff) | |
parent | fdec85eba16d6321597e93b447bc13a611cfdd23 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I0dd7c64669f4b130047a4a3836f62f7ee5b5f8d9
Diffstat (limited to 'src')
49 files changed, 940 insertions, 330 deletions
diff --git a/src/3rdparty b/src/3rdparty -Subproject a38752bff0fd3ae3e98ce973a437413e074403a +Subproject 7c8217b36a95e29f7a7832b177e3df8a3308365 diff --git a/src/buildtools/config/support.pri b/src/buildtools/config/support.pri index 54b5738cd..e7f869a15 100644 --- a/src/buildtools/config/support.pri +++ b/src/buildtools/config/support.pri @@ -55,7 +55,6 @@ defineReplace(qtwebengine_checkPdfError) { !qtwebengine_checkForSanitizer(QtPdf):return(false) linux:!qtwebengine_checkForPkgCfg(QtPdf):return(false) linux:!qtwebengine_checkForHostPkgCfg(QtPdf):return(false) - linux:!qtwebengine_checkForPackage(QtPdf,nss):return(false) win32:!qtwebengine_checkForWinVersion(QtPdf):return(false) return(true) } diff --git a/src/buildtools/configure.json b/src/buildtools/configure.json index a7f1d623a..5819fb860 100644 --- a/src/buildtools/configure.json +++ b/src/buildtools/configure.json @@ -399,7 +399,6 @@ && (!config.sanitizer || features.webengine-sanitizer) && (!config.linux || features.pkg-config) && (!config.linux || features.webengine-host-pkg-config) - && (!config.linux || features.webengine-system-nss) && (!config.win32 || features.webengine-winversion)", "output": [ "privateFeature" ] }, diff --git a/src/core/api/qwebenginecontextmenurequest.h b/src/core/api/qwebenginecontextmenurequest.h index bc8095dc9..d9041d797 100644 --- a/src/core/api/qwebenginecontextmenurequest.h +++ b/src/core/api/qwebenginecontextmenurequest.h @@ -46,6 +46,10 @@ #include <QtCore/QPoint> #include <QScopedPointer> +namespace extensions { +class MimeHandlerViewGuestDelegateQt; +} + namespace QtWebEngineCore { class RenderViewContextMenuQt; class WebContentsViewQt; @@ -156,6 +160,7 @@ private: QScopedPointer<QWebEngineContextMenuRequestPrivate> d; friend class QtWebEngineCore::WebContentsViewQt; friend class QtWebEngineCore::RenderViewContextMenuQt; + friend class extensions::MimeHandlerViewGuestDelegateQt; friend class QQuickWebEngineViewPrivate; friend class QQuickWebEngineView; friend class ContextMenuRequestJSWrapper; diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp index 1add722a5..bc0499bca 100644 --- a/src/core/browser_main_parts_qt.cpp +++ b/src/core/browser_main_parts_qt.cpp @@ -59,10 +59,12 @@ #include "content/public/common/service_manager_connection.h" #include "extensions/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_EXTENSIONS) +#include "content/public/browser/plugin_service.h" #include "extensions/common/constants.h" #include "extensions/common/extensions_client.h" #include "extensions/extensions_browser_client_qt.h" #include "extensions/extension_system_factory_qt.h" +#include "extensions/plugin_service_filter_qt.h" #include "common/extensions/extensions_client_qt.h" #endif //BUILDFLAG(ENABLE_EXTENSIONS) #include "services/service_manager/public/cpp/connector.h" @@ -250,6 +252,9 @@ void BrowserMainPartsQt::PreMainMessageLoopRun() extensions::ExtensionsClient::Set(new extensions::ExtensionsClientQt()); extensions::ExtensionsBrowserClient::Set(new extensions::ExtensionsBrowserClientQt()); extensions::ExtensionSystemFactoryQt::GetInstance(); + + content::PluginService *plugin_service = content::PluginService::GetInstance(); + plugin_service->SetFilter(extensions::PluginServiceFilterQt::GetInstance()); #endif //ENABLE_EXTENSIONS } diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 4dd3cadbb..6783175fe 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -50,7 +50,6 @@ #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/platform/platform_event_source.h" -#include "ui/snapshot/snapshot.h" #include "ppapi/buildflags/buildflags.h" #include <QGuiApplication> @@ -149,53 +148,6 @@ std::vector<AccessibilityTreeFormatter::TestPass> AccessibilityTreeFormatter::Ge } } // namespace content -#if defined(USE_AURA) -namespace ui { - -bool GrabWindowSnapshot(gfx::NativeWindow window, - const gfx::Rect& snapshot_bounds, - gfx::Image* image) -{ - NOTIMPLEMENTED(); - return false; -} - -bool GrabViewSnapshot(gfx::NativeView view, - const gfx::Rect& snapshot_bounds, - gfx::Image* image) -{ - NOTIMPLEMENTED(); - return false; -} - -void GrabWindowSnapshotAndScaleAsync(gfx::NativeWindow window, - const gfx::Rect& source_rect, - const gfx::Size& target_size, - GrabWindowSnapshotAsyncCallback callback) -{ - NOTIMPLEMENTED(); - std::move(callback).Run(gfx::Image()); -} - -void GrabWindowSnapshotAsync(gfx::NativeWindow window, - const gfx::Rect& source_rect, - GrabWindowSnapshotAsyncCallback callback) -{ - NOTIMPLEMENTED(); - std::move(callback).Run(gfx::Image()); -} - -void GrabViewSnapshotAsync(gfx::NativeView view, - const gfx::Rect& source_rect, - GrabWindowSnapshotAsyncCallback callback) -{ - NOTIMPLEMENTED(); - std::move(callback).Run(gfx::Image()); -} - -} // namespace ui -#endif // defined(USE_AURA) - std::unique_ptr<ui::OSExchangeDataProvider> ui::OSExchangeDataProviderFactory::CreateProvider() { return nullptr; diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index b70f8a290..fa960c58c 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -68,6 +68,7 @@ #include "content/public/common/service_names.mojom.h" #include "content/public/common/user_agent.h" #include "extensions/buildflags/buildflags.h" +#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_store.h" #include "services/network/network_service.h" @@ -152,12 +153,14 @@ #include "extensions/browser/extension_message_filter.h" #include "extensions/browser/extension_protocols.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/process_map.h" #include "extensions/browser/url_loader_factory_manager.h" #include "extensions/common/constants.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" #include "extensions/extension_web_contents_observer_qt.h" #include "extensions/extensions_browser_client_qt.h" #include "net/plugin_response_interceptor_url_loader_throttle.h" @@ -340,7 +343,12 @@ std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertSt std::string ContentBrowserClientQt::GetApplicationLocale() { - return WebEngineLibraryInfo::getApplicationLocale(); + std::string bcp47Name = QLocale().bcp47Name().toStdString(); + if (m_cachedQtLocale != bcp47Name) { + m_cachedQtLocale = bcp47Name; + m_appLocale = WebEngineLibraryInfo::getApplicationLocale(); + } + return m_appLocale; } std::string ContentBrowserClientQt::GetAcceptLangs(content::BrowserContext *context) @@ -652,6 +660,8 @@ bool ContentBrowserClientQt::AllowAppCache(const GURL &manifest_url, content::BrowserContext *context) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return false; return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(first_party), toQt(manifest_url)); } @@ -678,6 +688,8 @@ ContentBrowserClientQt::AllowServiceWorkerOnUI(const GURL &scope, content::BrowserContext *context) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return content::AllowServiceWorkerResult::No(); // FIXME: Chrome also checks if javascript is enabled here to check if has been disabled since the service worker // was started. return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(site_for_cookies), toQt(scope)) @@ -692,6 +704,8 @@ void ContentBrowserClientQt::AllowWorkerFileSystem(const GURL &url, base::OnceCallback<void(bool)> callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return std::move(callback).Run(false); std::move(callback).Run( static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url))); } @@ -702,6 +716,8 @@ bool ContentBrowserClientQt::AllowWorkerIndexedDB(const GURL &url, const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return false; return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url)); } @@ -848,8 +864,11 @@ static bool navigationThrottleCallback(content::WebContents *source, return false; int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; - WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(source->GetDelegate()); - WebContentsAdapterClient *client = delegate->adapterClient(); + + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView())->client(); + if (!client) + return false; client->navigationRequested(pageTransitionToNavigationType(params.transition_type()), toQt(params.url()), navigationRequestAction, @@ -1137,6 +1156,33 @@ void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int #endif } +base::flat_set<std::string> ContentBrowserClientQt::GetPluginMimeTypesWithExternalHandlers( + content::BrowserContext *browser_context) +{ + base::flat_set<std::string> mime_types; +#if BUILDFLAG(ENABLE_EXTENSIONS) + ProfileQt *profile = static_cast<ProfileQt *>(browser_context); + for (const std::string &extension_id : MimeTypesHandler::GetMIMETypeAllowlist()) { + const extensions::Extension *extension = + extensions::ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(extension_id); + // The allowed extension may not be installed, so we have to nullptr + // check |extension|. + if (!extension || + (profile->IsOffTheRecord() && !extensions::util::IsIncognitoEnabled( + extension_id, browser_context))) { + continue; + } + if (MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension)) { + for (const auto &supported_mime_type : handler->mime_type_set()) + mime_types.insert(supported_mime_type); + } + } +#endif + return mime_types; +} + bool ContentBrowserClientQt::WillCreateURLLoaderFactory( content::BrowserContext *browser_context, content::RenderFrameHost *frame, @@ -1202,4 +1248,13 @@ content::WebContentsViewDelegate *ContentBrowserClientQt::GetWebContentsViewDele return nullptr; } +content::ContentBrowserClient::AllowWebBluetoothResult +ContentBrowserClientQt::AllowWebBluetooth(content::BrowserContext *browser_context, + const url::Origin &requesting_origin, + const url::Origin &embedding_origin) +{ + DCHECK(browser_context); + return content::ContentBrowserClient::AllowWebBluetoothResult::BLOCK_GLOBALLY_DISABLED; +} + } // namespace QtWebEngineCore diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 75007989d..8b891131f 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -166,6 +166,9 @@ public: bool AllowWorkerIndexedDB(const GURL &url, content::BrowserContext *context, const std::vector<content::GlobalFrameRoutingId> &render_frames) override; + AllowWebBluetoothResult AllowWebBluetooth(content::BrowserContext *browser_context, + const url::Origin &requesting_origin, + const url::Origin &embedding_origin) override; #if QT_CONFIG(webengine_geolocation) std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override; @@ -255,6 +258,7 @@ public: NonNetworkURLLoaderFactoryMap* factories) override; void SiteInstanceGotProcess(content::SiteInstance *site_instance) override; void SiteInstanceDeleting(content::SiteInstance *site_instance) override; + base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(content::BrowserContext *browser_context) override; content::WebContentsViewDelegate* GetWebContentsViewDelegate(content::WebContents* web_contents) override; @@ -265,6 +269,8 @@ public: private: scoped_refptr<ShareGroupQt> m_shareGroupQt; + std::string m_appLocale; + std::string m_cachedQtLocale; }; } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 83c367de0..560cdbf54 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -86,7 +86,7 @@ const char kWidevineCdmFileName[] = #include "pdf/pdf.h" #include "pdf/pdf_ppapi.h" const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf"; -const char kPdfPluginPath[] = "internal-pdf-viewer/"; +const char kPdfPluginPath[] = "internal-pdf-viewer"; const char kPdfPluginSrc[] = "src"; #endif // QT_CONFIG(webengine_printing_and_pdf) diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index c22d5901f..a42ee4aff 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -331,6 +331,7 @@ qtConfig(webengine-extensions) { extensions/extensions_browser_client_qt.cpp \ extensions/messaging_delegate_qt.cpp \ extensions/mime_handler_view_guest_delegate_qt.cpp \ + extensions/plugin_service_filter_qt.cpp \ net/plugin_response_interceptor_url_loader_throttle.cpp \ renderer/extensions/extensions_dispatcher_delegate_qt.cpp \ renderer/extensions/extensions_renderer_client_qt.cpp \ @@ -349,6 +350,7 @@ qtConfig(webengine-extensions) { extensions/extensions_browser_client_qt.h \ extensions/messaging_delegate_qt.h \ extensions/mime_handler_view_guest_delegate_qt.h \ + extensions/plugin_service_filter_qt.h \ net/plugin_response_interceptor_url_loader_throttle.h \ renderer/extensions/extensions_dispatcher_delegate_qt.h \ renderer/extensions/extensions_renderer_client_qt.h \ diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 1f715444b..fd7a2c54f 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -41,15 +41,96 @@ #include "ui/display/display.h" +#include "type_conversion.h" + +#include <QGuiApplication> +#include <QScreen> + +#include <cmath> + namespace QtWebEngineCore { +static display::Display::Rotation toDisplayRotation(Qt::ScreenOrientation orientation) +{ + switch (orientation) { + case Qt::PrimaryOrientation: + case Qt::LandscapeOrientation: + return display::Display::ROTATE_0; + case Qt::PortraitOrientation: + return display::Display::ROTATE_90; + case Qt::InvertedLandscapeOrientation: + return display::Display::ROTATE_180; + case Qt::InvertedPortraitOrientation: + return display::Display::ROTATE_270; + } +} + +display::Display toDisplayDisplay(int id, const QScreen *screen) +{ + auto display = display::Display(id, toGfx(screen->geometry())); + display.set_work_area(toGfx(screen->availableGeometry())); + display.set_device_scale_factor(screen->devicePixelRatio()); + display.set_is_monochrome(screen->depth() == 1); + display.set_color_depth(screen->depth()); + display.set_depth_per_component(8); // FIXME: find the real value + display.set_display_frequency(std::ceil(screen->refreshRate())); + display.set_rotation(toDisplayRotation(screen->orientation())); + if (screen->nativeOrientation() != Qt::PrimaryOrientation) + display.set_panel_rotation(toDisplayRotation(screen->nativeOrientation())); + return display; +} + DesktopScreenQt::DesktopScreenQt() { - ProcessDisplayChanged(display::Display::GetDefaultDisplay(), true /* is_primary */); + initializeScreens(); } DesktopScreenQt::~DesktopScreenQt() -{} +{ + for (auto conn : qAsConst(m_connections)) + QObject::disconnect(conn); +} + +void DesktopScreenQt::initializeScreens() +{ + if (updateAllScreens()) { + m_connections[0] = + QObject::connect(qApp, &QGuiApplication::primaryScreenChanged, [this] (QScreen *screen) { + ProcessDisplayChanged(toDisplayDisplay(0, screen), true /* is_primary */); + }); + // no guarantees how these will affect ids: + m_connections[1] = + QObject::connect(qApp, &QGuiApplication::screenAdded, [this] (QScreen *) { + updateAllScreens(); + }); + m_connections[2] = + QObject::connect(qApp, &QGuiApplication::screenRemoved, [this] (QScreen *) { + updateAllScreens(); + }); + } else { + // Running headless + ProcessDisplayChanged(display::Display::GetDefaultDisplay(), true /* is_primary */); + m_connections[0] = + QObject::connect(qApp, &QGuiApplication::screenAdded, [this] (QScreen *) { + display_list().RemoveDisplay(display::kDefaultDisplayId); + QObject::disconnect(m_connections[0]); + initializeScreens(); + }); + } +} + +bool DesktopScreenQt::updateAllScreens() +{ + Q_ASSERT(qApp->primaryScreen() == qApp->screens().first()); + const auto screens = qApp->screens(); + const int oldLen = GetNumDisplays(); + for (int i = screens.length(); i < oldLen; ++i) + display_list().RemoveDisplay(i); + for (int i = 0; i < screens.length(); ++i) + ProcessDisplayChanged(toDisplayDisplay(i, screens.at(i)), i == 0 /* is_primary */); + + return screens.length() > 0; +} display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeWindow /*window*/) const { diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h index f47cfabbc..1b2e095a4 100644 --- a/src/core/desktop_screen_qt.h +++ b/src/core/desktop_screen_qt.h @@ -42,6 +42,8 @@ #include "ui/display/screen_base.h" +#include <qmetaobject.h> + namespace QtWebEngineCore { class DesktopScreenQt : public display::ScreenBase @@ -51,6 +53,11 @@ public: ~DesktopScreenQt() override; display::Display GetDisplayNearestWindow(gfx::NativeWindow /*window*/) const override; + +private: + void initializeScreens(); + bool updateAllScreens(); + QMetaObject::Connection m_connections[3]; }; } // namespace QtWebEngineCore diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp index 71d51190a..553757fbb 100644 --- a/src/core/devtools_frontend_qt.cpp +++ b/src/core/devtools_frontend_qt.cpp @@ -59,6 +59,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/values.h" +#include "chrome/browser/devtools/devtools_eye_dropper.h" #include "chrome/common/url_constants.h" #include "components/prefs/in_memory_pref_store.h" #include "components/prefs/json_pref_store.h" @@ -531,6 +532,11 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me Activate(); } else if (method == "closeWindow") { web_contents()->Close(); + } else if (method == "setEyeDropperActive" && params->GetSize() == 1) { + bool active; + if (!params->GetBoolean(0, &active)) + return; + SetEyeDropperActive(active); } else { VLOG(1) << "Unimplemented devtools method: " << message; return; @@ -540,6 +546,30 @@ void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &me SendMessageAck(request_id, nullptr); } +void DevToolsFrontendQt::SetEyeDropperActive(bool active) +{ + if (!m_inspectedContents) + return; + if (active) { + m_eyeDropper.reset(new DevToolsEyeDropper( + m_inspectedContents, + base::Bind(&DevToolsFrontendQt::ColorPickedInEyeDropper, + base::Unretained(this)))); + } else { + m_eyeDropper.reset(); + } +} + +void DevToolsFrontendQt::ColorPickedInEyeDropper(int r, int g, int b, int a) +{ + base::DictionaryValue color; + color.SetInteger("r", r); + color.SetInteger("g", g); + color.SetInteger("b", b); + color.SetInteger("a", a); + CallClientFunction("DevToolsAPI.eyeDropperPickedColor", &color, nullptr, nullptr); +} + void DevToolsFrontendQt::DispatchProtocolMessage(content::DevToolsAgentHost *agentHost, base::span<const uint8_t> message) { Q_UNUSED(agentHost); diff --git a/src/core/devtools_frontend_qt.h b/src/core/devtools_frontend_qt.h index 423131c4e..aac5909dc 100644 --- a/src/core/devtools_frontend_qt.h +++ b/src/core/devtools_frontend_qt.h @@ -65,6 +65,7 @@ class RenderViewHost; class WebContents; } // namespace content +class DevToolsEyeDropper; class PersistentPrefStore; namespace QtWebEngineCore { @@ -113,6 +114,8 @@ private: void RemovePreference(const std::string &name); void ClearPreferences(); void CreateJsonPreferences(bool clear); + void SetEyeDropperActive(bool active); + void ColorPickedInEyeDropper(int r, int g, int b, int a); // We shouldn't be keeping it alive QWeakPointer<WebContentsAdapter> m_frontendAdapter; @@ -123,6 +126,7 @@ private: int m_inspect_element_at_x; int m_inspect_element_at_y; std::unique_ptr<content::DevToolsFrontendHost> m_frontendHost; + std::unique_ptr<DevToolsEyeDropper> m_eyeDropper; class NetworkResourceLoader; std::set<std::unique_ptr<NetworkResourceLoader>, base::UniquePtrComparator> m_loaders; diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp index 9c080e9aa..285b27729 100644 --- a/src/core/extensions/extension_system_qt.cpp +++ b/src/core/extensions/extension_system_qt.cpp @@ -223,11 +223,12 @@ void ExtensionSystemQt::NotifyExtensionLoaded(const Extension *extension) // Register plugins included with the extension. // Implementation based on PluginManager::OnExtensionLoaded. const MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension); - if (handler && !handler->handler_url().empty()) { + if (handler && handler->HasPlugin()) { content::WebPluginInfo info; info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN; info.name = base::UTF8ToUTF16(extension->name()); - info.path = base::FilePath::FromUTF8Unsafe(extension->url().spec()); + info.path = handler->GetPluginPath(); + info.background_color = handler->GetBackgroundColor(); for (std::set<std::string>::const_iterator mime_type = handler->mime_type_set().begin(); mime_type != handler->mime_type_set().end(); ++mime_type) { content::WebPluginMimeType mime_type_info; diff --git a/src/core/extensions/extension_web_contents_observer_qt.cpp b/src/core/extensions/extension_web_contents_observer_qt.cpp index 5b1514bb4..e336f70b4 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.cpp +++ b/src/core/extensions/extension_web_contents_observer_qt.cpp @@ -43,13 +43,17 @@ #include "extension_web_contents_observer_qt.h" +#include "components/guest_view/browser/guest_view_base.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/common/url_constants.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/manifest.h" +#include "render_widget_host_view_qt.h" + namespace extensions { ExtensionWebContentsObserverQt::ExtensionWebContentsObserverQt(content::WebContents *web_contents) @@ -85,6 +89,16 @@ void ExtensionWebContentsObserverQt::RenderFrameCreated(content::RenderFrameHost policy->GrantRequestOrigin(process_id, url::Origin::Create(GURL(content::kChromeUIResourcesURL))); } +void ExtensionWebContentsObserverQt::RenderViewCreated(content::RenderViewHost *render_view_host) +{ + if (web_contents()->IsInnerWebContentsForGuest()) { + content::RenderWidgetHost *render_widget_host = render_view_host->GetWidget(); + content::WebContents *parent_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(web_contents()); + QtWebEngineCore::RenderWidgetHostViewQt *parent_rwhv = static_cast<QtWebEngineCore::RenderWidgetHostViewQt *>(parent_web_contents->GetRenderWidgetHostView()); + parent_rwhv->setGuest(static_cast<content::RenderWidgetHostImpl *>(render_widget_host)); + } +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(ExtensionWebContentsObserverQt) } // namespace extensions diff --git a/src/core/extensions/extension_web_contents_observer_qt.h b/src/core/extensions/extension_web_contents_observer_qt.h index 658966b31..c0269e4f5 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.h +++ b/src/core/extensions/extension_web_contents_observer_qt.h @@ -61,6 +61,7 @@ public: // content::WebContentsObserver overrides. void RenderFrameCreated(content::RenderFrameHost *render_frame_host) override; + void RenderViewCreated(content::RenderViewHost *render_view_host) override; private: friend class content::WebContentsUserData<ExtensionWebContentsObserverQt>; diff --git a/src/core/extensions/extensions_api_client_qt.cpp b/src/core/extensions/extensions_api_client_qt.cpp index 81d9efde2..925fd10da 100644 --- a/src/core/extensions/extensions_api_client_qt.cpp +++ b/src/core/extensions/extensions_api_client_qt.cpp @@ -47,9 +47,10 @@ #include <memory> #include "components/pdf/browser/pdf_web_contents_helper.h" +#include "extension_web_contents_observer_qt.h" #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h" -#include "extension_web_contents_observer_qt.h" +#include "mime_handler_view_guest_delegate_qt.h" #include "printing/print_view_manager_qt.h" namespace extensions { @@ -67,12 +68,12 @@ AppViewGuestDelegate *ExtensionsAPIClientQt::CreateAppViewGuestDelegate() const std::unique_ptr<guest_view::GuestViewManagerDelegate> ExtensionsAPIClientQt::CreateGuestViewManagerDelegate(content::BrowserContext *context) const { - return std::make_unique<guest_view::GuestViewManagerDelegate>(); + return std::make_unique<extensions::ExtensionsGuestViewManagerDelegate>(context); } std::unique_ptr<MimeHandlerViewGuestDelegate> ExtensionsAPIClientQt::CreateMimeHandlerViewGuestDelegate(MimeHandlerViewGuest *guest) const { - return std::make_unique<MimeHandlerViewGuestDelegate>(); + return std::make_unique<MimeHandlerViewGuestDelegateQt>(guest); } void ExtensionsAPIClientQt::AttachWebContentsHelpers(content::WebContents *web_contents) const diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp index 6bcf37d85..501252823 100644 --- a/src/core/extensions/extensions_browser_client_qt.cpp +++ b/src/core/extensions/extensions_browser_client_qt.cpp @@ -335,7 +335,7 @@ BrowserContext *ExtensionsBrowserClientQt::GetOriginalContext(BrowserContext *co bool ExtensionsBrowserClientQt::IsGuestSession(BrowserContext *context) const { - return false; + return context->IsOffTheRecord(); } bool ExtensionsBrowserClientQt::IsExtensionIncognitoEnabled(const std::string &extension_id, diff --git a/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp b/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp index 58f4f209a..16a747929 100644 --- a/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp +++ b/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp @@ -44,33 +44,44 @@ #include "mime_handler_view_guest_delegate_qt.h" -#include "content/browser/browser_plugin/browser_plugin_guest.h" -#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/context_menu_params.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "profile_adapter.h" +#include "qwebenginecontextmenurequest.h" +#include "qwebenginecontextmenurequest_p.h" +#include "render_widget_host_view_qt.h" +#include "touch_selection_controller_client_qt.h" +#include "web_contents_adapter.h" +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" + namespace extensions { MimeHandlerViewGuestDelegateQt::MimeHandlerViewGuestDelegateQt(MimeHandlerViewGuest *) : MimeHandlerViewGuestDelegate() + , m_contextMenuRequest(new QWebEngineContextMenuRequest(new QWebEngineContextMenuRequestPrivate)) { } MimeHandlerViewGuestDelegateQt::~MimeHandlerViewGuestDelegateQt() { + delete m_contextMenuRequest; } bool MimeHandlerViewGuestDelegateQt::HandleContextMenu(content::WebContents *web_contents, const content::ContextMenuParams ¶ms) { - content::ContextMenuParams new_params = params; - - gfx::Point guest_coordinates = - static_cast<content::WebContentsImpl *>(web_contents)->GetBrowserPluginGuest()->GetScreenCoordinates(gfx::Point()); + content::WebContents *parent_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(web_contents); + if (auto rwhv = static_cast<QtWebEngineCore::RenderWidgetHostViewQt *>(parent_web_contents->GetRenderWidgetHostView())) { + if (rwhv->getTouchSelectionControllerClient()->handleContextMenu(params)) + return true; - // Adjust (x,y) position for offset from guest to embedder. - new_params.x += guest_coordinates.x(); - new_params.y += guest_coordinates.y(); + QtWebEngineCore::WebContentsAdapterClient *adapterClient = rwhv->adapterClient(); + QtWebEngineCore::WebContentsViewQt::update(m_contextMenuRequest, params, adapterClient->profileAdapter()->isSpellCheckEnabled()); + adapterClient->contextMenuRequested(m_contextMenuRequest); + return true; + } return false; } diff --git a/src/core/extensions/mime_handler_view_guest_delegate_qt.h b/src/core/extensions/mime_handler_view_guest_delegate_qt.h index 6cd80689c..c9b822aa1 100644 --- a/src/core/extensions/mime_handler_view_guest_delegate_qt.h +++ b/src/core/extensions/mime_handler_view_guest_delegate_qt.h @@ -46,8 +46,11 @@ #define MIME_HANDLER_VIEW_GUEST_DELEGATE_QT_H_ #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h" -#include "content/browser/web_contents/web_contents_view.h" -#include "content/public/browser/web_contents.h" +#include "api/qtwebenginecoreglobal_p.h" + +QT_BEGIN_NAMESPACE +class QWebEngineContextMenuRequest; +QT_END_NAMESPACE namespace content { struct ContextMenuParams; @@ -66,6 +69,7 @@ public: const content::ContextMenuParams ¶ms) override; private: + QWebEngineContextMenuRequest *m_contextMenuRequest; DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewGuestDelegateQt); }; diff --git a/src/core/extensions/plugin_service_filter_qt.cpp b/src/core/extensions/plugin_service_filter_qt.cpp new file mode 100644 index 000000000..94cf5cb27 --- /dev/null +++ b/src/core/extensions/plugin_service_filter_qt.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "extensions/plugin_service_filter_qt.h" + +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" + +#include "web_contents_delegate_qt.h" + +using namespace QtWebEngineCore; + +namespace extensions { + +// static +PluginServiceFilterQt *PluginServiceFilterQt::GetInstance() { + return base::Singleton<PluginServiceFilterQt>::get(); +} + +bool PluginServiceFilterQt::IsPluginAvailable(int render_process_id, + int render_frame_id, + const GURL &url, + const url::Origin &main_frame_origin, + content::WebPluginInfo *plugin) +{ + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) { + // Availability checked somewhere before/during WebContents initialization. Let it load and enable + // all the plugins at this phase. This information will be queried again when receiving the response + // for the requested content. Postponing our decision and enabling/blocking there makes WebEngineSettings + // modifiable in runtime without reconstructing WebContents. + return true; + } + + if (web_contents->IsInnerWebContentsForGuest()) + web_contents = web_contents->GetOuterWebContents(); + + if (auto *delegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())) { + const WebEngineSettings *settings = delegate->webEngineSettings(); + if (!settings->testAttribute(QWebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(QWebEngineSettings::PluginsEnabled)) + return false; + } + + return true; +} + +bool PluginServiceFilterQt::CanLoadPlugin(int render_process_id, + const base::FilePath &path) +{ + return true; +} + +PluginServiceFilterQt::PluginServiceFilterQt() +{ +} + +PluginServiceFilterQt::~PluginServiceFilterQt() +{ +} + +} // namespace extensions diff --git a/src/core/extensions/plugin_service_filter_qt.h b/src/core/extensions/plugin_service_filter_qt.h new file mode 100644 index 000000000..ea5f082f2 --- /dev/null +++ b/src/core/extensions/plugin_service_filter_qt.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLUGIN_SERVICE_FILTER_QT +#define PLUGIN_SERVICE_FILTER_QT + +#include "content/public/browser/plugin_service_filter.h" + +#include "base/memory/singleton.h" + +namespace extensions { + +class PluginServiceFilterQt : public content::PluginServiceFilter { +public: + static PluginServiceFilterQt* GetInstance(); + + bool IsPluginAvailable(int render_process_id, + int render_frame_id, + const GURL &url, + const url::Origin &main_frame_origin, + content::WebPluginInfo *plugin) override; + + bool CanLoadPlugin(int render_process_id, + const base::FilePath &path) override; + +private: + friend struct base::DefaultSingletonTraits<PluginServiceFilterQt>; + + PluginServiceFilterQt(); + ~PluginServiceFilterQt(); +}; + +} // namespace extensions + +#endif // PLUGIN_SERVICE_FILTER_QT diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp index 334b147a5..bca059ae6 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -40,59 +40,27 @@ #include "plugin_response_interceptor_url_loader_throttle.h" #include "base/bind.h" +#include "base/guid.h" #include "base/task/post_task.h" +#include "chrome/browser/extensions/api/streams_private/streams_private_api.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/download_request_utils.h" #include "content/public/browser/download_utils.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" +#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" +#include "extensions/extension_system_qt.h" #include "web_contents_delegate_qt.h" #include <string> namespace QtWebEngineCore { -void onPdfStreamIntercepted(const GURL &original_url, std::string extension_id, int frame_tree_node_id) -{ - content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); - if (!web_contents) - return; - - WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); - if (!contentsDelegate) - return; - - WebEngineSettings *settings = contentsDelegate->webEngineSettings(); - if (!settings->testAttribute(QWebEngineSettings::PdfViewerEnabled) - || !settings->testAttribute(QWebEngineSettings::PluginsEnabled)) { - // If the applications has been set up to always download PDF files to open them in an - // external viewer, trigger the download. - std::unique_ptr<download::DownloadUrlParameters> params( - content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(web_contents, original_url, - MISSING_TRAFFIC_ANNOTATION)); - content::BrowserContext::GetDownloadManager(web_contents->GetBrowserContext())->DownloadUrl(std::move(params)); - return; - } - - // The URL passes the original pdf resource url, that will be requested - // by the pdf viewer extension page. - content::NavigationController::LoadURLParams params( - GURL(base::StringPrintf("%s://%s/index.html?%s", extensions::kExtensionScheme, - extension_id.c_str(), original_url.spec().c_str()))); - - params.frame_tree_node_id = frame_tree_node_id; - web_contents->GetController().LoadURLWithParams(params); -} - - -PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( - content::ResourceContext *resource_context, int resource_type, int frame_tree_node_id) - : m_resource_context(resource_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) -{} - PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id) : m_browser_context(browser_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) @@ -102,31 +70,111 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL network::mojom::URLResponseHead *response_head, bool *defer) { - Q_UNUSED(defer); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (content::download_utils::MustDownload(response_url, response_head->headers.get(), response_head->mime_type)) return; - if (m_resource_context) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - } else { - DCHECK(m_browser_context); - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - } + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(m_frame_tree_node_id); + if (!web_contents) + return; std::string extension_id; - // FIXME: We should use extensions::InfoMap in the future: if (response_head->mime_type == "application/pdf") extension_id = extension_misc::kPdfExtensionId; if (extension_id.empty()) return; - *defer = true; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); + if (!contentsDelegate) + return; + + WebEngineSettings *settings = contentsDelegate->webEngineSettings(); + if (!settings->testAttribute(QWebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(QWebEngineSettings::PluginsEnabled)) { + // PluginServiceFilterQt will inform the URLLoader about the disabled state of plugins + // and we can expect the download to be triggered automatically. It's unnecessary to + // go further and start the guest view embedding process. + return; + } + + // Chrome's PDF Extension does not work properly in the face of a restrictive + // Content-Security-Policy, and does not currently respect the policy anyway. + // Ignore CSP served on a PDF response. https://crbug.com/271452 + if (extension_id == extension_misc::kPdfExtensionId && response_head->headers) + response_head->headers->RemoveHeader("Content-Security-Policy"); + + MimeTypesHandler::ReportUsedHandler(extension_id); + + std::string view_id = base::GenerateGUID(); + // The string passed down to the original client with the response body. + std::string payload = view_id; + + mojo::PendingRemote<network::mojom::URLLoader> dummy_new_loader; + ignore_result(dummy_new_loader.InitWithNewPipeAndPassReceiver()); + mojo::Remote<network::mojom::URLLoaderClient> new_client; + mojo::PendingReceiver<network::mojom::URLLoaderClient> new_client_receiver = + new_client.BindNewPipeAndPassReceiver(); + + + uint32_t data_pipe_size = 64U; + // Provide the MimeHandlerView code a chance to override the payload. This is + // the case where the resource is handled by frame-based MimeHandlerView. + *defer = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, view_id, + &payload, &data_pipe_size, + base::BindOnce( + &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, + weak_factory_.GetWeakPtr())); + + mojo::DataPipe data_pipe(data_pipe_size); + uint32_t len = static_cast<uint32_t>(payload.size()); + CHECK_EQ(MOJO_RESULT_OK, + data_pipe.producer_handle->WriteData( + payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + + + new_client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle)); + + network::URLLoaderCompletionStatus status(net::OK); + status.decoded_body_length = len; + new_client->OnComplete(status); + + mojo::PendingRemote<network::mojom::URLLoader> original_loader; + mojo::PendingReceiver<network::mojom::URLLoaderClient> original_client; + delegate_->InterceptResponse(std::move(dummy_new_loader), + std::move(new_client_receiver), &original_loader, + &original_client); + + // Make a deep copy of URLResponseHead before passing it cross-thread. + auto deep_copied_response = response_head->Clone(); + if (response_head->headers) { + deep_copied_response->headers = + base::MakeRefCounted<net::HttpResponseHeaders>( + response_head->headers->raw_headers()); + } + + auto transferrable_loader = blink::mojom::TransferrableURLLoader::New(); + transferrable_loader->url = GURL( + extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() + + base::GenerateGUID()); + transferrable_loader->url_loader = std::move(original_loader); + transferrable_loader->url_loader_client = std::move(original_client); + transferrable_loader->head = std::move(deep_copied_response); + transferrable_loader->head->intercepted_by_plugin = true; + + bool embedded = m_resource_type != + static_cast<int>(blink::mojom::ResourceType::kMainFrame); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, + extension_id, view_id, embedded, m_frame_tree_node_id, + -1 /* render_process_id */, -1 /* render_frame_id */, + std::move(transferrable_loader), response_url)); +} - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&onPdfStreamIntercepted, - response_url, - extension_id, - m_frame_tree_node_id)); +void PluginResponseInterceptorURLLoaderThrottle::ResumeLoad() { + delegate_->Resume(); } } // namespace QtWebEngineCore diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index 7b9db6490..205ab25e6 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -41,11 +41,11 @@ #define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" namespace content { class BrowserContext; -class ResourceContext; } namespace QtWebEngineCore { @@ -53,8 +53,6 @@ namespace QtWebEngineCore { class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle { public: - PluginResponseInterceptorURLLoaderThrottle(content::ResourceContext *resource_context, - int resource_type, int frame_tree_node_id); PluginResponseInterceptorURLLoaderThrottle(content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id); ~PluginResponseInterceptorURLLoaderThrottle() override = default; @@ -63,11 +61,17 @@ private: // content::URLLoaderThrottle overrides; void WillProcessResponse(const GURL &response_url, network::mojom::URLResponseHead *response_head, bool *defer) override; - content::ResourceContext *m_resource_context = nullptr; + // Resumes loading for an intercepted response. This would give the extension + // layer chance to initialize its browser side state. + void ResumeLoad(); + content::BrowserContext *m_browser_context = nullptr; const int m_resource_type; const int m_frame_tree_node_id; + base::WeakPtrFactory<PluginResponseInterceptorURLLoaderThrottle> + weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 577d0f6c8..de28aee6c 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -121,6 +121,7 @@ ProfileAdapter::ProfileAdapter(const QString &storageName): ProfileAdapter::~ProfileAdapter() { + content::BrowserContext::NotifyWillBeDestroyed(m_profile.data()); while (!m_webContentsAdapterClients.isEmpty()) { m_webContentsAdapterClients.first()->releaseProfile(); } @@ -131,7 +132,9 @@ ProfileAdapter::~ProfileAdapter() } #if QT_CONFIG(ssl) delete m_clientCertificateStore; + m_clientCertificateStore = nullptr; #endif + WebEngineContext::flushMessages(); } void ProfileAdapter::setStorageName(const QString &storageName) diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index 748104312..36303605f 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -111,7 +111,6 @@ ProfileQt::~ProfileQt() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); m_prefServiceAdapter.commit(); - content::BrowserContext::NotifyWillBeDestroyed(this); BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(this); ShutdownStoragePartitions(); m_profileIOData->shutdownOnUIThread(); diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni index 73ec8bda9..8eee4ada0 100644 --- a/src/core/qtwebengine_resources.gni +++ b/src/core/qtwebengine_resources.gni @@ -138,10 +138,12 @@ repack("qtwebengine_repack_resources_200") { repack("qtwebengine_repack_resources_devtools") { sources = [ "$root_gen_dir/content/browser/devtools/devtools_resources.pak", + "$root_gen_dir/third_party/blink/public/resources/inspector_overlay_resources.pak", ] output = "$root_out_dir/qtwebengine_devtools_resources.pak" deps = [ "//content/browser/devtools:devtools_resources_grit", + "//third_party/blink/public:devtools_inspector_resources", ] } diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index 0f3e8b946..b14fc1049 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -75,6 +75,8 @@ source_set("qtwebengine_sources") { "//chrome/browser/custom_handlers/protocol_handler_registry.h", "//chrome/browser/custom_handlers/protocol_handler_registry_factory.cc", "//chrome/browser/custom_handlers/protocol_handler_registry_factory.h", + "//chrome/browser/devtools/devtools_eye_dropper.cc", + "//chrome/browser/devtools/devtools_eye_dropper.h", "//chrome/browser/media/webrtc/desktop_media_list.h", "//chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc", "//chrome/browser/net/chrome_mojo_proxy_resolver_factory.h", @@ -208,7 +210,10 @@ source_set("qtwebengine_sources") { "//components/pdf/browser:browser", "//components/pdf/renderer:renderer", "//components/printing/browser", - "//components/printing/renderer", + "//components/printing/renderer" + ] + sources += [ + "//chrome/browser/extensions/api/streams_private/streams_private_api.cc", ] } diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 43ee36ed2..14622142c 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -57,8 +57,10 @@ #include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/image_transport_factory.h" +#include "content/browser/renderer_host/display_util.h" #include "content/browser/renderer_host/frame_tree.h" #include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" @@ -70,6 +72,7 @@ #include "content/common/input_messages.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/cursor/cursor.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_configuration.h" @@ -83,7 +86,10 @@ #if defined(USE_AURA) #include "ui/base/cursor/cursor_size.h" #include "ui/base/cursor/cursors_aura.h" -#include "ui/base/resource/resource_bundle.h" +#endif + +#if defined(Q_OS_MACOS) +#include "content/app/resources/grit/content_resources.h" #endif #include <QGuiApplication> @@ -122,6 +128,20 @@ static inline ui::GestureProvider::Config QtGestureProviderConfig() { return config; } +extern display::Display toDisplayDisplay(int id, const QScreen *screen); + +static blink::ScreenInfo screenInfoFromQScreen(QScreen *screen) +{ + blink::ScreenInfo r; + if (!screen) + screen = qApp->primaryScreen(); + if (screen) + content::DisplayUtil::DisplayToScreenInfo(&r, toDisplayDisplay(0, screen)); + else + r.device_scale_factor = qGuiApp->devicePixelRatio(); + return r; +} + // An minimal override to support progressing flings class FlingingCompositor : public ui::Compositor { @@ -149,10 +169,33 @@ public: } }; +class GuestInputEventObserverQt : public content::RenderWidgetHost::InputEventObserver +{ +public: + GuestInputEventObserverQt(RenderWidgetHostViewQt *rwhv) + : m_rwhv(rwhv) + { + } + ~GuestInputEventObserverQt() {} + + void OnInputEvent(const blink::WebInputEvent&) override {} + void OnInputEventAck(blink::mojom::InputEventResultSource, + blink::mojom::InputEventResultState state, + const blink::WebInputEvent &event) override + { + if (event.GetType() == blink::WebInputEvent::Type::kMouseWheel) + m_rwhv->WheelEventAck(static_cast<const blink::WebMouseWheelEvent &>(event), state); + } + +private: + RenderWidgetHostViewQt *m_rwhv; +}; + RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) , m_taskRunner(base::ThreadTaskRunnerHandle::Get()) , m_gestureProvider(QtGestureProviderConfig(), this) + , m_guestInputEventObserver(new GuestInputEventObserverQt(this)) , m_frameSinkId(host()->GetFrameSinkId()) , m_delegateClient(new RenderWidgetHostViewQtDelegateClient(this)) { @@ -181,6 +224,8 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); + m_cursorManager.reset(new content::CursorManager(this)); + m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this)); ui::TouchSelectionController::Config config; config.max_tap_duration = base::TimeDelta::FromMilliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); @@ -207,6 +252,7 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() m_touchSelectionControllerClient.reset(); host()->render_frame_metadata_provider()->RemoveObserver(this); + host()->ViewDestroyed(); } void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) @@ -230,6 +276,11 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC m_adapterClient = nullptr; }); } +void RenderWidgetHostViewQt::setGuest(content::RenderWidgetHostImpl *rwh) +{ + rwh->AddInputEventObserver(m_guestInputEventObserver.get()); +} + void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) { } @@ -305,6 +356,11 @@ bool RenderWidgetHostViewQt::IsMouseLocked() return m_isMouseLocked; } +viz::FrameSinkId RenderWidgetHostViewQt::GetRootFrameSinkId() +{ + return m_uiCompositor->frame_sink_id(); +} + bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { return m_delegatedFrameHost->CanCopyFromCompositingSurface(); @@ -388,6 +444,74 @@ void RenderWidgetHostViewQt::UnlockMouse() host()->LostMouseLock(); } +bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type) +{ + int resourceId; + // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. + qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f; + qreal hotX; + qreal hotY; + +#if defined(USE_AURA) + gfx::Point hotspot; + if (!ui::GetCursorDataFor(ui::CursorSize::kNormal, type, hotspotDpr, &resourceId, &hotspot)) + return false; + hotX = hotspot.x(); + hotY = hotspot.y(); +#elif defined(Q_OS_MACOS) + // See chromium/content/common/cursors/webcursor_mac.mm + switch (type) { + case ui::mojom::CursorType::kVerticalText: + // TODO: [NSCursor IBeamCursorForVerticalLayout] + return false; + case ui::mojom::CursorType::kCell: + resourceId = IDR_CELL_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kContextMenu: + // TODO: [NSCursor contextualMenuCursor] + return false; + case ui::mojom::CursorType::kZoomIn: + resourceId = IDR_ZOOMIN_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kZoomOut: + resourceId = IDR_ZOOMOUT_CURSOR; + hotX = 7; + hotY = 7; + break; + default: + Q_UNREACHABLE(); + return false; + } +#else + Q_UNREACHABLE(); + return false; +#endif + + const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId); + if (!imageSkia) + return false; + + QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor)); + + // Convert hotspot coordinates into device-independent pixels. + hotX /= hotspotDpr; + hotY /= hotspotDpr; + +#if defined(Q_OS_LINUX) + // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. + qreal imageDpr = imageQt.devicePixelRatio(); + hotX *= imageDpr; + hotY *= imageDpr; +#endif + + m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); + return true; +} + void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) { DisplayCursor(webCursor); @@ -397,9 +521,6 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) { const ui::Cursor &cursorInfo = webCursor.cursor(); Qt::CursorShape shape = Qt::ArrowCursor; -#if defined(USE_AURA) - ui::mojom::CursorType auraType = ui::mojom::CursorType::kNull; -#endif switch (cursorInfo.type()) { case ui::mojom::CursorType::kNull: case ui::mojom::CursorType::kPointer: @@ -475,31 +596,14 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) case ui::mojom::CursorType::kAlias: shape = Qt::DragLinkCursor; break; -#if defined(USE_AURA) - case ui::mojom::CursorType::kVerticalText: - auraType = ui::mojom::CursorType::kVerticalText; - break; - case ui::mojom::CursorType::kCell: - auraType = ui::mojom::CursorType::kCell; - break; - case ui::mojom::CursorType::kContextMenu: - auraType = ui::mojom::CursorType::kContextMenu; - break; - case ui::mojom::CursorType::kZoomIn: - auraType = ui::mojom::CursorType::kZoomIn; - break; - case ui::mojom::CursorType::kZoomOut: - auraType = ui::mojom::CursorType::kZoomOut; - break; -#else case ui::mojom::CursorType::kVerticalText: case ui::mojom::CursorType::kCell: case ui::mojom::CursorType::kContextMenu: case ui::mojom::CursorType::kZoomIn: case ui::mojom::CursorType::kZoomOut: - // FIXME: Support on OS X + if (updateCursorFromResource(cursorInfo.type())) + return; break; -#endif case ui::mojom::CursorType::kNoDrop: case ui::mojom::CursorType::kNotAllowed: shape = Qt::ForbiddenCursor; @@ -521,36 +625,14 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) } break; } -#if defined(USE_AURA) - if (auraType != ui::mojom::CursorType::kNull) { - int resourceId; - gfx::Point hotspot; - // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. - qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f; - if (ui::GetCursorDataFor(ui::CursorSize::kNormal, auraType, hotspotDpr, &resourceId, &hotspot)) { - if (const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId)) { - QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor)); - - // Convert hotspot coordinates into device-independent pixels. - qreal hotX = hotspot.x() / hotspotDpr; - qreal hotY = hotspot.y() / hotspotDpr; - -#if defined(Q_OS_LINUX) - // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. - qreal imageDpr = imageQt.devicePixelRatio(); - hotX *= imageDpr; - hotY *= imageDpr; -#endif - - m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); - return; - } - } - } -#endif m_delegate->updateCursor(QCursor(shape)); } +content::CursorManager *RenderWidgetHostViewQt::GetCursorManager() +{ + return m_cursorManager.get(); +} + void RenderWidgetHostViewQt::SetIsLoading(bool) { // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. @@ -572,6 +654,18 @@ void RenderWidgetHostViewQt::RenderProcessGone() Destroy(); } +bool RenderWidgetHostViewQt::TransformPointToCoordSpaceForView(const gfx::PointF &point, + content::RenderWidgetHostViewBase *target_view, + gfx::PointF *transformed_point) +{ + if (target_view == this) { + *transformed_point = point; + return true; + } + + return target_view->TransformPointToLocalCoordSpace(point, GetCurrentSurfaceId(), transformed_point); +} + void RenderWidgetHostViewQt::Destroy() { delete this; @@ -584,7 +678,7 @@ void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_text) { - if (m_adapterClient) + if (host()->delegate() && m_adapterClient) m_adapterClient->setToolTip(toQt(tooltip_text)); } @@ -606,8 +700,8 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana const ui::mojom::TextInputState *state = text_input_manager_->GetTextInputState(); if (!state) { - m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); - m_delegate->setInputMethodHints(Qt::ImhNone); + // Do not reset input method state here because an editable node might be still focused and + // this would hide the virtual keyboard if a child of the focused node is removed. return; } @@ -714,7 +808,8 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) } } - host()->ForwardGestureEvent(event); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &event, ui::LatencyInfo()); } void RenderWidgetHostViewQt::DidStopFlinging() @@ -784,11 +879,11 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve auto result = m_gestureProvider.OnTouchEvent(motionEvent); if (!result.succeeded) return; - blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, result.moved_beyond_slop_region, false /*hovering, FIXME ?*/); - host()->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &touchEvent, CreateLatencyInfo(touchEvent)); } bool RenderWidgetHostViewQt::isPopup() const @@ -800,17 +895,7 @@ bool RenderWidgetHostViewQt::updateScreenInfo() { blink::ScreenInfo oldScreenInfo = m_screenInfo; QScreen *screen = m_delegate->window() ? m_delegate->window()->screen() : nullptr; - - if (screen) { - m_screenInfo.device_scale_factor = screen->devicePixelRatio(); - m_screenInfo.depth_per_component = 8; - m_screenInfo.depth = screen->depth(); - m_screenInfo.is_monochrome = (m_screenInfo.depth == 1); - m_screenInfo.rect = toGfx(screen->geometry()); - m_screenInfo.available_rect = toGfx(screen->availableGeometry()); - } else { - m_screenInfo.device_scale_factor = qGuiApp->devicePixelRatio(); - } + m_screenInfo = screenInfoFromQScreen(screen); return (m_screenInfo != oldScreenInfo); } @@ -821,8 +906,9 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *event) Q_ASSERT(m_pendingWheelEvents.isEmpty()); blink::WebMouseWheelEvent webEvent = WebEventFactory::toWebWheelEvent(event); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - GetMouseWheelPhaseHandler()->AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + GetMouseWheelPhaseHandler()->AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); return; } if (!m_pendingWheelEvents.isEmpty()) { @@ -842,8 +928,9 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even while (!m_pendingWheelEvents.isEmpty() && !m_wheelAckPending) { blink::WebMouseWheelEvent webEvent = m_pendingWheelEvents.takeFirst(); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); } } @@ -899,6 +986,15 @@ const viz::LocalSurfaceId &RenderWidgetHostViewQt::GetLocalSurfaceId() const return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId(); } +void RenderWidgetHostViewQt::FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) +{ + Q_UNUSED(node_bounds_in_screen); + if (!is_editable_node) { + m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); + m_delegate->setInputMethodHints(Qt::ImhNone); + } +} + void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index fed831551..e01d91c84 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -68,6 +68,7 @@ class TouchSelectionController; namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegateClient; +class GuestInputEventObserverQt; class TouchSelectionControllerClientQt; class WebContentsAdapterClient; @@ -87,6 +88,7 @@ public: WebContentsAdapterClient *adapterClient() { return m_adapterClient; } void setAdapterClient(WebContentsAdapterClient *adapterClient); RenderWidgetHostViewQtDelegateClient *delegateClient() const { return m_delegateClient.get(); } + void setGuest(content::RenderWidgetHostImpl *); void InitAsChild(gfx::NativeView) override; void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) override; @@ -98,6 +100,7 @@ public: void Focus() override; bool HasFocus() override; bool IsMouseLocked() override; + viz::FrameSinkId GetRootFrameSinkId() override; bool IsSurfaceAvailableForCopy() override; void CopyFromSurface(const gfx::Rect &src_rect, const gfx::Size &output_size, @@ -112,10 +115,14 @@ public: void UnlockMouse() override; void UpdateCursor(const content::WebCursor&) override; void DisplayCursor(const content::WebCursor&) override; + content::CursorManager *GetCursorManager() override; void SetIsLoading(bool) override; void ImeCancelComposition() override; void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) override; void RenderProcessGone() override; + bool TransformPointToCoordSpaceForView(const gfx::PointF &point, + content::RenderWidgetHostViewBase *target_view, + gfx::PointF *transformed_point) override; void Destroy() override; void SetTooltipText(const base::string16 &tooltip_text) override; void DisplayTooltipText(const base::string16& tooltip_text) override; @@ -127,13 +134,15 @@ public: viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override; void OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata); + // Overridden from RenderWidgetHostViewBase: void GetScreenInfo(blink::ScreenInfo *results) override; gfx::Rect GetBoundsInRootWindow() override; void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) override; viz::SurfaceId GetCurrentSurfaceId() const override; const viz::FrameSinkId &GetFrameSinkId() const override; - const viz::LocalSurfaceId &GetLocalSurfaceId() const; + const viz::LocalSurfaceId &GetLocalSurfaceId() const override; + void FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) override; void TakeFallbackContentFrom(content::RenderWidgetHostView *view) override; void EnsureSurfaceSynchronizedForWebTest() override; @@ -195,8 +204,15 @@ private: bool isPopup() const; + bool updateCursorFromResource(ui::mojom::CursorType type); + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + + std::unique_ptr<content::CursorManager> m_cursorManager; + ui::FilteredGestureProvider m_gestureProvider; + std::unique_ptr<GuestInputEventObserverQt> m_guestInputEventObserver; + viz::FrameSinkId m_frameSinkId; std::unique_ptr<RenderWidgetHostViewQtDelegateClient> m_delegateClient; std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index ef2d8ba25..305f4c1e9 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -47,6 +47,7 @@ #include "web_event_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "ui/touch_selection/touch_selection_controller.h" #include <QEvent> @@ -94,7 +95,7 @@ QList<TouchPoint> RenderWidgetHostViewQtDelegateClient::mapTouchPointIds(const Q [] (QSet<int> s, const TouchPoint &p) { s.insert(p.second.id()); return s; }).size()); for (auto &&point : qAsConst(input)) - if (point.state() == Qt::TouchPointReleased) + if (point.state() == QEventPoint::Released) m_touchIdMapping.remove(point.id()); return output; @@ -117,8 +118,8 @@ public: // index is only valid for ACTION_DOWN and ACTION_UP and should correspond to the point causing it // see blink_event_util.cc:ToWebTouchPointState for details Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1) - || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == Qt::TouchPointPressed) - || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == Qt::TouchPointReleased), + || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed) + || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released), "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state()))); } @@ -350,7 +351,10 @@ bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event) return false; #endif case QEvent::HoverLeave: - m_rwhv->host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); + if (m_rwhv->host()->delegate() && m_rwhv->host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(event); + m_rwhv->host()->delegate()->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo()); + } break; default: return false; @@ -476,7 +480,8 @@ void RenderWidgetHostViewQtDelegateClient::handlePointerEvent(T *event) #endif } - m_rwhv->host()->ForwardMouseEvent(webEvent); + if (m_rwhv->host()->delegate() && m_rwhv->host()->delegate()->GetInputEventRouter()) + m_rwhv->host()->delegate()->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo()); } void RenderWidgetHostViewQtDelegateClient::handleMouseEvent(QMouseEvent *event) @@ -535,14 +540,14 @@ void RenderWidgetHostViewQtDelegateClient::handleKeyEvent(QKeyEvent *event) std::vector<blink::mojom::EditCommandPtr> commands; commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, "")); m_editCommand.clear(); - m_rwhv->host()->ForwardKeyboardEventWithCommands(webEvent, latency, std::move(commands), nullptr); + m_rwhv->GetFocusedWidget()->ForwardKeyboardEventWithCommands(webEvent, latency, std::move(commands), nullptr); return; } bool keyDownTextInsertion = webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && webEvent.text[0]; webEvent.skip_in_browser = keyDownTextInsertion; - m_rwhv->host()->ForwardKeyboardEvent(webEvent); + m_rwhv->GetFocusedWidget()->ForwardKeyboardEvent(webEvent); if (keyDownTextInsertion) { // Blink won't consume the RawKeyDown, but rather the Char event in this case. @@ -550,7 +555,7 @@ void RenderWidgetHostViewQtDelegateClient::handleKeyEvent(QKeyEvent *event) // The same os_event will be set on both NativeWebKeyboardEvents. webEvent.skip_in_browser = false; webEvent.SetType(blink::WebInputEvent::Type::kChar); - m_rwhv->host()->ForwardKeyboardEvent(webEvent); + m_rwhv->GetFocusedWidget()->ForwardKeyboardEvent(webEvent); } } @@ -733,14 +738,22 @@ void RenderWidgetHostViewQtDelegateClient::handleGestureEvent(QNativeGestureEven const Qt::NativeGestureType type = event->gestureType(); // These are the only supported gestures by Chromium so far. if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) { - m_rwhv->host()->ForwardGestureEvent(WebEventFactory::toWebGestureEvent(event)); + auto *hostDelegate = m_rwhv->host()->delegate(); + if (hostDelegate && hostDelegate->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebGestureEvent(event); + hostDelegate->GetInputEventRouter()->RouteGestureEvent(m_rwhv, &webEvent, ui::LatencyInfo()); + } } } #endif void RenderWidgetHostViewQtDelegateClient::handleHoverEvent(QHoverEvent *event) { - m_rwhv->host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); + auto *hostDelegate = m_rwhv->host()->delegate(); + if (hostDelegate && hostDelegate->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(event); + hostDelegate->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo()); + } } void RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent *event) diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 86cc5d52a..ed7f98f23 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -90,6 +90,8 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "common/extensions/extensions_client_qt.h" #include "extensions/extensions_renderer_client_qt.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #endif //ENABLE_EXTENSIONS #if BUILDFLAG(ENABLE_PLUGINS) @@ -219,6 +221,11 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr new printing::PrintRenderFrameHelper(render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); #endif // QT_CONFIG(webengine_printing_and_pdf) #if BUILDFLAG(ENABLE_EXTENSIONS) + blink::AssociatedInterfaceRegistry *associated_interfaces = render_frame_observer->associatedInterfaces(); + associated_interfaces->AddInterface(base::BindRepeating( + &extensions::MimeHandlerViewContainerManager::BindReceiver, + render_frame->GetRoutingID())); + auto registry = std::make_unique<service_manager::BinderRegistry>(); ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry()); #endif @@ -336,6 +343,30 @@ std::unique_ptr<blink::WebPrescientNetworking> ContentRendererClientQt::CreatePr return std::make_unique<network_hints::WebPrescientNetworkingImpl>(render_frame); } +bool ContentRendererClientQt::IsPluginHandledExternally(content::RenderFrame *render_frame, + const blink::WebElement &plugin_element, + const GURL &original_url, + const std::string &original_mime_type) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS) + bool found = false; + content::WebPluginInfo plugin_info; + std::string mime_type; + + render_frame->Send(new FrameHostMsg_GetPluginInfo(render_frame->GetRoutingID(), original_url, + render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), + original_mime_type, &found, &plugin_info, &mime_type)); + + return extensions::MimeHandlerViewContainerManager::Get( + content::RenderFrame::FromWebFrame( + plugin_element.GetDocument().GetFrame()), + true /* create_if_does_not_exist */) + ->CreateFrameContainer(plugin_element, original_url, mime_type, plugin_info); +#else + return false; +#endif +} + bool ContentRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_frame, const blink::WebPluginParams ¶ms, blink::WebPlugin **plugin) @@ -346,7 +377,6 @@ bool ContentRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_ #endif //ENABLE_EXTENSIONS #if BUILDFLAG(ENABLE_PLUGINS) - chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New(); content::WebPluginInfo info; std::string mime_type; bool found = false; @@ -354,30 +384,18 @@ bool ContentRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_ render_frame->Send(new FrameHostMsg_GetPluginInfo(render_frame->GetRoutingID(), params.url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), params.mime_type.Utf8(), &found, &info, &mime_type)); - if (!found) { - *plugin = CreatePlugin(render_frame, params, *plugin_info); - return true; - } + if (!found) + *plugin = LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(render_frame, params)->plugin(); + else + *plugin = render_frame->CreatePlugin(info, params, nullptr); #endif // BUILDFLAG(ENABLE_PLUGINS) - return content::ContentRendererClient::OverrideCreatePlugin(render_frame, params, plugin); + return true; } bool ContentRendererClientQt::IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) { - return plugin_path.value() == FILE_PATH_LITERAL("internal-pdf-viewer/"); -} - -#if BUILDFLAG(ENABLE_PLUGINS) -// static -blink::WebPlugin* ContentRendererClientQt::CreatePlugin(content::RenderFrame* render_frame, - const blink::WebPluginParams& original_params, - const chrome::mojom::PluginInfo& plugin_info) -{ - // If the browser plugin is to be enabled, this should be handled by the - // renderer, so the code won't reach here due to the early exit in OverrideCreatePlugin. - return LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(render_frame, original_params)->plugin(); + return plugin_path.value() == FILE_PATH_LITERAL("internal-pdf-viewer"); } -#endif //BUILDFLAG(ENABLE_PLUGINS) #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) chrome::WebRtcLoggingAgentImpl *ContentRendererClientQt::GetWebRtcLoggingAgent() diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index 0b0a7b68c..a0faec531 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -47,7 +47,6 @@ #include "ppapi/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_PLUGINS) -#include "qtwebengine/browser/plugin.mojom.h" #include "third_party/blink/public/web/web_plugin_params.h" #endif @@ -113,6 +112,10 @@ public: void RunScriptsAtDocumentStart(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentIdle(content::RenderFrame *render_frame) override; + bool IsPluginHandledExternally(content::RenderFrame *embedder_frame, + const blink::WebElement &plugin_element, + const GURL &original_url, + const std::string &original_mime_type); bool OverrideCreatePlugin(content::RenderFrame *render_frame, const blink::WebPluginParams ¶ms, blink::WebPlugin **plugin) override; @@ -128,12 +131,6 @@ public: bool RequiresWebComponentsV0(const GURL &url) override; -#if BUILDFLAG(ENABLE_PLUGINS) - static blink::WebPlugin* CreatePlugin(content::RenderFrame* render_frame, - const blink::WebPluginParams& params, - const chrome::mojom::PluginInfo& plugin_info); -#endif - #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) chrome::WebRtcLoggingAgentImpl *GetWebRtcLoggingAgent(); #endif diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp index 33c744f13..1b9de4d4d 100644 --- a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp +++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp @@ -48,6 +48,7 @@ #include "base/memory/ptr_util.h" #include "chrome/renderer/pepper/pepper_flash_font_file_host.h" +#include "chrome/renderer/pepper/pepper_uma_host.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "components/pdf/renderer/pepper_pdf_host.h" #endif // QT_CONFIG(webengine_printing_and_pdf) @@ -127,6 +128,14 @@ std::unique_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateRe } } #endif // QT_CONFIG(webengine_printing_and_pdf) + + // Create a default ResourceHost for this message type to suppress + // "Failed to create PPAPI resource host" console error message. + switch (message.type()) { + case PpapiHostMsg_UMA_Create::ID: + return std::make_unique<ppapi::host::ResourceHost>(host_->GetPpapiHost(), instance, resource); + } + return nullptr; } diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index fd900c292..77d325f3c 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -77,6 +77,12 @@ void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost *ho } #endif +bool RenderFrameObserverQt::OnAssociatedInterfaceRequestForFrame(const std::string &interface_name, + mojo::ScopedInterfaceEndpointHandle *handle) +{ + return m_associated_interfaces.TryBindInterface(interface_name, handle); +} + void RenderFrameObserverQt::WillDetach() { m_isFrameDetached = true; diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index 237185f8c..8803dde89 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -46,6 +46,7 @@ #include "content/public/renderer/render_frame_observer_tracker.h" #include "ppapi/buildflags/buildflags.h" #include "services/service_manager/public/cpp/binder_registry.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" namespace content { class RenderFrame; @@ -67,12 +68,18 @@ public: #if QT_CONFIG(webengine_pepper_plugins) void DidCreatePepperPlugin(content::RendererPpapiHost *host) override; #endif + bool OnAssociatedInterfaceRequestForFrame( + const std::string &interface_name, + mojo::ScopedInterfaceEndpointHandle *handle) override; void OnDestruct() override; void WillDetach() override; bool isFrameDetached() const; service_manager::BinderRegistry *registry() { return ®istry_; } + blink::AssociatedInterfaceRegistry *associatedInterfaces() { + return &m_associated_interfaces; + } private: DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverQt); @@ -81,6 +88,7 @@ private: bool m_isFrameDetached; service_manager::BinderRegistry registry_; + blink::AssociatedInterfaceRegistry m_associated_interfaces; web_cache::WebCacheImpl *m_web_cache_impl; }; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 014fb6482..0f41a53cb 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1546,7 +1546,15 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD QObject::disconnect(onDestroyed); if (dValid) { if (m_webContents) { - content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + // This is the quickest and (at the moment) the most safe solution to not break guest views when + // dropping data into them. We don't even try to support dropping into PDF input fields, + // since it's not working in Chrome right now. + content::WebContents *targetWebContents = m_webContents.get(); + std::vector<content::WebContents *> innerWebContents = m_webContents->GetInnerWebContents(); + if (!innerWebContents.empty()) + targetWebContents = innerWebContents[0]; + + content::RenderViewHost *rvh = targetWebContents->GetRenderViewHost(); if (rvh) { rvh->GetWidget()->DragSourceEndedAt(gfx::PointF(m_lastDragClientPos.x(), m_lastDragClientPos.y()), gfx::PointF(m_lastDragScreenPos.x(), m_lastDragScreenPos.y()), diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 93c48f268..9041f1489 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -46,7 +46,6 @@ #include "render_widget_host_view_qt.h" #include "touch_selection_controller_client_qt.h" #include "type_conversion.h" -#include "web_contents_adapter_client.h" #include "web_contents_adapter.h" #include "web_engine_context.h" #include "web_contents_delegate_qt.h" @@ -209,7 +208,7 @@ ASSERT_ENUMS_MATCH(QWebEngineContextMenuRequest::CanSelectAll, blink::kCanSelect ASSERT_ENUMS_MATCH(QWebEngineContextMenuRequest::CanTranslate, blink::kCanTranslate) ASSERT_ENUMS_MATCH(QWebEngineContextMenuRequest::CanEditRichly, blink::kCanEditRichly) - +// static void WebContentsViewQt::update(QWebEngineContextMenuRequest *request, const content::ContextMenuParams ¶ms, bool spellcheckEnabled) { diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 07a78016d..ff3b9d632 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -44,9 +44,14 @@ #include "content/browser/web_contents/web_contents_view.h" #include "api/qtwebenginecoreglobal_p.h" +#include "web_contents_adapter_client.h" QT_FORWARD_DECLARE_CLASS(QWebEngineContextMenuRequest) +namespace extensions { +class MimeHandlerViewGuestDelegateQt; +} + namespace content { class WebContents; } @@ -131,6 +136,8 @@ private: WebContentsAdapterClient *m_client; WebContentsAdapterClient *m_factoryClient; std::unique_ptr<QWebEngineContextMenuRequest> m_contextMenuRequest; + + friend class extensions::MimeHandlerViewGuestDelegateQt; }; } // namespace QtWebEngineCore diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 7f338efe8..94f214a07 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -431,6 +431,15 @@ void WebEngineContext::removeProfileAdapter(ProfileAdapter *profileAdapter) m_profileAdapters.removeAll(profileAdapter); } +void WebEngineContext::flushMessages() +{ + if (!m_destroyed) { + base::MessagePump::Delegate *delegate = static_cast< + base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( + WebEngineContext::current()->m_runLoop->delegate_); + while (delegate->DoWork().is_immediate()) { } + } +} void WebEngineContext::destroy() { if (m_devtoolsServer) @@ -441,20 +450,17 @@ void WebEngineContext::destroy() m_webrtcLogUploader->Shutdown(); #endif - base::MessagePump::Delegate *delegate = - static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( - m_runLoop->delegate_); // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. cleanupVizProcess(); while (waitForViz) { - while (delegate->DoWork().is_immediate()) { } + flushMessages(); QThread::msleep(50); } destroyGpuProcess(); // Flush the UI message loop before quitting. - while (delegate->DoWork().is_immediate()) { } + flushMessages(); #if QT_CONFIG(webengine_printing_and_pdf) // Kill print job manager early as it has a content::NotificationRegistrar @@ -476,7 +482,7 @@ void WebEngineContext::destroy() // Handle any events posted by browser-context shutdown. // This should deliver all nessesery calls of DeleteSoon from PostTask - while (delegate->DoWork().is_immediate()) { } + flushMessages(); m_devtoolsServer.reset(); m_runLoop->AfterRun(); @@ -596,23 +602,47 @@ bool WebEngineContext::isGpuServiceOnUIThread() return !threadedGpu; } -static void appendToFeatureList(std::string &featureList, const char *feature) +static void initializeFeatureList(base::CommandLine *commandLine, std::vector<std::string> enableFeatures, std::vector<std::string> disableFeatures) { - if (featureList.empty()) - featureList = feature; - else - featureList = featureList + "," + feature; -} + std::string enableFeaturesString = base::JoinString(enableFeatures, ","); + if (commandLine->HasSwitch(switches::kEnableFeatures)) { + std::string commandLineEnableFeatures = commandLine->GetSwitchValueASCII(switches::kEnableFeatures); -static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *featureSwitch, std::string feature) -{ - if (!commandLine->HasSwitch(featureSwitch)) { - commandLine->AppendSwitchASCII(featureSwitch, feature); - } else { - std::string featureList = commandLine->GetSwitchValueASCII(featureSwitch); - featureList = featureList + "," + feature; - commandLine->AppendSwitchASCII(featureSwitch, featureList); + for (const std::string &enableFeature : base::SplitString(commandLineEnableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(disableFeatures.begin(), disableFeatures.end(), enableFeature); + if (it == disableFeatures.end()) + continue; + + qWarning("An unsupported feature has been enabled from command line: %s\n" + "The feature is enabled but there is no guarantee that it will work or not break QtWebEngine.", enableFeature.c_str()); + + // If a feature is disabled and enabled at the same time, then it will be disabled. + // Remove feature from the disable list to make it possible to override from command line. + disableFeatures.erase(it); + } + + enableFeaturesString = enableFeaturesString + "," + commandLineEnableFeatures; } + + std::string disableFeaturesString = base::JoinString(disableFeatures, ","); + if (commandLine->HasSwitch(switches::kDisableFeatures)) { + std::string commandLineDisableFeatures = commandLine->GetSwitchValueASCII(switches::kDisableFeatures); + + for (const std::string &disableFeature : base::SplitString(commandLineDisableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(enableFeatures.begin(), enableFeatures.end(), disableFeature); + if (it == enableFeatures.end()) + continue; + + qWarning("An essential feature has been disabled from command line: %s\n" + "The feature is disabled but there is no guarantee that it will not break QtWebEngine.", disableFeature.c_str()); + } + + disableFeaturesString = disableFeaturesString + "," + commandLineDisableFeatures; + } + + commandLine->AppendSwitchASCII(switches::kEnableFeatures, enableFeaturesString); + commandLine->AppendSwitchASCII(switches::kDisableFeatures, disableFeaturesString); + base::FeatureList::InitializeInstance(enableFeaturesString, disableFeaturesString); } WebEngineContext::WebEngineContext() @@ -683,55 +713,51 @@ WebEngineContext::WebEngineContext() // Do not advertise a feature we have removed at compile time parsedCommandLine->AppendSwitch(switches::kDisableSpeechAPI); - std::string disableFeatures; - std::string enableFeatures; + std::vector<std::string> disableFeatures; + std::vector<std::string> enableFeatures; // Needed to allow navigations within pages that were set using setHtml(). One example is // tst_QWebEnginePage::acceptNavigationRequest. // This is deprecated behavior, and will be removed in a future Chromium version, as per // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. - appendToFeatureList(enableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); + enableFeatures.push_back(features::kAllowContentInitiatedDataUrlNavigations.name); - appendToFeatureList(enableFeatures, features::kTracingServiceInProcess.name); + enableFeatures.push_back(features::kTracingServiceInProcess.name); // The video-capture service is not functioning at this moment (since 69) - appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); + disableFeatures.push_back(features::kMojoVideoCapture.name); #if defined(Q_OS_LINUX) // broken and crashy (even upstream): - appendToFeatureList(disableFeatures, features::kFontSrcLocalMatching.name); + disableFeatures.push_back(features::kFontSrcLocalMatching.name); #endif // We don't support the skia renderer (enabled by default on Linux since 80) - appendToFeatureList(disableFeatures, features::kUseSkiaRenderer.name); + disableFeatures.push_back(features::kUseSkiaRenderer.name); - appendToFeatureList(disableFeatures, network::features::kDnsOverHttpsUpgrade.name); + disableFeatures.push_back(network::features::kDnsOverHttpsUpgrade.name); // When enabled, event.movement is calculated in blink instead of in browser. - appendToFeatureList(disableFeatures, features::kConsolidatedMovementXY.name); + disableFeatures.push_back(features::kConsolidatedMovementXY.name); // Avoid crashing when websites tries using this feature (since 83) - appendToFeatureList(disableFeatures, features::kInstalledApp.name); + disableFeatures.push_back(features::kInstalledApp.name); // Explicitly tell Chromium about default-on features we do not support - appendToFeatureList(disableFeatures, features::kBackgroundFetch.name); - appendToFeatureList(disableFeatures, features::kSmsReceiver.name); - appendToFeatureList(disableFeatures, features::kWebPayments.name); - appendToFeatureList(disableFeatures, features::kWebUsb.name); - appendToFeatureList(disableFeatures, media::kPictureInPicture.name); + disableFeatures.push_back(features::kBackgroundFetch.name); + disableFeatures.push_back(features::kSmsReceiver.name); + disableFeatures.push_back(features::kWebPayments.name); + disableFeatures.push_back(features::kWebUsb.name); + disableFeatures.push_back(media::kPictureInPicture.name); if (useEmbeddedSwitches) { // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc - appendToFeatureList(enableFeatures, features::kOverlayScrollbar.name); + enableFeatures.push_back(features::kOverlayScrollbar.name); parsedCommandLine->AppendSwitch(switches::kEnableViewport); parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } - appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, disableFeatures); - appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, enableFeatures); - base::FeatureList::InitializeInstance( - parsedCommandLine->GetSwitchValueASCII(switches::kEnableFeatures), - parsedCommandLine->GetSwitchValueASCII(switches::kDisableFeatures)); + initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures); GLContextHelper::initialize(); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 63872bdfe..9ac598c67 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -108,6 +108,7 @@ public: static WebEngineContext *current(); static void destroyContextPostRoutine(); static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port); + static void flushMessages(); ProfileAdapter *createDefaultProfileAdapter(); ProfileAdapter *defaultProfileAdapter(); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index c5cede929..47c4634b3 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -46,6 +46,7 @@ #include "components/spellcheck/spellcheck_buildflags.h" #include "content/public/common/content_paths.h" #include "sandbox/policy/switches.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" @@ -353,18 +354,15 @@ base::string16 WebEngineLibraryInfo::getApplicationName() std::string WebEngineLibraryInfo::getApplicationLocale() { base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); - if (!parsedCommandLine->HasSwitch(switches::kLang)) { + if (parsedCommandLine->HasSwitch(switches::kLang)) { + return parsedCommandLine->GetSwitchValueASCII(switches::kLang); + } else { const QString &locale = QLocale().bcp47Name(); - - // QLocale::bcp47Name returns "en" for American English locale. Chromium requires the "US" suffix - // to clarify the dialect and ignores the shorter version. - if (locale == "en") - return "en-US"; - - return locale.toStdString(); + std::string resolvedLocale; + if (l10n_util::CheckAndResolveLocale(locale.toStdString(), &resolvedLocale)) + return resolvedLocale; } - - return parsedCommandLine->GetSwitchValueASCII(switches::kLang); + return "en-US"; } #if defined(OS_WIN) diff --git a/src/pdf/config/common.pri b/src/pdf/config/common.pri index 303c4a91c..afd96c881 100644 --- a/src/pdf/config/common.pri +++ b/src/pdf/config/common.pri @@ -1,6 +1,8 @@ include($$QTWEBENGINE_OUT_ROOT/src/pdf/qtpdf-config.pri) QT_FOR_CONFIG += pdf-private +gn_args += use_nss_certs=false + qtConfig(webengine-qt-png) { gn_args += pdfium_use_qt_libpng=true gn_args += "pdfium_qt_libpng_includes=\"$$system_path($$QMAKE_INCDIR_LIBPNG)\"" diff --git a/src/webengine/api/qquickwebenginetouchhandleprovider.cpp b/src/webengine/api/qquickwebenginetouchhandleprovider.cpp index 56162b223..d6d6116dd 100644 --- a/src/webengine/api/qquickwebenginetouchhandleprovider.cpp +++ b/src/webengine/api/qquickwebenginetouchhandleprovider.cpp @@ -67,7 +67,7 @@ void QQuickWebEngineTouchHandleProvider::init(const QMap<int, QImage> &images) return; } - m_touchHandleMap.insert(images); + m_touchHandleMap = images; } QImage QQuickWebEngineTouchHandleProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index aea514730..5d5392316 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -235,7 +235,8 @@ RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHo const bool hasWindowCapability = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows); RenderWidgetHostViewQtDelegateQuick *quickDelegate = new RenderWidgetHostViewQtDelegateQuick(client, /*isPopup = */ true); if (hasWindowCapability) { - RenderWidgetHostViewQtDelegateQuickWindow *wrapperWindow = new RenderWidgetHostViewQtDelegateQuickWindow(quickDelegate); + RenderWidgetHostViewQtDelegateQuickWindow *wrapperWindow = + new RenderWidgetHostViewQtDelegateQuickWindow(quickDelegate, q->window()); wrapperWindow->setVirtualParent(q); quickDelegate->setParentItem(wrapperWindow->contentItem()); return wrapperWindow; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp index 75c660086..c6d866033 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -44,9 +44,19 @@ namespace QtWebEngineCore { -RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow(RenderWidgetHostViewQtDelegateQuick *realDelegate) - : m_realDelegate(realDelegate) - , m_virtualParent(nullptr) +static inline QPoint getOffset(QQuickItem *item) +{ + // get parent window (scene) offset + QPointF offset = item->mapFromScene(QPoint(0, 0)); + offset = item->mapToGlobal(offset); + // get local offset + offset -= item->mapToScene(QPoint(0, 0)); + return offset.toPoint(); +} + +RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow( + RenderWidgetHostViewQtDelegateQuick *realDelegate, QWindow *parent) + : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr) { setFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); } @@ -61,29 +71,12 @@ void RenderWidgetHostViewQtDelegateQuickWindow::setVirtualParent(QQuickItem *vir m_virtualParent = virtualParent; } -static inline QRectF mapRectToGlobal(const QQuickItem *item, const QRectF &rect) -{ - const QPointF p1 = item->mapToGlobal(rect.topLeft()); - const QPointF p2 = item->mapToGlobal(rect.bottomRight()); - return QRectF(p1, p2).normalized(); -} - -static inline QRectF mapRectFromGlobal(const QQuickItem *item, const QRectF &rect) +void RenderWidgetHostViewQtDelegateQuickWindow::initAsPopup(const QRect &rect) { - const QPointF p1 = item->mapFromGlobal(rect.topLeft()); - const QPointF p2 = item->mapFromGlobal(rect.bottomRight()); - return QRectF(p1, p2).normalized(); -} - -void RenderWidgetHostViewQtDelegateQuickWindow::initAsPopup(const QRect &screenRect) -{ - QRectF popupRect(screenRect); - popupRect = mapRectFromGlobal(m_virtualParent, popupRect); - popupRect = m_virtualParent->mapRectToScene(popupRect); - popupRect = mapRectToGlobal(m_virtualParent, popupRect); - m_realDelegate->setSize(popupRect.size()); - popupRect.setSize(screenRect.size()); - setGeometry(popupRect.toAlignedRect()); + m_realDelegate->setSize(rect.size()); + QRect geometry(rect); + geometry.moveTo(rect.topLeft() - getOffset(m_virtualParent)); + setGeometry(geometry); raise(); show(); } @@ -133,12 +126,7 @@ void RenderWidgetHostViewQtDelegateQuickWindow::resize(int width, int height) void RenderWidgetHostViewQtDelegateQuickWindow::move(const QPoint &screenPos) { - QRectF popupRect(screenPos, size()); - popupRect = mapRectFromGlobal(m_virtualParent, popupRect); - popupRect = m_virtualParent->mapRectToScene(popupRect); - popupRect = mapRectToGlobal(m_virtualParent, popupRect); - - QQuickWindow::setPosition(popupRect.topLeft().toPoint()); + QQuickWindow::setPosition(screenPos - getOffset(m_virtualParent)); } } // namespace QtWebEngineCore diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h index 5e8155f1b..632c59fa5 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h @@ -52,7 +52,8 @@ namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegateQuickWindow : public QQuickWindow , public RenderWidgetHostViewQtDelegate { public: - RenderWidgetHostViewQtDelegateQuickWindow(RenderWidgetHostViewQtDelegateQuick *realDelegate); + RenderWidgetHostViewQtDelegateQuickWindow(RenderWidgetHostViewQtDelegateQuick *realDelegate, + QWindow *parent); ~RenderWidgetHostViewQtDelegateQuickWindow(); void initAsPopup(const QRect&) override; diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 2b5b2414c..0891f9ca8 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -88,7 +88,15 @@ void QWebEngineViewPrivate::pageChanged(QWebEnginePage *oldPage, QWebEnginePage if (oldPage) { oldPage->setVisible(false); - oldPage->disconnect(q); + QObject::disconnect(oldPage, &QWebEnginePage::titleChanged, q, &QWebEngineView::titleChanged); + QObject::disconnect(oldPage, &QWebEnginePage::urlChanged, q, &QWebEngineView::urlChanged); + QObject::disconnect(oldPage, &QWebEnginePage::iconUrlChanged, q, &QWebEngineView::iconUrlChanged); + QObject::disconnect(oldPage, &QWebEnginePage::iconChanged, q, &QWebEngineView::iconChanged); + QObject::disconnect(oldPage, &QWebEnginePage::loadStarted, q, &QWebEngineView::loadStarted); + QObject::disconnect(oldPage, &QWebEnginePage::loadProgress, q, &QWebEngineView::loadProgress); + QObject::disconnect(oldPage, &QWebEnginePage::loadFinished, q, &QWebEngineView::loadFinished); + QObject::disconnect(oldPage, &QWebEnginePage::selectionChanged, q, &QWebEngineView::selectionChanged); + QObject::disconnect(oldPage, &QWebEnginePage::renderProcessTerminated, q, &QWebEngineView::renderProcessTerminated); } if (newPage) { |