From 8f56ea6806d9a72d4b705da5f6f90fa5a6873567 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Thu, 4 Feb 2021 14:48:52 +0100 Subject: Show PDF viewer in a guest view This is the basic support of guest views, implemented based on Chrome. - Embed PDF as a child frame instead of navigating to its extension WebUI. Keep the original URL (pointing to the file) to extend functionality of PDF viewer with URL parameters. - Make RenderWidgetHostInputEventRouter to work and modify most of the event forwarding logic to use that. This way WebEngine supports pages with multiple RenderWidgetHost and guest views can be interactive with user input. [ChangeLog] PDF files are opened as embedded objects, WebEngine will not navigate the content away from the requested file to present it. PDF viewer can accept URL parameters (e.g. to control zooming or fitting to view). Also, PDF viewer is interactive when displayed in a subframe. Task-number: QTBUG-80463 Task-number: QTBUG-86152 Task-number: QTBUG-90712 Change-Id: Ib1591fbd9a594891cdeace8e9dae0d3cc21a9f8e Reviewed-by: Allan Sandfeld Jensen --- src/core/content_browser_client_qt.cpp | 37 ++++- src/core/content_browser_client_qt.h | 1 + src/core/content_client_qt.cpp | 2 +- src/core/extensions/extension_system_qt.cpp | 5 +- .../extension_web_contents_observer_qt.cpp | 16 ++- .../extension_web_contents_observer_qt.h | 1 + src/core/extensions/extensions_api_client_qt.cpp | 7 +- .../extensions/extensions_browser_client_qt.cpp | 2 +- .../mime_handler_view_guest_delegate_qt.cpp | 26 ++-- .../mime_handler_view_guest_delegate_qt.h | 3 +- ...in_response_interceptor_url_loader_throttle.cpp | 151 ++++++++++++++------- ...ugin_response_interceptor_url_loader_throttle.h | 12 +- src/core/qtwebengine_sources.gni | 5 +- src/core/render_widget_host_view_qt.cpp | 99 +++++++++++--- src/core/render_widget_host_view_qt.h | 9 ++ src/core/renderer/content_renderer_client_qt.cpp | 56 +++++--- src/core/renderer/content_renderer_client_qt.h | 11 +- .../pepper/pepper_renderer_host_factory_qt.cpp | 9 ++ src/core/renderer/render_frame_observer_qt.cpp | 6 + src/core/renderer/render_frame_observer_qt.h | 8 ++ src/core/web_contents_adapter.cpp | 10 +- src/core/web_contents_view_qt.cpp | 5 +- src/core/web_contents_view_qt.h | 3 + 23 files changed, 362 insertions(+), 122 deletions(-) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 0b5da57a6..e13ecd8d1 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" @@ -156,12 +157,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" @@ -984,8 +987,11 @@ static bool navigationThrottleCallback(content::WebContents *source, return false; int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; - WebContentsDelegateQt *delegate = static_cast(source->GetDelegate()); - WebContentsAdapterClient *client = delegate->adapterClient(); + + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast(source)->GetView())->client(); + if (!client) + return false; client->navigationRequested(pageTransitionToNavigationType(params.transition_type()), toQt(params.url()), navigationRequestAction, @@ -1273,6 +1279,33 @@ void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int #endif } +base::flat_set ContentBrowserClientQt::GetPluginMimeTypesWithExternalHandlers( + content::BrowserContext *browser_context) +{ + base::flat_set mime_types; +#if BUILDFLAG(ENABLE_EXTENSIONS) + ProfileQt *profile = static_cast(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, diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 3db182e69..7c8aa3ac9 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -258,6 +258,7 @@ public: NonNetworkURLLoaderFactoryMap* factories) override; void SiteInstanceGotProcess(content::SiteInstance *site_instance) override; void SiteInstanceDeleting(content::SiteInstance *site_instance) override; + base::flat_set GetPluginMimeTypesWithExternalHandlers(content::BrowserContext *browser_context) override; content::WebContentsViewDelegate* GetWebContentsViewDelegate(content::WebContents* web_contents) override; 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/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::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(parent_web_contents->GetRenderWidgetHostView()); + parent_rwhv->setGuest(static_cast(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; 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 #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 ExtensionsAPIClientQt::CreateGuestViewManagerDelegate(content::BrowserContext *context) const { - return std::make_unique(); + return std::make_unique(context); } std::unique_ptr ExtensionsAPIClientQt::CreateMimeHandlerViewGuestDelegate(MimeHandlerViewGuest *guest) const { - return std::make_unique(); + return std::make_unique(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..89d3d6f20 100644 --- a/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp +++ b/src/core/extensions/mime_handler_view_guest_delegate_qt.cpp @@ -44,12 +44,17 @@ #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 "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 *) @@ -63,14 +68,17 @@ MimeHandlerViewGuestDelegateQt::~MimeHandlerViewGuestDelegateQt() bool MimeHandlerViewGuestDelegateQt::HandleContextMenu(content::WebContents *web_contents, const content::ContextMenuParams ¶ms) { - content::ContextMenuParams new_params = params; - - gfx::Point guest_coordinates = - static_cast(web_contents)->GetBrowserPluginGuest()->GetScreenCoordinates(gfx::Point()); + content::WebContents *parent_web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(web_contents); + if (auto rwhv = static_cast(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::WebEngineContextMenuData contextMenuData(QtWebEngineCore::WebContentsViewQt::buildContextMenuData(params)); + contextMenuData.setIsSpellCheckerEnabled(adapterClient->profileAdapter()->isSpellCheckEnabled()); + adapterClient->contextMenuRequested(contextMenuData); + 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..8b2e29508 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,7 @@ #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" namespace content { struct ContextMenuParams; 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 bd03d3083..326bdabb1 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -40,27 +40,50 @@ #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 namespace QtWebEngineCore { -void onPdfStreamIntercepted(const GURL &original_url, std::string extension_id, int 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) +{} + +void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL &response_url, + network::mojom::URLResponseHead *response_head, + bool *defer) { - content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (content::download_utils::MustDownload(response_url, response_head->headers.get(), response_head->mime_type)) + return; + + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(m_frame_tree_node_id); if (!web_contents) return; + std::string extension_id; + if (response_head->mime_type == "application/pdf") + extension_id = extension_misc::kPdfExtensionId; + if (extension_id.empty()) + return; + WebContentsDelegateQt *contentsDelegate = static_cast(web_contents->GetDelegate()); if (!contentsDelegate) return; @@ -71,62 +94,90 @@ void onPdfStreamIntercepted(const GURL &original_url, std::string extension_id, // 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 params( - content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(web_contents, original_url, + content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(web_contents, response_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) -{} - -void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL &response_url, - network::mojom::URLResponseHead *response_head, - bool *defer) -{ - Q_UNUSED(defer); - 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); + // 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 dummy_new_loader; + ignore_result(dummy_new_loader.InitWithNewPipeAndPassReceiver()); + mojo::Remote new_client; + mojo::PendingReceiver 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(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 original_loader; + mojo::PendingReceiver 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( + response_head->headers->raw_headers()); } - 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; + 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(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 + weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index dc337e1de..a35218775 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -199,7 +199,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 958c1c3c4..a6b925db6 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -62,6 +62,7 @@ #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" @@ -302,12 +303,35 @@ 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(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_sendMotionActionDown(false) , m_touchMotionStarted(false) + , m_guestInputEventObserver(new GuestInputEventObserverQt(this)) , m_visible(false) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) @@ -354,6 +378,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()); @@ -406,6 +432,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) { } @@ -481,6 +512,11 @@ bool RenderWidgetHostViewQt::IsMouseLocked() return m_isMouseLocked; } +viz::FrameSinkId RenderWidgetHostViewQt::GetRootFrameSinkId() +{ + return m_uiCompositor->frame_sink_id(); +} + bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { return m_delegatedFrameHost->CanCopyFromCompositingSurface(); @@ -727,6 +763,11 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) 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. @@ -748,6 +789,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; @@ -760,7 +813,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)); } @@ -960,7 +1013,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() @@ -1169,8 +1223,12 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) if (m_mouseButtonPressed > 0) return false; #endif - case QEvent::HoverLeave: - host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); + case QEvent::HoverLeave: { + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(event); + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); + } + } break; default: return false; @@ -1251,11 +1309,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)); } QList RenderWidgetHostViewQt::mapTouchPoints(const QList &input) @@ -1343,13 +1401,13 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) std::vector commands; commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, "")); m_editCommand.clear(); - host()->ForwardKeyboardEventWithCommands(webEvent, latency, std::move(commands), nullptr); + 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; - host()->ForwardKeyboardEvent(webEvent); + GetFocusedWidget()->ForwardKeyboardEvent(webEvent); if (keyDownTextInsertion) { // Blink won't consume the RawKeyDown, but rather the Char event in this case. @@ -1357,7 +1415,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) // The same os_event will be set on both NativeWebKeyboardEvents. webEvent.skip_in_browser = false; webEvent.SetType(blink::WebInputEvent::Type::kChar); - host()->ForwardKeyboardEvent(webEvent); + GetFocusedWidget()->ForwardKeyboardEvent(webEvent); } } @@ -1525,8 +1583,9 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) Q_ASSERT(m_pendingWheelEvents.isEmpty()); blink::WebMouseWheelEvent webEvent = WebEventFactory::toWebWheelEvent(ev); 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()); return; } if (!m_pendingWheelEvents.isEmpty()) { @@ -1546,8 +1605,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()); } } @@ -1577,7 +1637,10 @@ void RenderWidgetHostViewQt::handleGestureEvent(QNativeGestureEvent *ev) const Qt::NativeGestureType type = ev->gestureType(); // These are the only supported gestures by Chromium so far. if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) { - host()->ForwardGestureEvent(WebEventFactory::toWebGestureEvent(ev)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebGestureEvent(ev); + host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &webEvent, ui::LatencyInfo()); + } } } #endif @@ -1806,12 +1869,16 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) #endif } - host()->ForwardMouseEvent(webEvent); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); } void RenderWidgetHostViewQt::handleHoverEvent(QHoverEvent *ev) { - host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { + auto webEvent = WebEventFactory::toWebMouseEvent(ev); + host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &webEvent, ui::LatencyInfo()); + } } void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 4fe76b2b6..63dae6d58 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -76,6 +76,7 @@ class TouchSelectionController; namespace QtWebEngineCore { +class GuestInputEventObserverQt; class TouchHandleDrawableClient; class TouchSelectionControllerClientQt; class TouchSelectionMenuController; @@ -119,6 +120,7 @@ public: void setDelegate(RenderWidgetHostViewQtDelegate *delegate); WebContentsAdapterClient *adapterClient() { return m_adapterClient; } void setAdapterClient(WebContentsAdapterClient *adapterClient); + void setGuest(content::RenderWidgetHostImpl *); void InitAsChild(gfx::NativeView) override; void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) override; @@ -130,6 +132,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, @@ -144,10 +147,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&) 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; @@ -263,6 +270,7 @@ private: blink::ScreenInfo m_screenInfo; scoped_refptr m_taskRunner; + std::unique_ptr m_cursorManager; ui::FilteredGestureProvider m_gestureProvider; base::TimeDelta m_eventsToNowDelta; @@ -271,6 +279,7 @@ private: QMap m_touchIdMapping; QList m_previousTouchPoints; std::unique_ptr m_delegate; + std::unique_ptr m_guestInputEventObserver; bool m_visible; bool m_deferredShow = false; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index cafdeddb4..317fde8f7 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -91,6 +91,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) @@ -220,6 +222,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(); ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry()); #endif @@ -337,6 +344,30 @@ std::unique_ptr ContentRendererClientQt::CreatePr return std::make_unique(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) @@ -347,7 +378,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; @@ -355,30 +385,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 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(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 ee0c1fb3c..bfeab41a2 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1547,7 +1547,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 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 6c5e76742..900c53829 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" @@ -195,7 +194,7 @@ ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanSelectAll, blink::kCanSelectAll) ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanTranslate, blink::kCanTranslate) ASSERT_ENUMS_MATCH(WebEngineContextMenuData::CanEditRichly, blink::kCanEditRichly) -static inline WebEngineContextMenuData fromParams(const content::ContextMenuParams ¶ms) +WebEngineContextMenuData WebContentsViewQt::buildContextMenuData(const content::ContextMenuParams ¶ms) { WebEngineContextMenuData ret; ret.setPosition(QPoint(params.x, params.y)); @@ -229,7 +228,7 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten return; } - WebEngineContextMenuData contextMenuData(fromParams(params)); + WebEngineContextMenuData contextMenuData(buildContextMenuData(params)); #if QT_CONFIG(webengine_spellchecker) // Do not use params.spellcheck_enabled, since it is never // correctly initialized for chrome asynchronous spellchecking. diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index d2f82dfad..da0c5d20c 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -44,6 +44,7 @@ #include "content/browser/web_contents/web_contents_view.h" #include "api/qtwebenginecoreglobal_p.h" +#include "web_contents_adapter_client.h" namespace content { class WebContents; @@ -120,6 +121,8 @@ public: void LostFocus(content::RenderWidgetHostImpl *render_widget_host) override; void TakeFocus(bool reverse) override; + static WebEngineContextMenuData buildContextMenuData(const content::ContextMenuParams ¶ms); + private: content::WebContents *m_webContents; WebContentsAdapterClient *m_client; -- cgit v1.2.3