diff options
Diffstat (limited to 'src/core/renderer/content_renderer_client_qt.cpp')
-rw-r--r-- | src/core/renderer/content_renderer_client_qt.cpp | 417 |
1 files changed, 241 insertions, 176 deletions
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index db3ab5745..3eda3993a 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -40,21 +40,21 @@ #include "renderer/content_renderer_client_qt.h" #include "common/qt_messages.h" -#include "printing/features/features.h" #include "renderer/content_settings_observer_qt.h" - #include "base/strings/string_split.h" -#if BUILDFLAG(ENABLE_SPELLCHECK) +#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 "components/error_page/common/error.h" #include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#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 // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif #include "components/visitedlink/renderer/visitedlink_slave.h" #include "components/web_cache/renderer/web_cache_impl.h" #include "content/public/renderer/render_frame.h" @@ -63,27 +63,42 @@ #include "content/public/common/simple_connection_filter.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" +#include "media/base/key_system_properties.h" +#include "media/media_buildflags.h" #include "net/base/net_errors.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "services/service_manager/public/cpp/service_context.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 BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) #include "renderer/print_web_view_helper_delegate_qt.h" -#endif // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif #include "renderer/render_frame_observer_qt.h" #include "renderer/render_view_observer_qt.h" #include "renderer/user_resource_controller.h" +#if QT_CONFIG(webengine_webchannel) #include "renderer/web_channel_ipc_transport.h" +#endif #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" #include "components/grit/components_resources.h" +#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 "third_party/widevine/cdm/widevine_cdm_common.h" + #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. +#endif namespace QtWebEngineCore { @@ -100,24 +115,29 @@ ContentRendererClientQt::~ContentRendererClientQt() void ContentRendererClientQt::RenderThreadStarted() { content::RenderThread *renderThread = content::RenderThread::Get(); + (void)GetConnector(); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + 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(base::MakeUnique<content::SimpleConnectionFilter>( - std::move(registry))); - + content::ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( + std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); renderThread->AddObserver(UserResourceController::instance()); -#if BUILDFLAG(ENABLE_SPELLCHECK) - m_spellCheck.reset(new SpellCheck(this)); - renderThread->AddObserver(m_spellCheck.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::AddOriginAccessWhitelistEntry(qrc, file, blink::WebString(), true); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) @@ -130,31 +150,22 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) { new QtWebEngineCore::RenderFrameObserverQt(render_frame); +#if QT_CONFIG(webengine_webchannel) if (render_frame->IsMainFrame()) new WebChannelIPCTransport(render_frame); +#endif UserResourceController::instance()->renderFrameCreated(render_frame); new QtWebEngineCore::ContentSettingsObserverQt(render_frame); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) new SpellCheckProvider(render_frame, m_spellCheck.data(), this); #endif -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) new printing::PrintRenderFrameHelper( render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) -} - -void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* render_frame) -{ - // Check whether the render_frame has been created and has not been detached yet. - // Otherwise the WebFrame is not available. - RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame); - if (!render_frame_observer || render_frame_observer->isFrameDetached()) - return; // The frame is invisible to scripts. - - UserResourceController::instance()->RunScriptsAtDocumentStart(render_frame); +#endif // QT_CONFIG(webengine_printing_and_pdf) } void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) @@ -242,201 +253,255 @@ bool ContentRendererClientQt::IsLinkVisited(unsigned long long linkHash) return m_visitedLinkSlave->IsVisited(linkHash); } -void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) +blink::WebPrescientNetworking *ContentRendererClientQt::GetPrescientNetworking() { - content::RenderThread::Get()->GetConnector()->BindInterface(service_manager::Identity("qtwebengine"), - interface_name, - std::move(interface_pipe)); + return m_prescientNetworkingDispatcher.get(); } -// The following is based on chrome/renderer/media/chrome_key_systems.cc: -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.Chromium file. - -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) -static const char kExternalClearKeyPepperType[] = "application/x-ppapi-clearkey-cdm"; - -static bool IsPepperCdmAvailable(const std::string& pepper_type, - std::vector<content::WebPluginMimeType::Param>* additional_params) +void ContentRendererClientQt::OnStart() { - base::Optional<std::vector<content::WebPluginMimeType::Param>> opt_additional_params; - content::RenderThread::Get()->Send( - new QtWebEngineHostMsg_IsInternalPluginAvailableForMimeType( - pepper_type, - &opt_additional_params)); - - if (opt_additional_params) - *additional_params = *opt_additional_params; - - return opt_additional_params.has_value(); + context()->connector()->BindConnectorRequest(std::move(m_connectorRequest)); } -// KeySystemProperties implementation for external Clear Key systems. -class ExternalClearKeyProperties : public media::KeySystemProperties +void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceInfo &remote_info, + const std::string& name, + mojo::ScopedMessagePipeHandle handle) { -public: - explicit ExternalClearKeyProperties(const std::string& key_system_name) - : key_system_name_(key_system_name) {} - - std::string GetKeySystemName() const override { return key_system_name_; } - bool IsSupportedInitDataType(media::EmeInitDataType init_data_type) const override - { - switch (init_data_type) { - case media::EmeInitDataType::WEBM: - case media::EmeInitDataType::KEYIDS: - return true; - - case media::EmeInitDataType::CENC: -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - return true; -#else - return false; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) - - case media::EmeInitDataType::UNKNOWN: - return false; - } - NOTREACHED(); - return false; - } - - media::SupportedCodecs GetSupportedCodecs() const override - { -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - return media::EME_CODEC_MP4_ALL | media::EME_CODEC_WEBM_ALL; -#else - return media::EME_CODEC_WEBM_ALL; -#endif - } - - media::EmeConfigRule GetRobustnessConfigRule( - media::EmeMediaType media_type, - const std::string& requested_robustness) const override - { - return requested_robustness.empty() ? media::EmeConfigRule::SUPPORTED - : media::EmeConfigRule::NOT_SUPPORTED; - } - - // Persistent license sessions are faked. - media::EmeSessionTypeSupport GetPersistentLicenseSessionSupport() const override - { - return media::EmeSessionTypeSupport::SUPPORTED; - } - - media::EmeSessionTypeSupport GetPersistentReleaseMessageSessionSupport() const override { - return media::EmeSessionTypeSupport::NOT_SUPPORTED; - } - - media::EmeFeatureSupport GetPersistentStateSupport() const override - { - return media::EmeFeatureSupport::REQUESTABLE; - } - - media::EmeFeatureSupport GetDistinctiveIdentifierSupport() const override - { - return media::EmeFeatureSupport::NOT_SUPPORTED; - } + Q_UNUSED(remote_info); + m_registry.TryBindInterface(name, &handle); +} - std::string GetPepperType() const override - { - return kExternalClearKeyPepperType; - } +void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) +{ + if (!m_connector) + return; + m_connector->BindInterface(service_manager::Identity("qtwebengine"), + interface_name, + std::move(interface_pipe)); +} -private: - const std::string key_system_name_; -}; +// The following is based on chrome/renderer/media/chrome_key_systems.cc: +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. +#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"; + "org.chromium.externalclearkey"; static const char kExternalClearKeyDecryptOnlyKeySystem[] = - "org.chromium.externalclearkey.decryptonly"; + "org.chromium.externalclearkey.decryptonly"; + static const char kExternalClearKeyMessageTypeTestKeySystem[] = + "org.chromium.externalclearkey.messagetypetest"; static const char kExternalClearKeyFileIOTestKeySystem[] = - "org.chromium.externalclearkey.fileiotest"; + "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"; + "org.chromium.externalclearkey.initializefail"; static const char kExternalClearKeyCrashKeySystem[] = - "org.chromium.externalclearkey.crash"; - - std::vector<content::WebPluginMimeType::Param> additional_params; - if (!IsPepperCdmAvailable(kExternalClearKeyPepperType, &additional_params)) + "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"; return; + } concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyKeySystem)); + new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); // Add support of decrypt-only mode in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyDecryptOnlyKeySystem)); - // A key system that triggers FileIO test in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem)); + // 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)); // 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 ExternalClearKeyProperties(kExternalClearKeyInitializeFailKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyInitializeFailKeySystem)); // A key system that triggers a crash in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyCrashKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyCrashKeySystem)); + + // A key system that triggers the verify host files test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyVerifyCdmHostTestKeySystem)); + + // A key system that fetches the Storage ID in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyStorageIdTestKeySystem)); + + // A key system that is registered with a different CDM GUID. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyDifferentGuidTestKeySystem)); + + // A key system that triggers CDM Proxy test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyCdmProxyTestKeySystem)); } #if defined(WIDEVINE_CDM_AVAILABLE) +static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, 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_WEBM_OPUS; + supported_codecs |= media::EME_CODEC_WEBM_VORBIS; + supported_codecs |= media::EME_CODEC_MP4_FLAC; +#if BUILDFLAG(USE_PROPRIETARY_CODECS) + supported_codecs |= media::EME_CODEC_MP4_AAC; +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + } + + // Video codecs are determined by what was registered for the CDM. + for (const auto &codec : supported_video_codecs) { + switch (codec) { + case media::VideoCodec::kCodecVP8: + supported_codecs |= media::EME_CODEC_WEBM_VP8; + break; + case media::VideoCodec::kCodecVP9: + supported_codecs |= media::EME_CODEC_WEBM_VP9; + supported_codecs |= media::EME_CODEC_COMMON_VP9; + break; +#if BUILDFLAG(USE_PROPRIETARY_CODECS) + case media::VideoCodec::kCodecH264: + supported_codecs |= media::EME_CODEC_MP4_AVC1; + break; +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + default: + DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); + break; + } + } -static void AddPepperBasedWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) + return supported_codecs; +} + +static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) { -//#if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) -// Version glibc_version(gnu_get_libc_version()); -// DCHECK(glibc_version.IsValid()); -// if (glibc_version.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION)) -// return; -//#endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) - - std::vector<content::WebPluginMimeType::Param> additional_params; - if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType, &additional_params)) { + media::mojom::KeySystemCapabilityPtr capability; + if (!content::IsKeySystemSupported(kWidevineKeySystem, &capability)) { DVLOG(1) << "Widevine CDM is not currently available."; return; } media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; - supported_codecs |= media::EME_CODEC_WEBM_OPUS; - supported_codecs |= media::EME_CODEC_WEBM_VORBIS; - supported_codecs |= media::EME_CODEC_WEBM_VP8; - supported_codecs |= media::EME_CODEC_WEBM_VP9; -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - supported_codecs |= media::EME_CODEC_MP4_AVC1; - supported_codecs |= media::EME_CODEC_MP4_AAC; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + // 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; + // Robustness. using Robustness = cdm::WidevineKeySystemProperties::Robustness; + auto max_audio_robustness = Robustness::SW_SECURE_CRYPTO; + auto max_video_robustness = Robustness::SW_SECURE_DECODE; + + if (base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) { + max_audio_robustness = Robustness::HW_SECURE_CRYPTO; + 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; + } + + bool cdm_supports_persistent_license = + base::ContainsValue(capability->session_types, media::CdmSessionType::kPersistentLicense); + 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( - supported_codecs, - Robustness::SW_SECURE_CRYPTO, // Maximum audio robustness. - Robustness::SW_SECURE_DECODE, // Maximum video robustness. - media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-license. - media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-release-message. - media::EmeFeatureSupport::REQUESTABLE, // Persistent state. - media::EmeFeatureSupport::NOT_SUPPORTED)); // Distinctive identifier. + 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)); } -#endif // defined(WIDEVINE_CDM_AVAILABLE) -#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) +#endif // defined(WIDEVINE_CDM_AVAILABLE) +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems) { #if BUILDFLAG(ENABLE_LIBRARY_CDMS) - AddExternalClearKey(key_systems); + if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) + AddExternalClearKey(key_systems); #if defined(WIDEVINE_CDM_AVAILABLE) - AddPepperBasedWidevine(key_systems); -#endif // defined(WIDEVINE_CDM_AVAILABLE) -#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) + AddWidevine(key_systems); +#endif // defined(WIDEVINE_CDM_AVAILABLE) + +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) +} + +#if QT_CONFIG(webengine_spellchecker) +void ContentRendererClientQt::InitSpellCheck() +{ + m_spellCheck.reset(new SpellCheck(&m_registry, this)); +} +#endif + +void ContentRendererClientQt::CreateRendererService(service_manager::mojom::ServiceRequest service_request) +{ + m_serviceContext = std::make_unique<service_manager::ServiceContext>( + std::make_unique<service_manager::ForwardingService>(this), + std::move(service_request)); +} + +service_manager::Connector* ContentRendererClientQt::GetConnector() +{ + if (!m_connector) + m_connector = service_manager::Connector::Create(&m_connectorRequest); + return m_connector.get(); } } // namespace |