diff options
Diffstat (limited to 'src/core/renderer/content_renderer_client_qt.cpp')
-rw-r--r-- | src/core/renderer/content_renderer_client_qt.cpp | 758 |
1 files changed, 440 insertions, 318 deletions
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 092e6845d..cc127e55f 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -1,91 +1,56 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "renderer/content_renderer_client_qt.h" -#include "common/qt_messages.h" -#include "extensions/buildflags/buildflags.h" -#include "printing/buildflags/buildflags.h" #include "renderer/content_settings_observer_qt.h" -#include "base/strings/string_split.h" -#if QT_CONFIG(webengine_spellchecker) -#include "components/spellcheck/renderer/spellcheck.h" -#include "components/spellcheck/renderer/spellcheck_provider.h" -#endif -#include "components/cdm/renderer/external_clear_key_key_system_properties.h" -#include "components/cdm/renderer/widevine_key_system_properties.h" +#include "renderer/render_configuration.h" +#include "renderer/render_frame_observer_qt.h" +#include "renderer/user_resource_controller.h" +#include "renderer/web_engine_page_render_frame.h" +#include "web_engine_library_info.h" + +#include "base/task/sequenced_task_runner.h" +#include "components/autofill/content/renderer/autofill_agent.h" +#include "components/autofill/content/renderer/password_autofill_agent.h" +#include "components/autofill/content/renderer/password_generation_agent.h" +#include "components/cdm/renderer/external_clear_key_key_system_info.h" +#include "components/cdm/renderer/widevine_key_system_info.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" -#include "components/network_hints/renderer/prescient_networking_dispatcher.h" -#if QT_CONFIG(webengine_printing_and_pdf) -#include "components/printing/renderer/print_render_frame_helper.h" -#endif -#include "components/visitedlink/renderer/visitedlink_slave.h" +#include "components/grit/components_resources.h" +#include "components/network_hints/renderer/web_prescient_networking_impl.h" +#include "components/visitedlink/renderer/visitedlink_reader.h" #include "components/web_cache/renderer/web_cache_impl.h" #include "content/public/renderer/render_frame.h" -#include "content/public/child/child_thread.h" -#include "content/public/common/service_manager_connection.h" -#include "content/public/common/simple_connection_filter.h" +#include "content/public/common/url_constants.h" #include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" -#include "media/base/key_system_properties.h" +#include "extensions/buildflags/buildflags.h" +#include "media/base/key_system_info.h" +#include "media/cdm/cdm_capability.h" #include "media/media_buildflags.h" +#include "mojo/public/cpp/bindings/binder_map.h" #include "net/base/net_errors.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/interface_provider.h" +#include "ppapi/buildflags/buildflags.h" +#include "printing/buildflags/buildflags.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/platform/web_url_error.h" -#include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/web/web_security_policy.h" -#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" -#include "content/public/common/web_preferences.h" + +#if QT_CONFIG(webengine_spellchecker) +#include "components/spellcheck/renderer/spellcheck.h" +#include "components/spellcheck/renderer/spellcheck_provider.h" +#endif #if QT_CONFIG(webengine_printing_and_pdf) #include "renderer/print_web_view_helper_delegate_qt.h" + +#include "components/pdf/renderer/internal_plugin_renderer_helpers.h" +#include "components/pdf/renderer/pdf_internal_plugin_delegate.h" +#include "components/printing/renderer/print_render_frame_helper.h" #endif -#include "renderer/render_frame_observer_qt.h" -#include "renderer/render_view_observer_qt.h" -#include "renderer/render_thread_observer_qt.h" -#include "renderer/user_resource_controller.h" #if QT_CONFIG(webengine_webchannel) #include "renderer/web_channel_ipc_transport.h" #endif @@ -93,28 +58,38 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "common/extensions/extensions_client_qt.h" #include "extensions/extensions_renderer_client_qt.h" -#endif //ENABLE_EXTENSIONS +#include "extensions/common/constants.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/connector.h" +#include "third_party/blink/public/web/web_security_policy.h" +#endif // ENABLE_EXTENSIONS -#include "components/grit/components_resources.h" +#if BUILDFLAG(ENABLE_PLUGINS) +#include "content/renderer/render_frame_impl.h" +#include "plugins/loadable_plugin_placeholder_qt.h" +#endif // ENABLE_PLUGINS #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "base/feature_list.h" #include "content/public/renderer/key_system_support.h" #include "media/base/media_switches.h" #include "media/base/video_codecs.h" +#include "media/cdm/clear_key_cdm_common.h" #include "third_party/widevine/cdm/buildflags.h" +#if BUILDFLAG(ENABLE_WIDEVINE) #include "third_party/widevine/cdm/widevine_cdm_common.h" #endif +#endif -namespace QtWebEngineCore { +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/renderer/media/webrtc_logging_agent_impl.h" +#endif -static const char kHttpErrorDomain[] = "http"; +namespace QtWebEngineCore { ContentRendererClientQt::ContentRendererClientQt() - : m_serviceBinding(this) { #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionsClient::Set(extensions::ExtensionsClientQt::GetInstance()); @@ -122,67 +97,83 @@ ContentRendererClientQt::ContentRendererClientQt() #endif } -ContentRendererClientQt::~ContentRendererClientQt() -{ -} +ContentRendererClientQt::~ContentRendererClientQt() {} void ContentRendererClientQt::RenderThreadStarted() { + base::i18n::SetICUDefaultLocale(WebEngineLibraryInfo::getApplicationLocale()); content::RenderThread *renderThread = content::RenderThread::Get(); - (void)GetConnector(); - m_renderThreadObserver.reset(new RenderThreadObserverQt()); - m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); + m_renderConfiguration.reset(new RenderConfiguration()); + m_userResourceController.reset(new UserResourceController()); + m_visitedLinkReader.reset(new visitedlink::VisitedLinkReader); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - m_prescientNetworkingDispatcher.reset(new network_hints::PrescientNetworkingDispatcher()); - - auto registry = std::make_unique<service_manager::BinderRegistry>(); - registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), - base::ThreadTaskRunnerHandle::Get()); - content::ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( - std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); - - renderThread->AddObserver(m_renderThreadObserver.data()); - renderThread->AddObserver(UserResourceController::instance()); + renderThread->AddObserver(m_renderConfiguration.data()); + renderThread->AddObserver(m_userResourceController.data()); #if QT_CONFIG(webengine_spellchecker) if (!m_spellCheck) InitSpellCheck(); #endif - // Allow XMLHttpRequests from qrc to file. - blink::WebURL qrc(blink::KURL("qrc:")); - blink::WebString file(blink::WebString::FromASCII("file")); - blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(qrc, file, blink::WebString(), true, - network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); - #if BUILDFLAG(ENABLE_EXTENSIONS) // Allow the pdf viewer extension to access chrome resources - blink::WebURL pdfViewerExtension(blink::KURL("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai")); + blink::WebURL pdfViewerExtension(GURL("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai")); blink::WebString chromeResources(blink::WebString::FromASCII("chrome")); - blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(pdfViewerExtension, chromeResources, blink::WebString(), true, - network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); + blink::WebSecurityPolicy::AddOriginAccessAllowListEntry( + pdfViewerExtension, chromeResources, blink::WebString(), 0, + network::mojom::CorsDomainMatchMode::kAllowSubdomains, network::mojom::CorsPortMatchMode::kAllowAnyPort, + network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); ExtensionsRendererClientQt::GetInstance()->RenderThreadStarted(); #endif } -void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) +void ContentRendererClientQt::ExposeInterfacesToBrowser(mojo::BinderMap* binders) { - // RenderViewObservers destroy themselves with their RenderView. - new RenderViewObserverQt(render_view, m_webCacheImpl.data()); - UserResourceController::instance()->renderViewCreated(render_view); + binders->Add<visitedlink::mojom::VisitedLinkNotificationSink>( + m_visitedLinkReader->GetBindCallback(), base::SingleThreadTaskRunner::GetCurrentDefault()); + + binders->Add<web_cache::mojom::WebCache>( + base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver, + base::Unretained(m_webCacheImpl.get())), + base::SingleThreadTaskRunner::GetCurrentDefault()); + +#if QT_CONFIG(webengine_spellchecker) + binders->Add<spellcheck::mojom::SpellChecker>( + base::BindRepeating( + [](ContentRendererClientQt *client, + mojo::PendingReceiver<spellcheck::mojom::SpellChecker> receiver) { + if (!client->m_spellCheck) + client->InitSpellCheck(); + client->m_spellCheck->BindReceiver(std::move(receiver)); + }, this), + base::SingleThreadTaskRunner::GetCurrentDefault()); +#endif + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + binders->Add<chrome::mojom::WebRtcLoggingAgent>( + base::BindRepeating( + [](ContentRendererClientQt *client, + mojo::PendingReceiver<chrome::mojom::WebRtcLoggingAgent> receiver) { + client->GetWebRtcLoggingAgent()->AddReceiver(std::move(receiver)); + }, this), + base::SingleThreadTaskRunner::GetCurrentDefault()); +#endif } -void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) +void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_frame) { - QtWebEngineCore::RenderFrameObserverQt *render_frame_observer = new QtWebEngineCore::RenderFrameObserverQt(render_frame); + QtWebEngineCore::RenderFrameObserverQt *render_frame_observer = + new QtWebEngineCore::RenderFrameObserverQt(render_frame, m_webCacheImpl.data()); + if (render_frame->IsMainFrame()) { #if QT_CONFIG(webengine_webchannel) - if (render_frame->IsMainFrame()) new WebChannelIPCTransport(render_frame); #endif + new WebEnginePageRenderFrame(render_frame); + } - UserResourceController::instance()->renderFrameCreated(render_frame); + m_userResourceController->renderFrameCreated(render_frame); new QtWebEngineCore::ContentSettingsObserverQt(render_frame); @@ -190,14 +181,39 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_fr new SpellCheckProvider(render_frame, m_spellCheck.data(), this); #endif #if QT_CONFIG(webengine_printing_and_pdf) - new printing::PrintRenderFrameHelper( - render_frame, - base::WrapUnique(new PrintWebViewHelperDelegateQt())); + new printing::PrintRenderFrameHelper(render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); #endif // QT_CONFIG(webengine_printing_and_pdf) + + blink::AssociatedInterfaceRegistry *associated_interfaces = render_frame_observer->associatedInterfaces(); + #if BUILDFLAG(ENABLE_EXTENSIONS) + associated_interfaces->AddInterface<extensions::mojom::MimeHandlerViewContainerManager>( + 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 + + autofill::PasswordAutofillAgent *password_autofill_agent = + new autofill::PasswordAutofillAgent(render_frame, associated_interfaces); + autofill::PasswordGenerationAgent *password_generation_agent = + new autofill::PasswordGenerationAgent(render_frame, password_autofill_agent, + associated_interfaces); + + new autofill::AutofillAgent(render_frame, password_autofill_agent, password_generation_agent, + associated_interfaces); +} + +void ContentRendererClientQt::WebViewCreated(blink::WebView *web_view, + bool was_created_by_renderer, + const url::Origin *outermost_origin) +{ + Q_UNUSED(was_created_by_renderer); +#if BUILDFLAG(ENABLE_EXTENSIONS) + ExtensionsRendererClientQt::GetInstance()->WebViewCreated(web_view, outermost_origin); +#endif } void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame *render_frame) @@ -215,7 +231,7 @@ void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame *rend RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame); if (render_frame_observer && !render_frame_observer->isFrameDetached()) - UserResourceController::instance()->RunScriptsAtDocumentEnd(render_frame); + m_userResourceController->RunScriptsAtDocumentEnd(render_frame); #if BUILDFLAG(ENABLE_EXTENSIONS) ExtensionsRendererClientQt::GetInstance()->RunScriptsAtDocumentEnd(render_frame); @@ -231,50 +247,38 @@ void ContentRendererClientQt::RunScriptsAtDocumentIdle(content::RenderFrame *ren #endif } -bool ContentRendererClientQt::HasErrorPage(int httpStatusCode) -{ - // Use an internal error page, if we have one for the status code. - if (!error_page::LocalizedError::HasStrings(error_page::Error::kHttpErrorDomain, httpStatusCode)) { - return false; - } - - return true; -} - -bool ContentRendererClientQt::ShouldSuppressErrorPage(content::RenderFrame *frame, const GURL &) -{ - return !(frame->GetWebkitPreferences().enable_error_page); -} - // To tap into the chromium localized strings. Ripped from the chrome layer (highly simplified). void ContentRendererClientQt::PrepareErrorPage(content::RenderFrame *renderFrame, const blink::WebURLError &web_error, const std::string &httpMethod, - bool ignoring_cache, + content::mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info, std::string *errorHtml) { - Q_UNUSED(ignoring_cache); - GetNavigationErrorStringsInternal(renderFrame, httpMethod, - error_page::Error::NetError(web_error.url(), web_error.reason(), web_error.has_copy_in_cache()), - errorHtml); + GetNavigationErrorStringsInternal( + renderFrame, httpMethod, + error_page::Error::NetError((GURL)web_error.url(), web_error.reason(), web_error.extended_reason(), + net::ResolveErrorInfo(), web_error.has_copy_in_cache()), + errorHtml); } void ContentRendererClientQt::PrepareErrorPageForHttpStatusError(content::RenderFrame *renderFrame, - const GURL &unreachable_url, + const blink::WebURLError &error, const std::string &httpMethod, - bool ignoring_cache, int http_status, + content::mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info, std::string *errorHtml) { - Q_UNUSED(ignoring_cache); GetNavigationErrorStringsInternal(renderFrame, httpMethod, - error_page::Error::HttpError(unreachable_url, http_status), + error_page::Error::HttpError(error.url(), http_status), errorHtml); } -void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, const std::string &httpMethod, const error_page::Error &error, std::string *errorHtml) +void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, + const std::string &httpMethod, + const error_page::Error &error, + std::string *errorHtml) { - Q_UNUSED(renderFrame) + Q_UNUSED(renderFrame); const bool isPost = QByteArray::fromStdString(httpMethod) == QByteArrayLiteral("POST"); if (errorHtml) { @@ -285,73 +289,182 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF // TODO(elproxy): We could potentially get better diagnostics here by first calling // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle. + base::Value::Dict error_page_params; error_page::LocalizedError::PageState errorPageState = - error_page::LocalizedError::GetPageState( - error.reason(), error.domain(), error.url(), isPost, - error.stale_copy_in_cache(), false, RenderThreadObserverQt::is_incognito_process(), false, - false, locale, std::unique_ptr<error_page::ErrorPageParams>()); + error_page::LocalizedError::GetPageState( + error.reason(), error.domain(), error.url(), isPost, false, + error.stale_copy_in_cache(), false, + RenderConfiguration::is_incognito_process(), false, false, false, locale, false, &error_page_params); resourceId = IDR_NET_ERROR_HTML; - const base::StringPiece template_html(ui::ResourceBundle::GetSharedInstance().GetRawDataResource(resourceId)); + std::string extracted_string = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(resourceId); + const base::StringPiece template_html(extracted_string.data(), extracted_string.size()); if (template_html.empty()) NOTREACHED() << "unable to load template. ID: " << resourceId; else // "t" is the id of the templates root node. - *errorHtml = webui::GetTemplatesHtml(template_html, &errorPageState.strings, "t"); + *errorHtml = webui::GetTemplatesHtml(template_html, errorPageState.strings, "t"); } } uint64_t ContentRendererClientQt::VisitedLinkHash(const char *canonicalUrl, size_t length) { - return m_visitedLinkSlave->ComputeURLFingerprint(canonicalUrl, length); + return m_visitedLinkReader->ComputeURLFingerprint(canonicalUrl, length); } bool ContentRendererClientQt::IsLinkVisited(uint64_t linkHash) { - return m_visitedLinkSlave->IsVisited(linkHash); + return m_visitedLinkReader->IsVisited(linkHash); } -blink::WebPrescientNetworking *ContentRendererClientQt::GetPrescientNetworking() +std::unique_ptr<blink::WebPrescientNetworking> ContentRendererClientQt::CreatePrescientNetworking(content::RenderFrame *render_frame) { - return m_prescientNetworkingDispatcher.get(); + return std::make_unique<network_hints::WebPrescientNetworkingImpl>(render_frame); } -bool ContentRendererClientQt::OverrideCreatePlugin( - content::RenderFrame* render_frame, - const blink::WebPluginParams& params, blink::WebPlugin** plugin) +namespace { +bool IsPdfExtensionOrigin(const url::Origin &origin) { #if BUILDFLAG(ENABLE_EXTENSIONS) - if (!ExtensionsRendererClientQt::GetInstance()->OverrideCreatePlugin(render_frame, params)) - return false; -#endif //ENABLE_EXTENSIONS - return content::ContentRendererClient::OverrideCreatePlugin(render_frame, params, plugin); + return origin.scheme() == extensions::kExtensionScheme && + origin.host() == extension_misc::kPdfExtensionId; +#else + return false; +#endif } -content::BrowserPluginDelegate* ContentRendererClientQt::CreateBrowserPluginDelegate(content::RenderFrame *render_frame, - const content::WebPluginInfo &info, - const std::string &mime_type, - const GURL &original_url) +#if BUILDFLAG(ENABLE_PLUGINS) +void AppendParams(const std::vector<content::WebPluginMimeType::Param> &additional_params, + blink::WebVector<blink::WebString> *existing_names, + blink::WebVector<blink::WebString> *existing_values) { -#if BUILDFLAG(ENABLE_EXTENSIONS) - return ExtensionsRendererClientQt::GetInstance()->CreateBrowserPluginDelegate(render_frame, info, mime_type, original_url); + DCHECK(existing_names->size() == existing_values->size()); + size_t existing_size = existing_names->size(); + size_t total_size = existing_size + additional_params.size(); + + blink::WebVector<blink::WebString> names(total_size); + blink::WebVector<blink::WebString> values(total_size); + + for (size_t i = 0; i < existing_size; ++i) { + names[i] = (*existing_names)[i]; + values[i] = (*existing_values)[i]; + } + + for (size_t i = 0; i < additional_params.size(); ++i) { + names[existing_size + i] = blink::WebString::FromUTF16(additional_params[i].name); + values[existing_size + i] = blink::WebString::FromUTF16(additional_params[i].value); + } + + existing_names->Swap(names); + existing_values->Swap(values); +} +#endif // BUILDFLAG(ENABLE_PLUGINS) + +#if QT_CONFIG(webengine_printing_and_pdf) +// based on chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.cc: +class PdfInternalPluginDelegateQt final + : public pdf::PdfInternalPluginDelegate +{ +public: + PdfInternalPluginDelegateQt() = default; + PdfInternalPluginDelegateQt(const PdfInternalPluginDelegateQt &) = delete; + PdfInternalPluginDelegateQt& operator=(const PdfInternalPluginDelegateQt &) = delete; + ~PdfInternalPluginDelegateQt() override = default; + + // `pdf::PdfInternalPluginDelegate`: + bool IsAllowedOrigin(const url::Origin &origin) const override; +}; + +bool PdfInternalPluginDelegateQt::IsAllowedOrigin(const url::Origin &origin) const +{ + return IsPdfExtensionOrigin(origin); +} +#endif +} // namespace + +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; + + static_cast<content::RenderFrameImpl *>(render_frame)->GetPepperHost()->GetPluginInfo( + original_url, original_mime_type, &found, &plugin_info, &mime_type); + if (!found) + return false; + if (IsPdfExtensionOrigin(render_frame->GetWebFrame()->GetSecurityOrigin())) + return true; + 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 nullptr; + return false; #endif } -void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string& name, - mojo::ScopedMessagePipeHandle handle) +bool ContentRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_frame, + const blink::WebPluginParams ¶ms, + blink::WebPlugin **plugin) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (!ExtensionsRendererClientQt::GetInstance()->OverrideCreatePlugin(render_frame, params)) + return false; +#endif // ENABLE_EXTENSIONS + +#if BUILDFLAG(ENABLE_PLUGINS) + content::WebPluginInfo info; + std::string mime_type; + bool found = false; + + static_cast<content::RenderFrameImpl *>(render_frame)->GetPepperHost()->GetPluginInfo( + params.url, params.mime_type.Utf8(), &found, &info, &mime_type); + if (!found) { + *plugin = LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(render_frame, params)->plugin(); + return true; + } + if (info.name == u"Chromium PDF Viewer") { + blink::WebPluginParams new_params(params); + for (const auto& mime_type : info.mime_types) { + if (mime_type.mime_type == params.mime_type.Utf8()) { + AppendParams(mime_type.additional_params, &new_params.attribute_names, + &new_params.attribute_values); + break; + } + } + + *plugin = pdf::CreateInternalPlugin(std::move(new_params), render_frame, std::make_unique<PdfInternalPluginDelegateQt>()); + return true; + } + *plugin = render_frame->CreatePlugin(info, params); +#endif // BUILDFLAG(ENABLE_PLUGINS) + return true; +} + +bool ContentRendererClientQt::IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) { - Q_UNUSED(remote_info); - m_registry.TryBindInterface(name, &handle); + return plugin_path.value() == FILE_PATH_LITERAL("internal-pdf-viewer"); } +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +chrome::WebRtcLoggingAgentImpl *ContentRendererClientQt::GetWebRtcLoggingAgent() +{ + if (!m_webrtcLoggingAgentImpl) { + m_webrtcLoggingAgentImpl = std::make_unique<chrome::WebRtcLoggingAgentImpl>(); + } + + return m_webrtcLoggingAgentImpl.get(); +} +#endif // QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) { - m_serviceBinding.GetConnector()->BindInterface( - service_manager::ServiceFilter::ByName("qtwebengine"), - interface_name, std::move(interface_pipe)); + content::RenderThread::Get()->BindHostReceiver(mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe))); } // The following is based on chrome/renderer/media/chrome_key_systems.cc: @@ -361,128 +474,125 @@ void ContentRendererClientQt::GetInterface(const std::string &interface_name, mo #if BUILDFLAG(ENABLE_LIBRARY_CDMS) // External Clear Key (used for testing). -static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProperties>>* concrete_key_systems) -{ - // TODO(xhwang): Move these into an array so we can use a for loop to add - // supported key systems below. - static const char kExternalClearKeyKeySystem[] = - "org.chromium.externalclearkey"; - static const char kExternalClearKeyDecryptOnlyKeySystem[] = - "org.chromium.externalclearkey.decryptonly"; - static const char kExternalClearKeyMessageTypeTestKeySystem[] = - "org.chromium.externalclearkey.messagetypetest"; - static const char kExternalClearKeyFileIOTestKeySystem[] = - "org.chromium.externalclearkey.fileiotest"; - static const char kExternalClearKeyOutputProtectionTestKeySystem[] = - "org.chromium.externalclearkey.outputprotectiontest"; - static const char kExternalClearKeyPlatformVerificationTestKeySystem[] = - "org.chromium.externalclearkey.platformverificationtest"; - static const char kExternalClearKeyInitializeFailKeySystem[] = - "org.chromium.externalclearkey.initializefail"; - static const char kExternalClearKeyCrashKeySystem[] = - "org.chromium.externalclearkey.crash"; - static const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = - "org.chromium.externalclearkey.verifycdmhosttest"; - static const char kExternalClearKeyStorageIdTestKeySystem[] = - "org.chromium.externalclearkey.storageidtest"; - static const char kExternalClearKeyDifferentGuidTestKeySystem[] = - "org.chromium.externalclearkey.differentguid"; - static const char kExternalClearKeyCdmProxyTestKeySystem[] = - "org.chromium.externalclearkey.cdmproxytest"; - - media::mojom::KeySystemCapabilityPtr capability; - if (!content::IsKeySystemSupported(kExternalClearKeyKeySystem, &capability)) { - DVLOG(1) << "External Clear Key not supported"; +static void AddExternalClearKey(const media::mojom::KeySystemCapabilityPtr &capability, + media::KeySystemInfos* key_systems) +{ + Q_UNUSED(capability); + if (!base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) { + DLOG(ERROR) << "ExternalClearKey supported despite not enabled."; return; } - concrete_key_systems->emplace_back( - new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); - - // Add support of decrypt-only mode in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyDecryptOnlyKeySystem)); - - // A key system that triggers various types of messages in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyMessageTypeTestKeySystem)); - - // A key system that triggers the FileIO test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyFileIOTestKeySystem)); - - // A key system that triggers the output protection test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyOutputProtectionTestKeySystem)); - - // A key system that triggers the platform verification test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyPlatformVerificationTestKeySystem)); + // TODO(xhwang): Actually use `capability` to determine capabilities. + key_systems->push_back(std::make_unique<cdm::ExternalClearKeyKeySystemInfo>()); +} - // A key system that Chrome thinks is supported by ClearKeyCdm, but actually - // will be refused by ClearKeyCdm. This is to test the CDM initialization - // failure case. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyInitializeFailKeySystem)); +#if BUILDFLAG(ENABLE_WIDEVINE) +media::SupportedCodecs GetVP9Codecs(const base::flat_set<media::VideoCodecProfile> &profiles) +{ + if (profiles.empty()) { + // If no profiles are specified, then all are supported. + return media::EME_CODEC_VP9_PROFILE0 | media::EME_CODEC_VP9_PROFILE2; + } - // A key system that triggers a crash in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyCrashKeySystem)); + media::SupportedCodecs supported_vp9_codecs = media::EME_CODEC_NONE; + for (const auto& profile : profiles) { + switch (profile) { + case media::VP9PROFILE_PROFILE0: + supported_vp9_codecs |= media::EME_CODEC_VP9_PROFILE0; + break; + case media::VP9PROFILE_PROFILE2: + supported_vp9_codecs |= media::EME_CODEC_VP9_PROFILE2; + break; + default: + DVLOG(1) << "Unexpected " << media::GetCodecName(media::VideoCodec::kVP9) + << " profile: " << media::GetProfileName(profile); + break; + } + } - // A key system that triggers the verify host files test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyVerifyCdmHostTestKeySystem)); + return supported_vp9_codecs; +} - // A key system that fetches the Storage ID in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyStorageIdTestKeySystem)); +#if BUILDFLAG(ENABLE_PLATFORM_HEVC) +media::SupportedCodecs GetHevcCodecs(const base::flat_set<media::VideoCodecProfile> &profiles) +{ + // If no profiles are specified, then all are supported. + if (profiles.empty()) { + return media::EME_CODEC_HEVC_PROFILE_MAIN | + media::EME_CODEC_HEVC_PROFILE_MAIN10; + } - // A key system that is registered with a different CDM GUID. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyDifferentGuidTestKeySystem)); + media::SupportedCodecs supported_hevc_codecs = media::EME_CODEC_NONE; + for (const auto& profile : profiles) { + switch (profile) { + case media::HEVCPROFILE_MAIN: + supported_hevc_codecs |= media::EME_CODEC_HEVC_PROFILE_MAIN; + break; + case media::HEVCPROFILE_MAIN10: + supported_hevc_codecs |= media::EME_CODEC_HEVC_PROFILE_MAIN10; + break; + default: + DVLOG(1) << "Unexpected " << media::GetCodecName(media::VideoCodec::kHEVC) + << " profile: " << media::GetProfileName(profile); + break; + } + } - // A key system that triggers CDM Proxy test in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyCdmProxyTestKeySystem)); + return supported_hevc_codecs; } +#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_WIDEVINE) -static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, bool is_secure) +static media::SupportedCodecs GetSupportedCodecs(const media::CdmCapability& capability, + bool is_secure) { media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; - // Audio codecs are always supported because the CDM only does decrypt-only - // for audio. The only exception is when |is_secure| is true and there's no - // secure video decoder available, which is a signal that secure hardware - // decryption is not available either. - // TODO(sandersd): Distinguish these from those that are directly supported, - // as those may offer a higher level of protection. - if (!supported_video_codecs.empty() || !is_secure) { - supported_codecs |= media::EME_CODEC_OPUS; - supported_codecs |= media::EME_CODEC_VORBIS; - supported_codecs |= media::EME_CODEC_FLAC; + for (const auto& codec : capability.audio_codecs) { + switch (codec) { + case media::AudioCodec::kOpus: + supported_codecs |= media::EME_CODEC_OPUS; + break; + case media::AudioCodec::kVorbis: + supported_codecs |= media::EME_CODEC_VORBIS; + break; + case media::AudioCodec::kFLAC: + supported_codecs |= media::EME_CODEC_FLAC; + break; #if BUILDFLAG(USE_PROPRIETARY_CODECS) - supported_codecs |= media::EME_CODEC_AAC; + case media::AudioCodec::kAAC: + supported_codecs |= media::EME_CODEC_AAC; + break; #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + default: + DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); + break; + } } - // Video codecs are determined by what was registered for the CDM. - for (const auto &codec : supported_video_codecs) { - switch (codec) { - case media::VideoCodec::kCodecVP8: + for (const auto &codec : capability.video_codecs) { + switch (codec.first) { + case media::VideoCodec::kVP8: supported_codecs |= media::EME_CODEC_VP8; break; - case media::VideoCodec::kCodecVP9: - supported_codecs |= media::EME_CODEC_VP9_PROFILE0; - supported_codecs |= media::EME_CODEC_VP9_PROFILE2; + case media::VideoCodec::kVP9: + supported_codecs |= GetVP9Codecs(codec.second.supported_profiles); + break; + case media::VideoCodec::kAV1: + supported_codecs |= media::EME_CODEC_AV1; break; #if BUILDFLAG(USE_PROPRIETARY_CODECS) - case media::VideoCodec::kCodecH264: + case media::VideoCodec::kH264: supported_codecs |= media::EME_CODEC_AVC1; break; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(ENABLE_PLATFORM_HEVC) + case media::VideoCodec::kHEVC: + supported_codecs |= GetHevcCodecs(codec.second.supported_profiles); + break; +#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) default: - DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); + DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec.first); break; } } @@ -490,25 +600,36 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC return supported_codecs; } -static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) +static void AddWidevine(const media::mojom::KeySystemCapabilityPtr &capability, + media::KeySystemInfos *key_systems) { - media::mojom::KeySystemCapabilityPtr capability; - if (!content::IsKeySystemSupported(kWidevineKeySystem, &capability)) { - DVLOG(1) << "Widevine CDM is not currently available."; - return; + // Codecs and encryption schemes. + media::SupportedCodecs codecs = media::EME_CODEC_NONE; + media::SupportedCodecs hw_secure_codecs = media::EME_CODEC_NONE; + base::flat_set<media::EncryptionScheme> encryption_schemes; + base::flat_set<media::EncryptionScheme> hw_secure_encryption_schemes; + base::flat_set<media::CdmSessionType> session_types; + base::flat_set<media::CdmSessionType> hw_secure_session_types; + if (capability->sw_secure_capability) { + codecs = GetSupportedCodecs(capability->sw_secure_capability.value(), /*is_secure=*/false); + encryption_schemes = capability->sw_secure_capability->encryption_schemes; + if (!base::Contains(capability->sw_secure_capability->session_types, media::CdmSessionType::kTemporary)) { + DVLOG(1) << "Temporary sessions must be supported."; + return; + } } - // Codecs and encryption schemes. - auto codecs = - GetSupportedCodecs(capability->video_codecs, /*is_secure=*/false); - const auto& encryption_schemes = capability->encryption_schemes; - auto hw_secure_codecs = GetSupportedCodecs(capability->hw_secure_video_codecs, - /*is_secure=*/true); - const auto& hw_secure_encryption_schemes = - capability->hw_secure_encryption_schemes; + if (capability->hw_secure_capability) { + hw_secure_codecs = GetSupportedCodecs(capability->hw_secure_capability.value(), /*is_secure=*/true); + hw_secure_encryption_schemes = capability->hw_secure_capability->encryption_schemes; + if (!base::Contains(capability->hw_secure_capability->session_types, media::CdmSessionType::kTemporary)) { + DVLOG(1) << "Temporary sessions must be supported."; + return; + } + } // Robustness. - using Robustness = cdm::WidevineKeySystemProperties::Robustness; + using Robustness = cdm::WidevineKeySystemInfo::Robustness; auto max_audio_robustness = Robustness::SW_SECURE_CRYPTO; auto max_video_robustness = Robustness::SW_SECURE_DECODE; @@ -517,73 +638,74 @@ static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> max_video_robustness = Robustness::HW_SECURE_ALL; } - // Session types. - bool cdm_supports_temporary_session = base::ContainsValue(capability->session_types, media::CdmSessionType::kTemporary); - if (!cdm_supports_temporary_session) { - DVLOG(1) << "Temporary session must be supported."; - return; - } - - auto persistent_license_support = media::EmeSessionTypeSupport::NOT_SUPPORTED; - auto persistent_usage_record_support = media::EmeSessionTypeSupport::NOT_SUPPORTED; - // Others. auto persistent_state_support = media::EmeFeatureSupport::REQUESTABLE; auto distinctive_identifier_support = media::EmeFeatureSupport::NOT_SUPPORTED; - concrete_key_systems->emplace_back(new cdm::WidevineKeySystemProperties( - codecs, encryption_schemes, hw_secure_codecs, - hw_secure_encryption_schemes, max_audio_robustness, max_video_robustness, - persistent_license_support, persistent_usage_record_support, - persistent_state_support, distinctive_identifier_support)); + key_systems->emplace_back(new cdm::WidevineKeySystemInfo( + codecs, std::move(encryption_schemes), std::move(session_types), + hw_secure_codecs, std::move(hw_secure_encryption_schemes), + std::move(hw_secure_session_types), + max_audio_robustness, max_video_robustness, + persistent_state_support, + distinctive_identifier_support)); } #endif // BUILDFLAG(ENABLE_WIDEVINE) #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) -void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems) +void OnKeySystemSupportUpdated(media::GetSupportedKeySystemsCB cb, + content::KeySystemCapabilityPtrMap key_system_capabilities) { + media::KeySystemInfos key_systems; + for (const auto &entry : key_system_capabilities) { #if BUILDFLAG(ENABLE_LIBRARY_CDMS) - if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) - AddExternalClearKey(key_systems); - + const auto &key_system = entry.first; + const auto &capability = entry.second; #if BUILDFLAG(ENABLE_WIDEVINE) - AddWidevine(key_systems); + if (key_system == kWidevineKeySystem) { + AddWidevine(capability, &key_systems); + continue; + } #endif // BUILDFLAG(ENABLE_WIDEVINE) + if (key_system == media::kExternalClearKeyKeySystem) { + AddExternalClearKey(capability, &key_systems); + continue; + } + + DLOG(ERROR) << "Unrecognized key system: " << key_system; #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + } + + cb.Run(std::move(key_systems)); +} + +void ContentRendererClientQt::GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) +{ + content::ObserveKeySystemSupportUpdate( + base::BindRepeating(&OnKeySystemSupportUpdated, std::move(cb))); } #if QT_CONFIG(webengine_spellchecker) void ContentRendererClientQt::InitSpellCheck() { - m_spellCheck.reset(new SpellCheck(&m_registry, this)); + m_spellCheck.reset(new SpellCheck(this)); } #endif void ContentRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, const blink::WebURL &url, + const net::SiteForCookies &site_for_cookies, const url::Origin *initiator_origin, - GURL *new_url, - bool *attach_same_site_cookies) + GURL *new_url) { #if BUILDFLAG(ENABLE_EXTENSIONS) - ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, initiator_origin, new_url, attach_same_site_cookies); + ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, site_for_cookies, + initiator_origin, new_url); if (!new_url->is_empty()) return; #endif - content::ContentRendererClient::WillSendRequest(frame, transition_type, url, initiator_origin, new_url, attach_same_site_cookies); -} - -void ContentRendererClientQt::CreateRendererService(service_manager::mojom::ServiceRequest service_request) -{ - DCHECK(!m_serviceBinding.is_bound()); - m_serviceBinding.Bind(std::move(service_request)); } -service_manager::Connector* ContentRendererClientQt::GetConnector() -{ - return m_serviceBinding.GetConnector(); -} - -} // namespace +} // namespace QtWebEngineCore |