diff options
Diffstat (limited to 'src/core')
95 files changed, 3785 insertions, 2951 deletions
diff --git a/src/core/api/qwebenginenotification.cpp b/src/core/api/qwebenginenotification.cpp index abc63fed2..0505b825a 100644 --- a/src/core/api/qwebenginenotification.cpp +++ b/src/core/api/qwebenginenotification.cpp @@ -132,7 +132,7 @@ bool QWebEngineNotification::matches(const QWebEngineNotification *other) const } /*! - \qmlproperty bool WebEngineNotification::title + \qmlproperty string WebEngineNotification::title \brief The title of the notification. */ /*! diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index 75b6e3a81..69033cdfd 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -46,6 +46,7 @@ #include <QtCore/qurl.h> namespace QtWebEngineCore { +class InterceptedRequest; class NetworkDelegateQt; class URLRequestNotification; } // namespace QtWebEngineCore @@ -110,6 +111,7 @@ public: private: friend class QtWebEngineCore::NetworkDelegateQt; friend class QtWebEngineCore::URLRequestNotification; + friend class QtWebEngineCore::InterceptedRequest; Q_DISABLE_COPY(QWebEngineUrlRequestInfo) Q_DECLARE_PRIVATE(QWebEngineUrlRequestInfo) diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index c760dcd45..816a46041 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -148,6 +148,19 @@ QAccessibleInterface *BrowserAccessibilityQt::child(int index) const return static_cast<BrowserAccessibilityQt*>(BrowserAccessibility::PlatformGetChild(index)); } +QAccessibleInterface *BrowserAccessibilityQt::focusChild() const +{ + if (state().focused) + return const_cast<BrowserAccessibilityQt *>(this); + + for (int i = 0; i < childCount(); ++i) { + if (QAccessibleInterface *iface = child(i)->focusChild()) + return iface; + } + + return nullptr; +} + int BrowserAccessibilityQt::childCount() const { return PlatformChildCount(); @@ -479,7 +492,7 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ax::mojom::Role::kTabList: return QAccessible::PageTabList; case ax::mojom::Role::kTabPanel: - return QAccessible::PageTab; + return QAccessible::Pane; case ax::mojom::Role::kTerm: return QAccessible::StaticText; case ax::mojom::Role::kTextField: diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index decfc1e9d..4acac6aa7 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -68,6 +68,7 @@ public: // navigation, hierarchy QAccessibleInterface *parent() const override; QAccessibleInterface *child(int index) const override; + QAccessibleInterface *focusChild() const override; int childCount() const override; int indexOfChild(const QAccessibleInterface *) const override; diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp index 5d999ab92..494c7b4d4 100644 --- a/src/core/compositor/display_overrides.cpp +++ b/src/core/compositor/display_overrides.cpp @@ -42,12 +42,17 @@ #include "components/viz/service/display_embedder/output_surface_provider_impl.h" #include "gpu/ipc/in_process_command_buffer.h" +#include <qtgui-config.h> std::unique_ptr<viz::OutputSurface> viz::OutputSurfaceProviderImpl::CreateGLOutputSurface( scoped_refptr<VizProcessContextProvider> context_provider) { +#if QT_CONFIG(opengl) return std::make_unique<QtWebEngineCore::DisplayGLOutputSurface>(std::move(context_provider)); +#else + return nullptr; +#endif // QT_CONFIG(opengl) } std::unique_ptr<viz::OutputSurface> diff --git a/src/core/configure.json b/src/core/configure.json index b33b10fda..9f05409ba 100644 --- a/src/core/configure.json +++ b/src/core/configure.json @@ -6,7 +6,7 @@ "gui-private", "printsupport" ], - "condition": "features.build-qtwebengine-core && features.webengine-core-support", + "condition": "module.gui && features.build-qtwebengine-core && features.webengine-core-support", "testDir": "../../config.tests", "commandline": { "options": { diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 29b6e09ed..baa08fa7e 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -41,14 +41,18 @@ #include "base/memory/ptr_util.h" #include "base/optional.h" +#include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "base/message_loop/message_loop.h" #include "base/task/post_task.h" #include "base/threading/thread_restrictions.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" #endif +#include "components/navigation_interception/intercept_navigation_throttle.h" +#include "components/navigation_interception/navigation_params.h" #include "components/guest_view/browser/guest_view_base.h" #include "components/network_hints/browser/network_hints_message_filter.h" #include "content/browser/renderer_host/render_view_host_delegate.h" @@ -58,6 +62,7 @@ #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/media_observer.h" +#include "content/public/browser/network_service_instance.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" @@ -66,14 +71,18 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" +#include "content/public/browser/web_ui_url_loader_factory.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" #include "content/public/common/url_constants.h" +#include "content/public/common/url_loader_throttle.h" #include "content/public/common/user_agent.h" #include "media/media_buildflags.h" #include "extensions/buildflags/buildflags.h" +#include "extensions/browser/extension_protocols.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/remote.h" @@ -84,6 +93,8 @@ #include "qtwebengine/browser/qtwebengine_renderer_manifest.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_store.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/features.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/sandbox/switches.h" @@ -109,8 +120,12 @@ #include "devtools_manager_delegate_qt.h" #include "login_delegate_qt.h" #include "media_capture_devices_dispatcher.h" -#include "net/network_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" +#include "net/cookie_monster_delegate_qt.h" +#include "net/custom_url_loader_factory.h" +#include "net/proxying_restricted_cookie_manager_qt.h" +#include "net/proxying_url_loader_factory_qt.h" +#include "net/qrc_url_scheme_handler.h" +#include "net/system_network_context_manager.h" #include "platform_notification_service_qt.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "printing/printing_message_filter_qt.h" @@ -121,6 +136,7 @@ #include "renderer_host/user_resource_controller_host.h" #include "service/service_qt.h" #include "type_conversion.h" +#include "web_contents_adapter_client.h" #include "web_contents_delegate_qt.h" #include "web_engine_context.h" #include "web_engine_library_info.h" @@ -143,13 +159,16 @@ #endif #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "extensions/extensions_browser_client_qt.h" +#include "content/public/browser/file_url_loader.h" #include "extensions/browser/extension_message_filter.h" #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h" #include "extensions/browser/io_thread_extension_message_filter.h" #include "extensions/common/constants.h" + #include "common/extensions/extensions_client_qt.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.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" #endif #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) @@ -159,6 +178,7 @@ #include <QGuiApplication> #include <QLocale> +#include <QStandardPaths> #if QT_CONFIG(opengl) # include <QOpenGLContext> # include <QOpenGLExtraFunctions> @@ -276,22 +296,26 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* { const int id = host->GetID(); Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())), - base::BindOnce(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id)); + + host->AddFilter(new network_hints::NetworkHintsMessageFilter(id)); + + // Allow requesting custom schemes. + const auto policy = content::ChildProcessSecurityPolicy::GetInstance(); + const auto profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + policy->GrantRequestScheme(id, scheme.toStdString()); // FIXME: Add a settings variable to enable/disable the file scheme. - content::ChildProcessSecurityPolicy::GetInstance()->GrantRequestScheme(id, url::kFileScheme); - static_cast<ProfileQt*>(host->GetBrowserContext())->m_profileAdapter->userResourceController()->renderProcessStartedWithHost(host); + policy->GrantRequestScheme(id, url::kFileScheme); + profileAdapter->userResourceController()->renderProcessStartedWithHost(host); host->AddFilter(new BrowserMessageFilterQt(id, profile)); #if QT_CONFIG(webengine_printing_and_pdf) - host->AddFilter(new PrintingMessageFilterQt(host->GetID())); + host->AddFilter(new PrintingMessageFilterQt(id)); #endif #if BUILDFLAG(ENABLE_EXTENSIONS) - host->AddFilter(new extensions::ExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::IOThreadExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(host->GetID(), host->GetBrowserContext())); + host->AddFilter(new extensions::ExtensionMessageFilter(id, profile)); + host->AddFilter(new extensions::IOThreadExtensionMessageFilter(id, profile)); + host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS bool is_incognito_process = profile->IsOffTheRecord(); @@ -313,11 +337,7 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* void ContentBrowserClientQt::ResourceDispatcherHostCreated() { -#if BUILDFLAG(ENABLE_EXTENSIONS) - m_resourceDispatcherHostDelegate.reset(new ResourceDispatcherHostDelegateQt); -#else m_resourceDispatcherHostDelegate.reset(new content::ResourceDispatcherHostDelegate); -#endif content::ResourceDispatcherHost::Get()->SetDelegate(m_resourceDispatcherHostDelegate.get()); } @@ -459,12 +479,20 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) { + ContentBrowserClient::GetAdditionalWebUISchemes(additional_schemes); additional_schemes->push_back(content::kChromeDevToolsScheme); } void ContentBrowserClientQt::GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) { - additional_schemes->push_back(content::kChromeDevToolsScheme); + ContentBrowserClient::GetAdditionalViewSourceSchemes(additional_schemes); +} + +void ContentBrowserClientQt::GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) +{ + ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(additional_schemes); + additional_schemes->push_back(content::kChromeDevToolsScheme); + additional_schemes->push_back(content::kChromeUIScheme); } #if defined(Q_OS_LINUX) @@ -659,19 +687,6 @@ std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystem } #endif -void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - content::RenderProcessHost* host = content::RenderProcessHost::FromID(render_process_id); - if (!host) - return; - - content::BrowserMessageFilter *network_hints_message_filter = - new network_hints::NetworkHintsMessageFilter(render_process_id); - host->AddFilter(network_hints_message_filter); -} - bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() { // mirroring AwContentBrowserClient, CastContentBrowserClient and @@ -687,13 +702,17 @@ bool ContentBrowserClientQt::WillCreateRestrictedCookieManager(network::mojom::R int routing_id, network::mojom::RestrictedCookieManagerRequest *request) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::CreateRestrictedCookieManager, - ProfileIODataQt::FromBrowserContext(browser_context)->getWeakPtrOnUIThread(), - std::move(*request), - role, origin, is_service_worker, process_id, routing_id)); - return true; + network::mojom::RestrictedCookieManagerRequest orig_request = std::move(*request); + network::mojom::RestrictedCookieManagerPtrInfo target_rcm_info; + *request = mojo::MakeRequest(&target_rcm_info); + + ProxyingRestrictedCookieManagerQt::CreateAndBind( + ProfileIODataQt::FromBrowserContext(browser_context), + std::move(target_rcm_info), + is_service_worker, process_id, routing_id, + std::move(orig_request)); + + return false; // only made a proxy, still need the actual impl to be made. } bool ContentBrowserClientQt::AllowAppCacheOnIO(const GURL &manifest_url, @@ -751,6 +770,14 @@ static void LaunchURL(const GURL& url, content::WebContents* webContents = web_contents_getter.Run(); if (!webContents) return; + + ProtocolHandlerRegistry* protocolHandlerRegistry = + ProtocolHandlerRegistryFactory::GetForBrowserContext( + webContents->GetBrowserContext()); + if (protocolHandlerRegistry && + protocolHandlerRegistry->IsHandledProtocol(url.scheme())) + return; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } @@ -766,7 +793,7 @@ bool ContentBrowserClientQt::HandleExternalProtocol( bool has_user_gesture, network::mojom::URLLoaderFactoryPtr *out_factory) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); +// Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_UNUSED(child_id); Q_UNUSED(navigation_data); Q_UNUSED(out_factory); @@ -822,30 +849,126 @@ private: std::vector<std::unique_ptr<content::URLLoaderThrottle>> ContentBrowserClientQt::CreateURLLoaderThrottlesOnIO( - const network::ResourceRequest & /*request*/, content::ResourceContext *resource_context, + const network::ResourceRequest &request, content::ResourceContext *resource_context, const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, - content::NavigationUIData * /*navigation_ui_data*/, int /*frame_tree_node_id*/) + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) { std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; ProfileIODataQt *ioData = ProfileIODataQt::FromResourceContext(resource_context); result.push_back(std::make_unique<ProtocolHandlerThrottle< scoped_refptr<ProtocolHandlerRegistry::IOThreadDelegate>>>( - ioData->protocolHandlerRegistryIOThreadDelegate())); + ioData->protocolHandlerRegistryIOThreadDelegate())); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + resource_context, request.resource_type, frame_tree_node_id)); +#endif return result; } std::vector<std::unique_ptr<content::URLLoaderThrottle>> ContentBrowserClientQt::CreateURLLoaderThrottles( const network::ResourceRequest &request, content::BrowserContext *browser_context, - const base::RepeatingCallback<content::WebContents *()> &wc_getter, - content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) + const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) { std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; result.push_back(std::make_unique<ProtocolHandlerThrottle<ProtocolHandlerRegistry *>>( - ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); + ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + browser_context, request.resource_type, frame_tree_node_id)); +#endif return result; } +WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) +{ + if (ui::PageTransitionIsRedirect(transition)) + return WebContentsAdapterClient::RedirectNavigation; + + int32_t qualifier = ui::PageTransitionGetQualifier(transition); + + if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) + return WebContentsAdapterClient::BackForwardNavigation; + + ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); + + switch (strippedTransition) { + case ui::PAGE_TRANSITION_LINK: + return WebContentsAdapterClient::LinkNavigation; + case ui::PAGE_TRANSITION_TYPED: + return WebContentsAdapterClient::TypedNavigation; + case ui::PAGE_TRANSITION_FORM_SUBMIT: + return WebContentsAdapterClient::FormSubmittedNavigation; + case ui::PAGE_TRANSITION_RELOAD: + return WebContentsAdapterClient::ReloadNavigation; + default: + return WebContentsAdapterClient::OtherNavigation; + } +} + +static bool navigationThrottleCallback(content::WebContents *source, + const navigation_interception::NavigationParams ¶ms) +{ + // We call navigationRequested later in launchExternalUrl for external protocols. + // The is_external_protocol parameter here is not fully accurate though, + // and doesn't know about profile specific custom URL schemes. + ProfileQt *profile = static_cast<ProfileQt *>(source->GetBrowserContext()); + if (params.is_external_protocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(params.url().scheme()))) + return false; + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(source->GetDelegate()); + WebContentsAdapterClient *client = delegate->adapterClient(); + client->navigationRequested(pageTransitionToNavigationType(params.transition_type()), + toQt(params.url()), + navigationRequestAction, + params.is_main_frame()); + return navigationRequestAction == static_cast<int>(WebContentsAdapterClient::IgnoreRequest); +} + +std::vector<std::unique_ptr<content::NavigationThrottle>> ContentBrowserClientQt::CreateThrottlesForNavigation( + content::NavigationHandle *navigation_handle) +{ + std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; + throttles.push_back(std::make_unique<navigation_interception::InterceptNavigationThrottle>( + navigation_handle, + base::BindRepeating(&navigationThrottleCallback), + navigation_interception::SynchronyMode::kSync)); + return throttles; +} + +bool ContentBrowserClientQt::IsHandledURL(const GURL &url) +{ + static const char *const kProtocolList[] = { + url::kFileScheme, + content::kChromeDevToolsScheme, +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::kExtensionScheme, +#endif + content::kChromeUIScheme, + url::kDataScheme, + url::kAboutScheme, +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kFtpScheme, +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kBlobScheme, + url::kFileSystemScheme, + url::kQrcScheme, + }; + + // We don't check url.IsCustom() here because we don't + // know if the registered protocol is installed in the + // profile that will be used to load the URL. + + const std::string scheme = url.scheme(); + + for (const char *protocol : kProtocolList) { + if (scheme == protocol) + return true; + } + return net::URLRequest::IsHandledProtocol(scheme); +} + std::unique_ptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegate( const net::AuthChallengeInfo &authInfo, content::WebContents *web_contents, @@ -875,6 +998,16 @@ bool ContentBrowserClientQt::ShouldUseProcessPerSite(content::BrowserContext* br return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url); } +bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserOrResourceContext browser_or_resource_context, + const GURL &effective_site_url) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (effective_site_url.SchemeIs(extensions::kExtensionScheme)) + return true; +#endif + return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_or_resource_context, effective_site_url); +} + std::string ContentBrowserClientQt::getUserAgent() { // Mention the Chromium version we're based on to get passed stupid UA-string-based feature detection (several WebRTC demos need this) @@ -887,4 +1020,194 @@ std::string ContentBrowserClientQt::GetProduct() return productName.toStdString(); } +scoped_refptr<network::SharedURLLoaderFactory> ContentBrowserClientQt::GetSystemSharedURLLoaderFactory() +{ + if (!SystemNetworkContextManager::GetInstance()) + return nullptr; + return SystemNetworkContextManager::GetInstance()->GetSharedURLLoaderFactory(); +} + +network::mojom::NetworkContext *ContentBrowserClientQt::GetSystemNetworkContext() +{ + if (!SystemNetworkContextManager::GetInstance()) + return nullptr; + return SystemNetworkContextManager::GetInstance()->GetContext(); +} + +void ContentBrowserClientQt::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + + if (!SystemNetworkContextManager::GetInstance()) + SystemNetworkContextManager::CreateInstance(); + + // Need to set up global NetworkService state before anything else uses it. + SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(network_service); +} + +network::mojom::NetworkContextPtr ContentBrowserClientQt::CreateNetworkContext(content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return nullptr; + + network::mojom::NetworkContextPtr network_context; + // ### do we need to pass in_memory and relative_partition_path to ProfileIODataQt::CreateNetworkContextParams() ? + network::mojom::NetworkContextParamsPtr context_params = ProfileIODataQt::FromBrowserContext(context)->CreateNetworkContextParams(); + content::GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context), std::move(context_params)); + + network::mojom::CookieManagerPtrInfo cookie_manager_info; + network_context->GetCookieManager(mojo::MakeRequest(&cookie_manager_info)); + ProfileIODataQt::FromBrowserContext(context)->cookieDelegate()->setMojoCookieManager(std::move(cookie_manager_info)); + + return network_context; +} + +std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDirectory() +{ + return { + toFilePath(QStandardPaths::writableLocation(QStandardPaths::DataLocation)), + toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) }; +} + +void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, + NonNetworkURLLoaderFactoryMap *factories) +{ + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); + Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionNavigationURLLoaderFactory(profile, + !!extensions::WebViewGuest::FromWebContents(web_contents))); +#endif +} + +#if BUILDFLAG(ENABLE_EXTENSIONS) +namespace { +// The FileURLLoaderFactory provided to the extension background pages. +// Checks with the ChildProcessSecurityPolicy to validate the file access. +class FileURLLoaderFactory : public network::mojom::URLLoaderFactory +{ +public: + explicit FileURLLoaderFactory(int child_id) : child_id_(child_id) {} + +private: + // network::mojom::URLLoaderFactory: + void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest& request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override + { + if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(child_id_, request.url)) { + client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED)); + return; + } + content::CreateFileURLLoader(request, std::move(loader), std::move(client), + /* observer */ nullptr, + /* allow_directory_listing */ false); + } + + void Clone(network::mojom::URLLoaderFactoryRequest loader) override + { + bindings_.AddBinding(this, std::move(loader)); + } + + int child_id_; + mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; + DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory); +}; +} // namespace +#endif + +void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, + NonNetworkURLLoaderFactoryMap *factories) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + content::RenderProcessHost *process_host = content::RenderProcessHost::FromID(render_process_id); + Profile *profile = Profile::FromBrowserContext(process_host->GetBrowserContext()); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id, render_frame_id); + if (factory) + factories->emplace(extensions::kExtensionScheme, std::move(factory)); + + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) + return; + + extensions::ExtensionWebContentsObserverQt *web_observer = + extensions::ExtensionWebContentsObserverQt::FromWebContents(web_contents); + if (!web_observer) + return; + + const extensions::Extension *extension = web_observer->GetExtensionFromFrame(frame_host, false); + if (!extension) + return; + + std::vector<std::string> allowed_webui_hosts; + // Support for chrome:// scheme if appropriate. + if ((extension->is_extension() || extension->is_platform_app()) && + extensions::Manifest::IsComponentLocation(extension->location())) { + // Components of chrome that are implemented as extensions or platform apps + // are allowed to use chrome://resources/ and chrome://theme/ URLs. + allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost); + } + if (!allowed_webui_hosts.empty()) { + factories->emplace(content::kChromeUIScheme, + content::CreateWebUIURLLoader(frame_host, + content::kChromeUIScheme, + std::move(allowed_webui_hosts))); + } + // Support for file:// scheme when approved by ChildProcessSecurityPolicy. + // FIXME: Not needed after switching to using transferable url loaders and guest views. + factories->emplace(url::kFileScheme, std::make_unique<FileURLLoaderFactory>(render_process_id)); +#endif +} + +bool ContentBrowserClientQt::WillCreateURLLoaderFactory( + content::BrowserContext *browser_context, + content::RenderFrameHost *frame, + int render_process_id, + bool is_navigation, + bool is_download, + const url::Origin &request_initiator, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, + network::mojom::TrustedURLLoaderHeaderClientPtrInfo *header_client, + bool *bypass_redirect_checks) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return false; + + auto proxied_receiver = std::move(*factory_receiver); + network::mojom::URLLoaderFactoryPtrInfo target_factory_info; + *factory_receiver = mojo::MakeRequest(&target_factory_info); + int process_id = is_navigation ? 0 : render_process_id; + + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProxyingURLLoaderFactoryQt::CreateProxy, process_id, + browser_context->GetResourceContext(), + std::move(proxied_receiver), + std::move(target_factory_info))); + return true; +} + } // namespace QtWebEngineCore diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index f5b03a8d9..cd48d6fe5 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -116,6 +116,7 @@ public: void GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) override; void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) override; + void GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) override; void BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, const std::string& interface_name, @@ -177,6 +178,8 @@ public: #endif bool ShouldIsolateErrorPage(bool in_main_frame) override; bool ShouldUseProcessPerSite(content::BrowserContext* browser_context, const GURL& effective_url) override; + bool DoesSiteRequireDedicatedProcess(content::BrowserOrResourceContext browser_or_resource_contexts, + const GURL &effective_site_url) override; #if defined(Q_OS_LINUX) void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) override; @@ -216,6 +219,31 @@ public: const base::RepeatingCallback<content::WebContents *()> &wc_getter, content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) override; + std::vector<std::unique_ptr<content::NavigationThrottle>> CreateThrottlesForNavigation( + content::NavigationHandle *navigation_handle) override; + + bool IsHandledURL(const GURL &url) override; + + bool WillCreateURLLoaderFactory(content::BrowserContext *browser_context, + content::RenderFrameHost *frame, + int render_process_id, + bool is_navigation, + bool is_download, + const url::Origin &request_initiator, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, + network::mojom::TrustedURLLoaderHeaderClientPtrInfo *header_client, + bool *bypass_redirect_checks) override; + scoped_refptr<network::SharedURLLoaderFactory> GetSystemSharedURLLoaderFactory() override; + network::mojom::NetworkContext *GetSystemNetworkContext() override; + void OnNetworkServiceCreated(network::mojom::NetworkService *network_service) override; + network::mojom::NetworkContextPtr CreateNetworkContext(content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path) override; + std::vector<base::FilePath> GetNetworkContextsParentDirectory() override; + void RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, NonNetworkURLLoaderFactoryMap *factories) override; + void RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, + NonNetworkURLLoaderFactoryMap* factories) override; + static std::string getUserAgent(); std::string GetUserAgent() override { return getUserAgent(); } @@ -223,7 +251,6 @@ public: private: void InitFrameInterfaces(); - void AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context); std::unique_ptr<content::ResourceDispatcherHostDelegate> m_resourceDispatcherHostDelegate; scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 554ee3e12..22f3f548f 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -129,7 +129,8 @@ static QString getLocalAppDataDir() static const int32_t kPepperFlashPermissions = ppapi::PERMISSION_DEV | ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_BYPASS_USER_GESTURE | - ppapi::PERMISSION_FLASH; + ppapi::PERMISSION_FLASH | + ppapi::PERMISSION_SOCKET; namespace switches { const char kPpapiFlashPath[] = "ppapi-flash-path"; @@ -286,11 +287,11 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) - QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Versions"); + QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - const QString library = QLatin1String("/Google Chrome Framework.framework/Versions/A/Libraries/" + const QString library = QLatin1String("/Versions/Current/Libraries/" "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"); for (const QFileInfo &info : widevineVersionDirs) pluginPaths << info.absoluteFilePath() + library; @@ -320,7 +321,12 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, } } #elif defined(Q_OS_LINUX) - pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdm.so") // Google Chrome + pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdm.so") // Old Google Chrome +#if Q_PROCESSOR_WORDSIZE == 8 + << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") +#else + << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") +#endif << QStringLiteral("/usr/lib/chromium/libwidevinecdm.so") // Arch << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdm.so") // Ubuntu/neon << QStringLiteral("/usr/lib64/chromium/libwidevinecdm.so"); // OpenSUSE style diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index 9eab15456..d317bf625 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -82,17 +82,16 @@ SOURCES = \ net/client_cert_override.cpp \ net/client_cert_store_data.cpp \ net/cookie_monster_delegate_qt.cpp \ - net/custom_protocol_handler.cpp \ - net/network_delegate_qt.cpp \ + net/custom_url_loader_factory.cpp \ + net/proxy_config_monitor.cpp \ net/proxy_config_service_qt.cpp \ + net/proxying_url_loader_factory_qt.cpp \ + net/proxying_restricted_cookie_manager_qt.cpp \ net/qrc_url_scheme_handler.cpp \ - net/restricted_cookie_manager_qt.cpp \ net/ssl_host_state_delegate_qt.cpp \ - net/url_request_context_getter_qt.cpp \ - net/url_request_custom_job.cpp \ + net/system_network_context_manager.cpp \ net/url_request_custom_job_delegate.cpp \ net/url_request_custom_job_proxy.cpp \ - net/url_request_notification.cpp \ net/webui_controller_factory_qt.cpp \ ozone/gl_context_qt.cpp \ ozone/gl_ozone_egl_qt.cpp \ @@ -193,16 +192,14 @@ HEADERS = \ net/client_cert_override.h \ net/client_cert_store_data.h \ net/cookie_monster_delegate_qt.h \ - net/custom_protocol_handler.h \ - net/network_delegate_qt.h \ + net/custom_url_loader_factory.h \ + net/proxying_url_loader_factory_qt.h \ + net/proxying_restricted_cookie_manager_qt.h \ net/qrc_url_scheme_handler.h \ - net/restricted_cookie_manager_qt.h \ net/ssl_host_state_delegate_qt.h \ - net/url_request_context_getter_qt.h \ - net/url_request_custom_job.h \ + net/system_network_context_manager.h \ net/url_request_custom_job_delegate.h \ net/url_request_custom_job_proxy.h \ - net/url_request_notification.h \ net/webui_controller_factory_qt.h \ ozone/gl_context_qt.h \ ozone/gl_ozone_egl_qt.h \ @@ -219,6 +216,7 @@ HEADERS = \ profile_adapter_client.h \ profile_qt.h \ profile_io_data_qt.h \ + proxy_config_monitor.h \ proxy_config_service_qt.h \ quota_permission_context_qt.h \ quota_request_controller.h \ @@ -339,11 +337,11 @@ qtConfig(webengine-extensions) { extensions/extensions_browser_api_provider_qt.cpp \ extensions/extensions_browser_client_qt.cpp \ extensions/mime_handler_view_guest_delegate_qt.cpp \ + net/plugin_response_interceptor_url_loader_throttle.cpp \ renderer/extensions/extensions_dispatcher_delegate_qt.cpp \ renderer/extensions/extensions_renderer_client_qt.cpp \ renderer/extensions/renderer_permissions_policy_delegate_qt.cpp \ - renderer/extensions/resource_request_policy_qt.cpp \ - renderer_host/resource_dispatcher_host_delegate_qt.cpp + renderer/extensions/resource_request_policy_qt.cpp HEADERS += \ common/extensions/extensions_api_provider_qt.h \ @@ -356,9 +354,9 @@ qtConfig(webengine-extensions) { extensions/extensions_browser_api_provider_qt.h \ extensions/extensions_browser_client_qt.h \ extensions/mime_handler_view_guest_delegate_qt.h \ + net/plugin_response_interceptor_url_loader_throttle.h \ renderer/extensions/extensions_dispatcher_delegate_qt.h \ renderer/extensions/extensions_renderer_client_qt.h \ renderer/extensions/renderer_permissions_policy_delegate_qt.h \ - renderer/extensions/resource_request_policy_qt.h \ - renderer_host/resource_dispatcher_host_delegate_qt.h + renderer/extensions/resource_request_policy_qt.h } diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 34e290317..7049b8273 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -298,7 +298,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content ProfileAdapterClient::NoReason, adapterClient, QFileInfo(suggestedFilePath).fileName(), - time_t(QDateTime::currentMSecsSinceEpoch()) + QDateTime::currentMSecsSinceEpoch() }; for (ProfileAdapterClient *client : qAsConst(clients)) { diff --git a/src/core/extensions/extension_web_contents_observer_qt.cpp b/src/core/extensions/extension_web_contents_observer_qt.cpp index 365f04e46..5b1514bb4 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.cpp +++ b/src/core/extensions/extension_web_contents_observer_qt.cpp @@ -70,42 +70,6 @@ void ExtensionWebContentsObserverQt::CreateForWebContents(content::WebContents * FromWebContents(web_contents)->Initialize(); } -std::string ExtensionWebContentsObserverQt::GetExtensionIdFromFrame(content::RenderFrameHost *render_frame_host) const -{ - const GURL &site = render_frame_host->GetSiteInstance()->GetSiteURL(); - if (!site.SchemeIs(kExtensionScheme)) - return std::string(); - - return site.host(); -} - -const Extension *ExtensionWebContentsObserverQt::GetExtensionFromFrame(content::RenderFrameHost *render_frame_host, bool verify_url) const -{ - std::string extension_id = GetExtensionIdFromFrame(render_frame_host); - if (extension_id.empty()) - return nullptr; - - content::BrowserContext *browser_context = - render_frame_host->GetProcess()->GetBrowserContext(); - const Extension *extension = ExtensionRegistry::Get(browser_context) - ->enabled_extensions() - .GetByID(extension_id); - if (!extension) - return nullptr; - - if (verify_url) { - const url::Origin &origin(render_frame_host->GetLastCommittedOrigin()); - // Without site isolation, this check is needed to eliminate non-extension - // schemes. With site isolation, this is still needed to exclude sandboxed - // extension frames with a unique origin. - const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL()); - if (origin.opaque() || site_url != content::SiteInstance::GetSiteForURL(browser_context, origin.GetURL())) - return nullptr; - } - - return extension; -} - void ExtensionWebContentsObserverQt::RenderFrameCreated(content::RenderFrameHost *render_frame_host) { ExtensionWebContentsObserver::RenderFrameCreated(render_frame_host); diff --git a/src/core/extensions/extension_web_contents_observer_qt.h b/src/core/extensions/extension_web_contents_observer_qt.h index a528b3856..658966b31 100644 --- a/src/core/extensions/extension_web_contents_observer_qt.h +++ b/src/core/extensions/extension_web_contents_observer_qt.h @@ -59,9 +59,6 @@ public: static void CreateForWebContents(content::WebContents *web_contents); - std::string GetExtensionIdFromFrame(content::RenderFrameHost *) const; - const Extension *GetExtensionFromFrame(content::RenderFrameHost *, bool) const; - // content::WebContentsObserver overrides. void RenderFrameCreated(content::RenderFrameHost *render_frame_host) override; diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp index 59c15d2f5..d974155c5 100644 --- a/src/core/extensions/extensions_browser_client_qt.cpp +++ b/src/core/extensions/extensions_browser_client_qt.cpp @@ -66,10 +66,12 @@ #include "extensions/browser/mojo/interface_registration.h" #include "extensions/browser/url_request_util.h" #include "extensions/common/file_util.h" +#include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/completion_once_callback.h" #include "net/base/mime_util.h" #include "net/url_request/url_request_simple_job.h" #include "services/network/public/mojom/url_loader.mojom.h" +#include "third_party/zlib/google/compression_utils.h" #include "ui/base/resource/resource_bundle.h" #include "component_extension_resource_manager_qt.h" @@ -165,6 +167,163 @@ private: mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_; }; +scoped_refptr<base::RefCountedMemory> GetResource(int resource_id, const std::string &extension_id) +{ + const ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance(); + scoped_refptr<base::RefCountedMemory> bytes = rb.LoadDataResourceBytes(resource_id); + auto *replacements = extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager() + ? extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager()->GetTemplateReplacementsForExtension( + extension_id) + : nullptr; + + bool is_gzipped = rb.IsGzipped(resource_id); + if (!bytes->size() || (!replacements && !is_gzipped)) { + return bytes; + } + + base::StringPiece input(reinterpret_cast<const char *>(bytes->front()), bytes->size()); + + std::string temp_str; + + base::StringPiece source = input; + if (is_gzipped) { + temp_str.resize(compression::GetUncompressedSize(input)); + source = temp_str; + CHECK(compression::GzipUncompress(input, source)); + } + + if (replacements) { + temp_str = ui::ReplaceTemplateExpressions(source, *replacements); + } + + DCHECK(!temp_str.empty()); + + return base::RefCountedString::TakeString(&temp_str); +} + +// Loads an extension resource in a Chrome .pak file. These are used by +// component extensions. +class ResourceBundleFileLoader : public network::mojom::URLLoader +{ +public: + static void CreateAndStart(const network::ResourceRequest &request, network::mojom::URLLoaderRequest loader, + network::mojom::URLLoaderClientPtrInfo client_info, const base::FilePath &filename, + int resource_id, const std::string &content_security_policy, bool send_cors_header) + { + // Owns itself. Will live as long as its URLLoader and URLLoaderClientPtr + // bindings are alive - essentially until either the client gives up or all + // file data has been sent to it. + auto *bundle_loader = new ResourceBundleFileLoader(content_security_policy, send_cors_header); + bundle_loader->Start(request, std::move(loader), std::move(client_info), filename, resource_id); + } + + // mojom::URLLoader implementation: + void FollowRedirect(const std::vector<std::string> &removed_headers, + const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override + { + NOTREACHED() << "No redirects for local file loads."; + } + // Current implementation reads all resource data at start of resource + // load, so priority, and pausing is not currently implemented. + void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override {} + void PauseReadingBodyFromNet() override {} + void ResumeReadingBodyFromNet() override {} + void ProceedWithResponse() override {} + +private: + ResourceBundleFileLoader(const std::string &content_security_policy, bool send_cors_header) : binding_(this) + { + response_headers_ = extensions::BuildHttpHeaders(content_security_policy, send_cors_header, base::Time()); + } + ~ResourceBundleFileLoader() override = default; + + void Start(const network::ResourceRequest &request, network::mojom::URLLoaderRequest loader, + network::mojom::URLLoaderClientPtrInfo client_info, const base::FilePath &filename, int resource_id) + { + client_.Bind(std::move(client_info)); + binding_.Bind(std::move(loader)); + binding_.set_connection_error_handler( + base::BindOnce(&ResourceBundleFileLoader::OnBindingError, base::Unretained(this))); + client_.set_connection_error_handler( + base::BindOnce(&ResourceBundleFileLoader::OnConnectionError, base::Unretained(this))); + auto data = GetResource(resource_id, request.url.host()); + + std::string *read_mime_type = new std::string; + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, { base::MayBlock() }, + base::BindOnce(&net::GetMimeTypeFromFile, filename, base::Unretained(read_mime_type)), + base::BindOnce(&ResourceBundleFileLoader::OnMimeTypeRead, weak_factory_.GetWeakPtr(), std::move(data), + base::Owned(read_mime_type))); + } + + void OnMimeTypeRead(scoped_refptr<base::RefCountedMemory> data, std::string *read_mime_type, bool read_result) + { + network::ResourceResponseHead head; + head.request_start = base::TimeTicks::Now(); + head.response_start = base::TimeTicks::Now(); + head.content_length = data->size(); + head.mime_type = *read_mime_type; + DetermineCharset(head.mime_type, data.get(), &head.charset); + mojo::DataPipe pipe(data->size()); + if (!pipe.consumer_handle.is_valid()) { + client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED)); + client_.reset(); + MaybeDeleteSelf(); + return; + } + head.headers = response_headers_; + head.headers->AddHeader(base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentLength, + base::NumberToString(head.content_length).c_str())); + if (!head.mime_type.empty()) { + head.headers->AddHeader( + base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType, head.mime_type.c_str())); + } + client_->OnReceiveResponse(head); + client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle)); + + uint32_t write_size = data->size(); + MojoResult result = pipe.producer_handle->WriteData(data->front(), &write_size, MOJO_WRITE_DATA_FLAG_NONE); + OnFileWritten(result); + } + + void OnConnectionError() + { + client_.reset(); + MaybeDeleteSelf(); + } + + void OnBindingError() + { + binding_.Close(); + MaybeDeleteSelf(); + } + + void MaybeDeleteSelf() + { + if (!binding_.is_bound() && !client_.is_bound()) + delete this; + } + + void OnFileWritten(MojoResult result) + { + // All the data has been written now. The consumer will be notified that + // there will be no more data to read from now. + if (result == MOJO_RESULT_OK) + client_->OnComplete(network::URLLoaderCompletionStatus(net::OK)); + else + client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED)); + client_.reset(); + MaybeDeleteSelf(); + } + + mojo::Binding<network::mojom::URLLoader> binding_; + network::mojom::URLLoaderClientPtr client_; + scoped_refptr<net::HttpResponseHeaders> response_headers_; + base::WeakPtrFactory<ResourceBundleFileLoader> weak_factory_{ this }; + + DISALLOW_COPY_AND_ASSIGN(ResourceBundleFileLoader); +}; + } // namespace namespace extensions { @@ -307,7 +466,8 @@ void ExtensionsBrowserClientQt::LoadResourceFromResourceBundle(const network::Re network::mojom::URLLoaderClientPtr client, bool send_cors_header) { - NOTIMPLEMENTED(); + ResourceBundleFileLoader::CreateAndStart(request, std::move(loader), client.PassInterface(), resource_relative_path, + resource_id, content_security_policy, send_cors_header); } diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 63b93c502..62e02e126 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -46,10 +46,11 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/file_select_listener.h" -#include <QFileInfo> #include <QDir> -#include <QVariant> +#include <QFileInfo> +#include <QMimeDatabase> #include <QStringList> +#include <QVariant> namespace QtWebEngineCore { @@ -165,4 +166,54 @@ QString FilePickerController::defaultFileName() const return m_defaultFileName; } +QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTypes) +{ + QStringList nameFilters; + QStringList acceptedGlobs; + QMimeDatabase mimeDatabase; + + if (acceptedMimeTypes.isEmpty()) + return nameFilters; + + for (QString type : acceptedMimeTypes) { + if (type.startsWith(".")) { + // A single suffix + // Filename.type doesn't have to exist and mimeTypeForFile() supports + // custom suffixes as valid (but unknown) MIME types. + const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename" + type); + if (mimeType.isValid()) { + QString glob = "*" + type; + acceptedGlobs.append(glob); + nameFilters.append(mimeType.comment() + " (" + glob + ")"); + } + } else if (type.contains("/") && !type.endsWith("*")) { + // All suffixes for a given MIME type + const QMimeType &mimeType = mimeDatabase.mimeTypeForName(type); + if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) { + QString globs = mimeType.globPatterns().join(" "); + acceptedGlobs.append(globs); + nameFilters.append(mimeType.comment() + " (" + globs + ")"); + } + } else if (type.endsWith("/*")) { + // All MIME types for audio/*, image/* or video/* + // as separate filters as Chrome does + static const QList<QMimeType> &allMimeTypes = mimeDatabase.allMimeTypes(); + type = type.remove("/*"); + for (const QMimeType &m : allMimeTypes) { + if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { + QString globs = m.globPatterns().join(" "); + acceptedGlobs.append(globs); + nameFilters.append(m.comment() + " (" + globs + ")"); + } + } + } else { + NOTREACHED(); + } + } + + nameFilters.prepend(QObject::tr("Accepted types") + " (" + acceptedGlobs.join(" ") + ")"); + + return nameFilters; +} + } // namespace diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h index dc8c0eddf..0b680161a 100644 --- a/src/core/file_picker_controller.h +++ b/src/core/file_picker_controller.h @@ -80,6 +80,8 @@ public: QString defaultFileName() const; FileChooserMode mode() const; + static QStringList nameFilters(const QStringList &acceptedMimeTypes); + public Q_SLOTS: void accepted(const QStringList &files); void accepted(const QVariant &files); diff --git a/src/core/find_text_helper.cpp b/src/core/find_text_helper.cpp index 065fed38f..da9d7f352 100644 --- a/src/core/find_text_helper.cpp +++ b/src/core/find_text_helper.cpp @@ -108,6 +108,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, // waiting for it forever. // Assume that any unfinished find has been unsuccessful when a new one is started // to cover that case. + m_lastCompletedFindRequestId = m_currentFindRequestId; m_viewClient->findTextFinished(QWebEngineFindTextResult()); invokeResultCallback(m_currentFindRequestId, 0); } diff --git a/src/core/login_delegate_qt.cpp b/src/core/login_delegate_qt.cpp index f63252112..80e2d9102 100644 --- a/src/core/login_delegate_qt.cpp +++ b/src/core/login_delegate_qt.cpp @@ -51,6 +51,8 @@ #include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/resource_request_info.h" #include "extensions/buildflags/buildflags.h" +#include "services/network/public/cpp/features.h" + #if BUILDFLAG(ENABLE_EXTENSIONS) #include "extensions/browser/info_map.h" #include "extensions/common/extension.h" @@ -153,7 +155,9 @@ void LoginDelegateQt::sendAuthToRequester(bool success, const QString &user, con std::move(m_auth_required_callback).Run(base::nullopt); } - destroy(); + // With network service the auth callback has already deleted us. + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + destroy(); } void LoginDelegateQt::destroy() diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index c94ff7eee..7bf499917 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -126,7 +126,7 @@ content::DesktopMediaID getDefaultScreenId() // // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread -#if QT_CONFIG(webengine_webrtc) && !defined(USE_X11) +#if QT_CONFIG(webengine_webrtc) && !defined(WEBRTC_USE_X11) // Source id patterns are different across platforms. // On Linux, the hardcoded value "0" is used. // On Windows, the screens are enumerated consecutively in increasing order from 0. diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index dad9a8db5..dba79b4db 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -44,7 +44,9 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "mojo/public/cpp/bindings/binding.h" #include "net/cookies/cookie_util.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" #include "api/qwebenginecookiestore.h" #include "api/qwebenginecookiestore_p.h" @@ -52,6 +54,25 @@ namespace QtWebEngineCore { +class CookieChangeListener : public network::mojom::CookieChangeListener +{ +public: + CookieChangeListener(CookieMonsterDelegateQt *delegate) : m_delegate(delegate) { } + ~CookieChangeListener() override = default; + + // network::mojom::CookieChangeListener: + void OnCookieChange(const net::CanonicalCookie &canonical_cookie, + network::mojom::CookieChangeCause cause) override + { + m_delegate->OnCookieChanged(canonical_cookie, net::CookieChangeCause(cause)); + } + +private: + CookieMonsterDelegateQt *m_delegate; + + DISALLOW_COPY_AND_ASSIGN(CookieChangeListener); +}; + static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); @@ -60,7 +81,8 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) CookieMonsterDelegateQt::CookieMonsterDelegateQt() : m_client(0) - , m_cookieMonster(nullptr) + , m_listener(new CookieChangeListener(this)) + , m_binding(m_listener.get()) { } @@ -81,22 +103,12 @@ void CookieMonsterDelegateQt::AddStore(net::CookieStore *store) bool CookieMonsterDelegateQt::hasCookieMonster() { - return m_cookieMonster; + return m_mojoCookieManager.is_bound(); } void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread, this, callbackId); - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); -} - -void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback) -{ - if (m_cookieMonster) - m_cookieMonster->GetAllCookiesAsync(std::move(callback)); + m_mojoCookieManager->GetAllCookies(base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId)); } void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) @@ -105,24 +117,16 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie Q_ASSERT(m_client); net::CookieStore::SetCookiesCallback callback; - if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnIOThread, this, callbackId); GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); + std::string cookie_line = cookie.toRawForm().toStdString(); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, - gurl, cookie.toRawForm().toStdString(), std::move(callback))); -} - -void CookieMonsterDelegateQt::SetCookieOnIOThread(const GURL &url, const std::string &cookie_line, - net::CookieMonster::SetCookiesCallback callback) -{ + if (callbackId != CallbackDirectory::NoCallbackId) + callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId); net::CookieOptions options; options.set_include_httponly(); - - if (m_cookieMonster) - m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback)); + auto canonCookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), options); + m_mojoCookieManager->SetCanonicalCookie(*canonCookie.get(), gurl.scheme(), options, std::move(callback)); } void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) @@ -131,53 +135,23 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q Q_ASSERT(m_client); GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, - gurl, cookie.name().toStdString())); -} - -void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name) -{ - if (m_cookieMonster) { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetCookiesToDeleteCallback, this, cookie_name); - m_cookieMonster->GetAllCookiesForURLAsync(url, std::move(callback)); - } -} - -void CookieMonsterDelegateQt::GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList) -{ - Q_UNUSED(statusList); - if (!m_cookieMonster) - return; - - net::CookieList cookiesToDelete; - for (auto cookie : cookies) { - if (cookie.Name() == cookie_name) - cookiesToDelete.push_back(cookie); - } - for (auto cookie : cookiesToDelete) - m_cookieMonster->DeleteCanonicalCookieAsync(cookie, base::DoNothing()); + std::string cookie_name = cookie.name().toStdString(); + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->url = gurl; + filter->cookie_name = cookie_name; + m_mojoCookieManager->DeleteCookies(std::move(filter), network::mojom::CookieManager::DeleteCookiesCallback()); } - void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) { Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); -} - -void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - if (m_cookieMonster) - m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->session_control = network::mojom::CookieDeletionSessionControl::SESSION_COOKIES; + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) @@ -185,36 +159,30 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); -} - -void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - if (m_cookieMonster) - m_cookieMonster->DeleteAllAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } -void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster *monster) +void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info) { - if (monster == m_cookieMonster) - return; - - m_subscriptions.clear(); - if (monster) - AddStore(monster); +// DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + m_mojoCookieManager.Bind(std::move(cookie_manager_info)); - m_cookieMonster = monster; + network::mojom::CookieChangeListenerPtr listener_ptr; + m_binding.Bind(mojo::MakeRequest(&listener_ptr)); - if (!m_client) - return; + m_mojoCookieManager->AddGlobalChangeListener(std::move(listener_ptr)); - if (monster) + if (m_client) m_client->d_func()->processPendingUserCookies(); - else - m_client->d_func()->rejectPendingUserCookies(); +} + +void CookieMonsterDelegateQt::unsetMojoCookieManager() +{ + m_binding.Close(); + m_mojoCookieManager.reset(); } void CookieMonsterDelegateQt::setClient(QWebEngineCookieStore *client) @@ -253,32 +221,17 @@ void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie &cookie m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieChangeCause::INSERTED); } -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, const net::CookieStatusList &statusList) +void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); QByteArray rawCookies; for (auto &&cookie : cookies) rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId, rawCookies)); -} - -void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status) -{ - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, status)); -} - -void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies) -{ - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies)); + GetAllCookiesResultOnUIThread(callbackId, rawCookies); } -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies) +void CookieMonsterDelegateQt::GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies) { if (m_client) m_client->d_func()->onGetAllCallbackResult(callbackId, cookies); diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h index 23b803790..f7ebe38c2 100644 --- a/src/core/net/cookie_monster_delegate_qt.h +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -57,8 +57,22 @@ QT_WARNING_PUSH // For some reason adding -Wno-unused-parameter to QMAKE_CXXFLAGS has no // effect with clang, so use a pragma for these dirty chromium headers QT_WARNING_DISABLE_CLANG("-Wunused-parameter") + +// We need to work around Chromium using 'signals' as a variable name in headers: +#ifdef signals +#define StAsH_signals signals +#undef signals +#endif #include "base/memory/ref_counted.h" -#include "net/cookies/cookie_monster.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "net/cookies/cookie_change_dispatcher.h" +#include "net/cookies/cookie_store.h" +#include "services/network/public/mojom/cookie_manager.mojom-forward.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" +#ifdef StAsH_signals +#define signals StAsH_signals +#undef StAsH_signals +#endif QT_WARNING_POP #include <QNetworkCookie> @@ -68,18 +82,16 @@ QT_FORWARD_DECLARE_CLASS(QWebEngineCookieStore) namespace QtWebEngineCore { -// Extends net::CookieMonster::kDefaultCookieableSchemes with qrc, without enabling -// cookies for the file:// scheme, which is disabled by default in Chromium. -// Since qrc:// is similar to file:// and there are some unknowns about how -// to correctly handle file:// cookies, qrc:// should only be used for testing. -static const char *const kCookieableSchemes[] = { "http", "https", "qrc", "ws", "wss" }; +class CookieMonsterDelegateQtPrivate; class Q_WEBENGINECORE_PRIVATE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { QPointer<QWebEngineCookieStore> m_client; - net::CookieMonster *m_cookieMonster; std::vector<std::unique_ptr<net::CookieChangeSubscription>> m_subscriptions; + network::mojom::CookieManagerPtr m_mojoCookieManager; + std::unique_ptr<network::mojom::CookieChangeListener> m_listener; + mojo::Binding<network::mojom::CookieChangeListener> m_binding; public: CookieMonsterDelegateQt(); ~CookieMonsterDelegateQt(); @@ -92,8 +104,9 @@ public: void deleteSessionCookies(quint64 callbackId); void deleteAllCookies(quint64 callbackId); - void setCookieMonster(net::CookieMonster *monster); void setClient(QWebEngineCookieStore *client); + void setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info); + void unsetMojoCookieManager(); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; @@ -102,21 +115,8 @@ public: void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause); private: - void GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback); - void SetCookieOnIOThread(const GURL &url, const std::string &cookie_line, - net::CookieMonster::SetCookiesCallback callback); - void DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name); - void DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback); - void DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback); - - void GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); - void DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies); - - void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies); + void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies); + void GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies); void SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); void DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies); }; diff --git a/src/core/net/custom_protocol_handler.cpp b/src/core/net/custom_protocol_handler.cpp deleted file mode 100644 index 7e8ee47ab..000000000 --- a/src/core/net/custom_protocol_handler.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "custom_protocol_handler.h" -#include "url_request_custom_job.h" - -#include "net/base/net_errors.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_error_job.h" - -namespace QtWebEngineCore { - -CustomProtocolHandler::CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter) - : m_profileAdapter(profileAdapter) -{ -} - -net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const -{ - if (!networkDelegate) - return new net::URLRequestErrorJob(request, nullptr, net::ERR_ACCESS_DENIED); - - return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_profileAdapter); -} - -} // namespace diff --git a/src/core/net/custom_protocol_handler.h b/src/core/net/custom_protocol_handler.h deleted file mode 100644 index 625afc1d5..000000000 --- a/src/core/net/custom_protocol_handler.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef CUSTOM_PROTOCOL_HANDLER_H_ -#define CUSTOM_PROTOCOL_HANDLER_H_ - -#include "qtwebenginecoreglobal_p.h" -#include "net/url_request/url_request_job_factory.h" - -#include <QtCore/QByteArray> -#include <QtCore/QObject> -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace net { -class NetworkDelegate; -class URLRequestJob; -} // namespace - -namespace QtWebEngineCore { - -class ProfileAdapter; - -// Implements a ProtocolHandler for custom URL schemes. -// If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. -class Q_WEBENGINECORE_PRIVATE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler -{ - -public: - CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter); - - net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; - -private: - DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - QPointer<ProfileAdapter> m_profileAdapter; -}; - -} // namespace - -#endif // CUSTOM_PROTOCOL_HANDLER_H_ diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp new file mode 100644 index 000000000..555eccf42 --- /dev/null +++ b/src/core/net/custom_url_loader_factory.cpp @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "custom_url_loader_factory.h" + +#include "base/strings/stringprintf.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "mojo/public/cpp/system/simple_watcher.h" +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" +#include "net/http/http_util.h" +#include "services/network/public/mojom/url_loader.mojom.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" + +#include "api/qwebengineurlscheme.h" +#include "net/url_request_custom_job_proxy.h" +#include "profile_adapter.h" +#include "type_conversion.h" + +#include <QtCore/qbytearray.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qiodevice.h> +#include <QtCore/qmimedatabase.h> +#include <QtCore/qmimedata.h> +#include <QtCore/qurl.h> + +namespace QtWebEngineCore { + +namespace { + +class CustomURLLoader : public network::mojom::URLLoader + , private URLRequestCustomJobProxy::Client +{ +public: + static void CreateAndStart(const network::ResourceRequest &request, + network::mojom::URLLoaderRequest loader, + network::mojom::URLLoaderClientPtrInfo client_info, + QPointer<ProfileAdapter> profileAdapter) + { + // CustomURLLoader will handle its own life-cycle, and delete when + // the client lets go. + auto *customUrlLoader = new CustomURLLoader(request, std::move(loader), std::move(client_info), profileAdapter); + customUrlLoader->Start(); + } + + // network::mojom::URLLoader: + void FollowRedirect(const std::vector<std::string> &removed_headers, + const net::HttpRequestHeaders &modified_headers, + const base::Optional<GURL> &new_url) override + { + // We can be asked for follow our own redirect + scoped_refptr<URLRequestCustomJobProxy> proxy = new URLRequestCustomJobProxy(this, m_proxy->m_scheme, m_proxy->m_profileAdapter); + m_proxy->m_client = nullptr; +// m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + m_proxy = std::move(proxy); + if (new_url) + m_request.url = *new_url; + else + m_request.url = m_redirect; + m_redirect = GURL(); + for (const std::string &header: removed_headers) + m_request.headers.RemoveHeader(header); + m_request.headers.MergeFrom(modified_headers); + Start(); + } + void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override { } + void PauseReadingBodyFromNet() override { } + void ResumeReadingBodyFromNet() override { } + void ProceedWithResponse() override { } + +private: + CustomURLLoader(const network::ResourceRequest &request, + network::mojom::URLLoaderRequest loader, + network::mojom::URLLoaderClientPtrInfo client_info, + QPointer<ProfileAdapter> profileAdapter) + // ### We can opt to run the url-loader on the UI thread instead + : m_taskRunner(base::CreateSingleThreadTaskRunner({ content::BrowserThread::IO })) + , m_proxy(new URLRequestCustomJobProxy(this, request.url.scheme(), profileAdapter)) + , m_binding(this, std::move(loader)) + , m_client(std::move(client_info)) + , m_request(request) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_binding.set_connection_error_handler( + base::BindOnce(&CustomURLLoader::OnConnectionError, m_weakPtrFactory.GetWeakPtr())); + m_firstBytePosition = 0; + m_device = nullptr; + m_error = 0; + QWebEngineUrlScheme scheme = QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(request.url.scheme())); + m_corsEnabled = scheme.flags().testFlag(QWebEngineUrlScheme::CorsEnabled); + } + + ~CustomURLLoader() override = default; + + void Start() + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_head.request_start = base::TimeTicks::Now(); + + if (!m_pipe.consumer_handle.is_valid()) + return CompleteWithFailure(net::ERR_FAILED); + + std::map<std::string, std::string> headers; + net::HttpRequestHeaders::Iterator it(m_request.headers); + while (it.GetNext()) + headers.emplace(it.name(), it.value()); + if (!m_request.referrer.is_empty()) + headers.emplace("Referer", m_request.referrer.spec()); + + std::string rangeHeader; + if (m_request.headers.GetHeader(net::HttpRequestHeaders::kRange, &rangeHeader)) { + std::vector<net::HttpByteRange> ranges; + if (net::HttpUtil::ParseRangeHeader(rangeHeader, &ranges)) { + // Chromium doesn't support multiple range requests in one single URL request. + if (ranges.size() == 1) + m_firstBytePosition = ranges[0].first_byte_position(); + } + } + +// m_taskRunner->PostTask(FROM_HERE, + base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy, + m_request.url, m_request.method, m_request.request_initiator, std::move(headers))); + } + + void CompleteWithFailure(net::Error net_error) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_client->OnComplete(network::URLLoaderCompletionStatus(net_error)); + ClearProxyAndClient(false); + } + + void OnConnectionError() + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_binding.Close(); + if (m_client.is_bound()) + ClearProxyAndClient(false); + else + delete this; + } + + void OnTransferComplete(MojoResult result) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + if (result == MOJO_RESULT_OK) { + network::URLLoaderCompletionStatus status(net::OK); + status.encoded_data_length = m_totalBytesRead + m_head.headers->raw_headers().length(); + status.encoded_body_length = m_totalBytesRead; + status.decoded_body_length = m_totalBytesRead; + m_client->OnComplete(status); + } else { + m_client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED)); + } + ClearProxyAndClient(false /* result == MOJO_RESULT_OK */); + } + + void ClearProxyAndClient(bool wait_for_loader_error = false) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_proxy->m_client = nullptr; + m_client.reset(); + if (m_device && m_device->isOpen()) + m_device->close(); + m_device = nullptr; +// m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + if (!wait_for_loader_error || !m_binding.is_bound()) + delete this; + } + + // URLRequestCustomJobProxy::Client: + void notifyExpectedContentSize(qint64 size) override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_head.content_length = size; + } + void notifyHeadersComplete() override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + DCHECK(!m_error); + m_head.response_start = base::TimeTicks::Now(); + + std::string headers; + if (!m_redirect.is_empty()) { + headers += "HTTP/1.1 303 See Other\n"; + headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); + } else { + headers += "HTTP/1.1 200 OK\n"; + if (m_mimeType.size() > 0) { + headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); + if (m_charset.size() > 0) + headers += base::StringPrintf("; charset=%s", m_charset.c_str()); + headers += "\n"; + } + } + if (m_corsEnabled) { + std::string origin; + if (m_request.headers.GetHeader("Origin", &origin)) { + headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str()); + headers += "Access-Control-Allow-Credentials: true\n"; + } + } + m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head.encoded_data_length = m_head.headers->raw_headers().length(); + + if (!m_redirect.is_empty()) { + m_head.content_length = m_head.encoded_body_length = -1; + net::URLRequest::FirstPartyURLPolicy first_party_url_policy = + m_request.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT + : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; + net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( + m_request.method, m_request.url, + m_request.site_for_cookies, m_request.top_frame_origin, + first_party_url_policy, m_request.referrer_policy, + m_request.referrer.spec(), net::HTTP_SEE_OTHER, + m_redirect, base::nullopt, false /*insecure_scheme_was_upgraded*/); + m_client->OnReceiveRedirect(redirectInfo, m_head); + // ### should m_request be updated with RedirectInfo? (see FollowRedirect) + return; + } + DCHECK(m_device); + m_head.mime_type = m_mimeType; + m_head.charset = m_charset; + m_client->OnReceiveResponse(m_head); + m_client->OnStartLoadingResponseBody(std::move(m_pipe.consumer_handle)); + + readAvailableData(); + if (m_device) { + m_watcher = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC, m_taskRunner); + m_watcher->Watch(m_pipe.producer_handle.get(), MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, + base::BindRepeating(&CustomURLLoader::notifyReadyWrite, + m_weakPtrFactory.GetWeakPtr())); + } + } + void notifyCanceled() override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + OnTransferComplete(MOJO_RESULT_CANCELLED); + } + void notifyAborted() override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + notifyStartFailure(net::ERR_ABORTED); + } + void notifyStartFailure(int error) override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_head.response_start = base::TimeTicks::Now(); + std::string headers; + switch (error) { + case net::ERR_INVALID_URL: + headers = "HTTP/1.1 400 Bad Request\n"; + break; + case net::ERR_FILE_NOT_FOUND: + headers = "HTTP/1.1 404 Not Found\n"; + break; + case net::ERR_ABORTED: + headers = "HTTP/1.1 503 Request Aborted\n"; + break; + case net::ERR_ACCESS_DENIED: + headers = "HTTP/1.1 403 Forbidden\n"; + break; + case net::ERR_FAILED: + headers = "HTTP/1.1 400 Request Failed\n"; + break; + default: + headers = "HTTP/1.1 500 Internal Error\n"; + break; + } + m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head.encoded_data_length = m_head.headers->raw_headers().length(); + m_head.content_length = m_head.encoded_body_length = -1; + m_client->OnReceiveResponse(m_head); + CompleteWithFailure(net::Error(error)); + } + void notifyReadyRead() override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + readAvailableData(); + } + void notifyReadyWrite(MojoResult result, const mojo::HandleSignalsState &state) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + if (result != MOJO_RESULT_OK) { + CompleteWithFailure(net::ERR_FAILED); + return; + } + readAvailableData(); + } + void readAvailableData() + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + for (;;) { + if (m_error || !m_device) + break; + + void *buffer = nullptr; + uint32_t bufferSize = 0; + MojoResult beginResult = m_pipe.producer_handle->BeginWriteData( + &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE); + if (beginResult == MOJO_RESULT_SHOULD_WAIT) + return; // Wait for pipe watcher + if (beginResult != MOJO_RESULT_OK) + break; + + int readResult = m_device->read(static_cast<char *>(buffer), bufferSize); + uint32_t bytesRead = std::max(readResult, 0); + m_pipe.producer_handle->EndWriteData(bytesRead); + m_totalBytesRead += bytesRead; + m_client->OnTransferSizeUpdated(m_totalBytesRead); + + if (m_device->atEnd()) { + OnTransferComplete(MOJO_RESULT_OK); + return; + } + + if (readResult == 0) + return; // Wait for readyRead + if (readResult < 0) + break; + } + + CompleteWithFailure(m_error ? net::Error(m_error) : net::ERR_FAILED); + } + base::TaskRunner *taskRunner() override + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + return m_taskRunner.get(); + } + + scoped_refptr<base::SequencedTaskRunner> m_taskRunner; + scoped_refptr<URLRequestCustomJobProxy> m_proxy; + + mojo::Binding<network::mojom::URLLoader> m_binding; + network::mojom::URLLoaderClientPtr m_client; + mojo::DataPipe m_pipe; + std::unique_ptr<mojo::SimpleWatcher> m_watcher; + + network::ResourceRequest m_request; + network::ResourceResponseHead m_head; + qint64 m_totalBytesRead = 0; + bool m_corsEnabled; + + base::WeakPtrFactory<CustomURLLoader> m_weakPtrFactory{this}; + + DISALLOW_COPY_AND_ASSIGN(CustomURLLoader); +}; + +class CustomURLLoaderFactory : public network::mojom::URLLoaderFactory { +public: + CustomURLLoaderFactory(ProfileAdapter *profileAdapter) + : m_taskRunner(base::CreateSequencedTaskRunner({ content::BrowserThread::IO })) + , m_profileAdapter(profileAdapter) + { + } + ~CustomURLLoaderFactory() override = default; + + // network::mojom::URLLoaderFactory: + void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest &request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override + { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + Q_UNUSED(routing_id); + Q_UNUSED(request_id); + Q_UNUSED(options); + Q_UNUSED(traffic_annotation); + + m_taskRunner->PostTask(FROM_HERE, + base::BindOnce(&CustomURLLoader::CreateAndStart, request, + std::move(loader), client.PassInterface(), + m_profileAdapter)); + + } + + void Clone(network::mojom::URLLoaderFactoryRequest request) override + { + m_bindings.AddBinding(this, std::move(request)); + } + + const scoped_refptr<base::SequencedTaskRunner> m_taskRunner; + mojo::BindingSet<network::mojom::URLLoaderFactory> m_bindings; + QPointer<ProfileAdapter> m_profileAdapter; + DISALLOW_COPY_AND_ASSIGN(CustomURLLoaderFactory); +}; + +} // namespace + +std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter) +{ + return std::make_unique<CustomURLLoaderFactory>(profileAdapter); +} + +} // namespace QtWebEngineCore + diff --git a/src/core/net/url_request_context_getter_qt.h b/src/core/net/custom_url_loader_factory.h index a6ef6eae0..58adf4b79 100644 --- a/src/core/net/url_request_context_getter_qt.h +++ b/src/core/net/custom_url_loader_factory.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,27 +37,33 @@ ** ****************************************************************************/ -#ifndef URL_REQUEST_CONTEXT_GETTER_QT_H -#define URL_REQUEST_CONTEXT_GETTER_QT_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -#include "net/url_request/url_request_context_getter.h" +#ifndef CUSTOM_URL_LOADER_FACTORY_H_ +#define CUSTOM_URL_LOADER_FACTORY_H_ -namespace QtWebEngineCore { +#include <memory> -class ProfileIODataQt; +namespace network { +namespace mojom { +class URLLoaderFactory; +} // namespace mojom +} // namespace network -class URLRequestContextGetterQt : public net::URLRequestContextGetter -{ -public: - URLRequestContextGetterQt(ProfileIODataQt *data); - net::URLRequestContext *GetURLRequestContext() override; - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; +namespace QtWebEngineCore { +class ProfileAdapter; -private: - virtual ~URLRequestContextGetterQt(); - ProfileIODataQt *m_profileIOData; -}; +std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter); } // namespace QtWebEngineCore -#endif // URL_REQUEST_CONTEXT_GETTER_QT_H +#endif // CUSTOM_URL_LOADER_FACTORY_H_ diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp deleted file mode 100644 index 7d3801ffe..000000000 --- a/src/core/net/network_delegate_qt.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "network_delegate_qt.h" - -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_request_info.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_request.h" -#include "ui/base/page_transition_types.h" - -#include "profile_adapter.h" -#include "cookie_monster_delegate_qt.h" -#include "profile_io_data_qt.h" -#include "qwebengineurlrequestinfo.h" -#include "qwebengineurlrequestinfo_p.h" -#include "qwebengineurlrequestinterceptor.h" -#include "type_conversion.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" -#include "url_request_notification.h" - -namespace QtWebEngineCore { - -WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) -{ - if (ui::PageTransitionIsRedirect(transition)) - return WebContentsAdapterClient::RedirectNavigation; - - int32_t qualifier = ui::PageTransitionGetQualifier(transition); - - if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) - return WebContentsAdapterClient::BackForwardNavigation; - - ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); - - switch (strippedTransition) { - case ui::PAGE_TRANSITION_LINK: - return WebContentsAdapterClient::LinkNavigation; - case ui::PAGE_TRANSITION_TYPED: - return WebContentsAdapterClient::TypedNavigation; - case ui::PAGE_TRANSITION_FORM_SUBMIT: - return WebContentsAdapterClient::FormSubmittedNavigation; - case ui::PAGE_TRANSITION_RELOAD: - return WebContentsAdapterClient::ReloadNavigation; - default: - return WebContentsAdapterClient::OtherNavigation; - } -} - -static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) -{ - if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) - return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); - return QWebEngineUrlRequestInfo::ResourceTypeUnknown; -} - -static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) -{ - return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); -} - -NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *newUrl) -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_profileIOData); - content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); - - content::ResourceType resourceType = content::ResourceType::kMaxValue; - WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; - - if (resourceInfo) { - resourceType = resourceInfo->GetResourceType(); - navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); - } - - const QUrl qUrl = toQt(request->url()); - - QUrl firstPartyUrl = QUrl(); - if (resourceType == content::ResourceType::kSubFrame) - firstPartyUrl = toQt(request->first_party_url()); - else - firstPartyUrl = toQt(request->site_for_cookies()); - - const QUrl initiator = request->initiator().has_value() ? toQt(request->initiator()->GetURL()) : QUrl(); - - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), - toQt(navigationType), - qUrl, - firstPartyUrl, - initiator, - QByteArray::fromStdString(request->method())); - QWebEngineUrlRequestInfo requestInfo(infoPrivate); - - // Deprecated =begin - // quick peek if deprecated - - if (m_profileIOData->isInterceptorDeprecated()) { - QWebEngineUrlRequestInterceptor *profileInterceptor = m_profileIOData->acquireInterceptor(); - if (profileInterceptor && m_profileIOData->isInterceptorDeprecated()) { - profileInterceptor->interceptRequest(requestInfo); - m_profileIOData->releaseInterceptor(); - if (requestInfo.changed()) { - int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - - if (qUrl != infoPrivate->url) - *newUrl = toGurl(infoPrivate->url); - - if (!infoPrivate->extraHeaders.isEmpty()) { - auto end = infoPrivate->extraHeaders.constEnd(); - for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request->SetReferrer(header.value().toStdString()); - } else { - request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - - if (result != net::OK) - return result; - - requestInfo.resetChanged(); - } - } else { - m_profileIOData->releaseInterceptor(); - } - } - // Deprecated =cut - - if (!resourceInfo) - return net::OK; - - // try to bail out - if (!m_profileIOData->hasPageInterceptors() && (!m_profileIOData->requestInterceptor() || m_profileIOData->isInterceptorDeprecated()) && - !content::IsResourceTypeFrame(resourceType)) - return net::OK; - - auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest(); - new URLRequestNotification( - request, - resourceInfo->IsMainFrame(), - newUrl, - std::move(requestInfo), - webContentsGetter, - std::move(callback), - m_profileIOData->profileAdapter() - ); - - // We'll run the callback after we notified the UI thread. - return net::ERR_IO_PENDING; -} - -void NetworkDelegateQt::OnURLRequestDestroyed(net::URLRequest *) {} - -void NetworkDelegateQt::OnCompleted(net::URLRequest * /*request*/, bool /*started*/, int /*net_error*/) {} - -bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie & /*cookie*/, - net::CookieOptions *, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canSetCookies(request.site_for_cookies(), request.url(), std::string()); -} - -bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest &request, const net::CookieList &, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canGetCookies(request.site_for_cookies(), request.url()); -} - -bool NetworkDelegateQt::OnForcePrivacyMode(const GURL &url, const GURL &site_for_cookies) const -{ - return false; - // FIXME: This is what the NetworkContext implementation does (changes tst_QWebEngineCookieStore tests since 72) - // return !canGetCookies(site_for_cookies, url); -} - -bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); -} - -bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canGetCookies(toQt(first_party), toQt(url)); -} - -int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *, net::CompletionOnceCallback, net::HttpRequestHeaders *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, - const net::ProxyRetryInfoMap &proxy_retry_info, - net::HttpRequestHeaders *headers) -{} - -void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) {} - -int NetworkDelegateQt::OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, - scoped_refptr<net::HttpResponseHeaders> *, GURL *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeRedirect(net::URLRequest *, const GURL &) {} - -void NetworkDelegateQt::OnResponseStarted(net::URLRequest *, int) {} - -void NetworkDelegateQt::OnNetworkBytesReceived(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnNetworkBytesSent(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnPACScriptError(int, const base::string16 &) {} - -net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest *, - const net::AuthChallengeInfo &, - AuthCallback, net::AuthCredentials *) -{ - return AUTH_REQUIRED_RESPONSE_NO_ACTION; -} - -bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const -{ - return true; -} - -bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin &origin) const -{ - return false; -} - -void NetworkDelegateQt::OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) const -{ - std::move(result_callback).Run(std::set<url::Origin>()); -} - -bool NetworkDelegateQt::OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h deleted file mode 100644 index f294c6c7c..000000000 --- a/src/core/net/network_delegate_qt.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef NETWORK_DELEGATE_QT_H -#define NETWORK_DELEGATE_QT_H - -#include "net/base/network_delegate.h" -#include "net/base/net_errors.h" - -#include <QUrl> -#include <QSet> - -namespace content { -class WebContents; -} - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class NetworkDelegateQt : public net::NetworkDelegate -{ - ProfileIODataQt *m_profileIOData; - -public: - NetworkDelegateQt(ProfileIODataQt *data); - - // net::NetworkDelegate implementation - int OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *new_url) override; - void OnURLRequestDestroyed(net::URLRequest *request) override; - bool OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie &cookie, net::CookieOptions *options, - bool) override; - int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionOnceCallback callback, - net::HttpRequestHeaders *headers) override; - void OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, - const net::ProxyRetryInfoMap &proxy_retry_info, net::HttpRequestHeaders *headers) override; - void OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) override; - int OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, - scoped_refptr<net::HttpResponseHeaders> *, GURL *) override; - void OnBeforeRedirect(net::URLRequest *, const GURL &) override; - void OnResponseStarted(net::URLRequest *, int) override; - void OnNetworkBytesReceived(net::URLRequest *, int64_t) override; - void OnNetworkBytesSent(net::URLRequest *, int64_t) override; - void OnCompleted(net::URLRequest *request, bool started, int net_error) override; - void OnPACScriptError(int, const base::string16 &) override; - net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest *, const net::AuthChallengeInfo &, - AuthCallback, net::AuthCredentials *) override; - bool OnCanGetCookies(const net::URLRequest &, const net::CookieList &, bool) override; - bool OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const override; - bool OnForcePrivacyMode(const GURL &, const GURL &) const override; - bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const override; - - bool OnCanQueueReportingReport(const url::Origin &origin) const override; - void OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) const override; - bool OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const override; - bool OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const override; - - bool canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const; - bool canGetCookies(const GURL &first_party, const GURL &url) const; -}; - -} // namespace QtWebEngineCore - -#endif // NETWORK_DELEGATE_QT_H diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp new file mode 100644 index 000000000..cfd011ade --- /dev/null +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "plugin_response_interceptor_url_loader_throttle.h" + +#include "base/bind.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.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 "content/public/common/resource_type.h" +#include "extensions/common/constants.h" +#include "extensions/common/extension.h" + +#include "extensions/extension_system_qt.h" +#include "profile_adapter.h" +#include "profile_io_data_qt.h" +#include "profile_qt.h" +#include "web_contents_delegate_qt.h" + +#include <string> + +namespace QtWebEngineCore { + +void onPdfStreamIntercepted(const GURL &original_url, std::string extension_id, int frame_tree_node_id) +{ + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); + if (!web_contents) + return; + + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); + if (!contentsDelegate) + return; + + WebEngineSettings *settings = contentsDelegate->webEngineSettings(); + if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) { + // If the applications has been set up to always download PDF files to open them in an + // external viewer, trigger the download. + std::unique_ptr<download::DownloadUrlParameters> params( + content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(web_contents, original_url, + MISSING_TRAFFIC_ANNOTATION)); + content::BrowserContext::GetDownloadManager(web_contents->GetBrowserContext())->DownloadUrl(std::move(params)); + return; + } + + // The URL passes the original pdf resource url, that will be requested + // by the pdf viewer extension page. + content::NavigationController::LoadURLParams params( + GURL(base::StringPrintf("%s://%s/index.html?%s", extensions::kExtensionScheme, + extension_id.c_str(), original_url.spec().c_str()))); + + params.frame_tree_node_id = frame_tree_node_id; + web_contents->GetController().LoadURLWithParams(params); +} + + +PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( + content::ResourceContext *resource_context, int resource_type, int frame_tree_node_id) + : m_resource_context(resource_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) +{} + +PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( + content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id) + : m_browser_context(browser_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) +{} + +void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL &response_url, + network::ResourceResponseHead *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); + } + + 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; + + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&onPdfStreamIntercepted, + response_url, + extension_id, + m_frame_tree_node_id)); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index 673e07bf0..82384e11e 100644 --- a/src/core/net/url_request_notification.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -37,50 +37,40 @@ ** ****************************************************************************/ -#ifndef URL_REQUEST_NOTIFIACTION_H -#define URL_REQUEST_NOTIFIACTION_H +#ifndef PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ +#define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ -#include "content/public/browser/resource_request_info.h" -#include "net/base/completion_once_callback.h" -#include "qwebengineurlrequestinfo.h" -#include <QPointer> +#include "base/macros.h" +#include "content/public/common/url_loader_throttle.h" -class GURL; - -namespace net { -class URLRequest; +namespace content { +class BrowserContext; +class ResourceContext; } namespace QtWebEngineCore { -class ProfileAdapter; -class ProfileIoDataQt; - -// Notifies WebContentsAdapterClient of a new URLRequest. -class URLRequestNotification +class PluginResponseInterceptorURLLoaderThrottle : public content::URLLoaderThrottle { public: - URLRequestNotification(net::URLRequest *request, - bool isMainFrameRequest, - GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, - QPointer<ProfileAdapter> adapter); - ~URLRequestNotification() = default; - void cancel(); - void notify(); - void complete(int error); + 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; private: - net::URLRequest *m_request; //used only by io thread - bool m_isMainFrameRequest; - GURL *m_newUrl; - const QUrl m_originalUrl; - QWebEngineUrlRequestInfo m_requestInfo; - content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter; - net::CompletionOnceCallback m_callback; - QPointer<ProfileAdapter> m_profileAdapter; + // content::URLLoaderThrottle overrides; + void WillProcessResponse(const GURL &response_url, network::ResourceResponseHead *response_head, bool *defer) override; + + content::ResourceContext *m_resource_context = nullptr; + content::BrowserContext *m_browser_context = nullptr; + const int m_resource_type; + const int m_frame_tree_node_id; + + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; -} -#endif + +} // namespace QtWebEngineCore + +#endif // PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ diff --git a/src/core/net/proxy_config_monitor.cpp b/src/core/net/proxy_config_monitor.cpp new file mode 100644 index 000000000..818b6cb7f --- /dev/null +++ b/src/core/net/proxy_config_monitor.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +// originally based on chrome/browser/net/proxy_config_monitor.cc +// Copyright 2017 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 file. + +#include "profile_qt.h" +#include "proxy_config_monitor.h" +#include "proxy_config_service_qt.h" + +#include "base/strings/utf_string_conversions.h" +#include "base/task/post_task.h" +#include "build/build_config.h" +#include "components/proxy_config/pref_proxy_config_tracker_impl.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "net/proxy_resolution/proxy_resolution_service.h" +#include "services/network/public/mojom/network_context.mojom.h" + +#include <utility> + +using content::BrowserThread; + +ProxyConfigMonitor::ProxyConfigMonitor(PrefService *prefs) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + proxy_config_service_.reset( + new ProxyConfigServiceQt( + prefs, base::CreateSingleThreadTaskRunnerWithTraits({ BrowserThread::UI }))); + + proxy_config_service_->AddObserver(this); +} + +ProxyConfigMonitor::~ProxyConfigMonitor() +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) + || !BrowserThread::IsThreadInitialized(BrowserThread::UI)); + proxy_config_service_->RemoveObserver(this); +} + +void ProxyConfigMonitor::AddToNetworkContextParams( + network::mojom::NetworkContextParams *network_context_params) +{ + network::mojom::ProxyConfigClientPtr proxy_config_client; + network_context_params->proxy_config_client_request = mojo::MakeRequest(&proxy_config_client); + proxy_config_client_set_.AddPtr(std::move(proxy_config_client)); + + poller_binding_set_.AddBinding( + this, mojo::MakeRequest(&network_context_params->proxy_config_poller_client)); + + net::ProxyConfigWithAnnotation proxy_config; + net::ProxyConfigService::ConfigAvailability availability = + proxy_config_service_->GetLatestProxyConfig(&proxy_config); + if (availability != net::ProxyConfigService::CONFIG_PENDING) + network_context_params->initial_proxy_config = proxy_config; +} + +void ProxyConfigMonitor::OnProxyConfigChanged( + const net::ProxyConfigWithAnnotation &config, + net::ProxyConfigService::ConfigAvailability availability) +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) + || !BrowserThread::IsThreadInitialized(BrowserThread::UI)); + proxy_config_client_set_.ForAllPtrs( + [config, availability](network::mojom::ProxyConfigClient *proxy_config_client) { + switch (availability) { + case net::ProxyConfigService::CONFIG_VALID: + proxy_config_client->OnProxyConfigUpdated(config); + break; + case net::ProxyConfigService::CONFIG_UNSET: + proxy_config_client->OnProxyConfigUpdated( + net::ProxyConfigWithAnnotation::CreateDirect()); + break; + case net::ProxyConfigService::CONFIG_PENDING: + NOTREACHED(); + break; + } + }); +} + +void ProxyConfigMonitor::OnLazyProxyConfigPoll() +{ + proxy_config_service_->OnLazyPoll(); +} diff --git a/src/core/net/proxy_config_monitor.h b/src/core/net/proxy_config_monitor.h new file mode 100644 index 000000000..23f073a84 --- /dev/null +++ b/src/core/net/proxy_config_monitor.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +// originally based on chrome/browser/net/proxy_config_monitor.h +// Copyright 2017 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 file. + +#ifndef PROXY_CONFIG_MONITOR_H +#define PROXY_CONFIG_MONITOR_H + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "build/buildflag.h" +#include "extensions/buildflags/buildflags.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "net/proxy_resolution/proxy_config_service.h" +#include "services/network/public/mojom/network_context.mojom-forward.h" +#include "services/network/public/mojom/network_service.mojom-forward.h" +#include "services/network/public/mojom/proxy_config.mojom-forward.h" +#include "services/network/public/mojom/proxy_config_with_annotation.mojom.h" + +namespace net { +class ProxyConfigWithAnnotation; +} + +class PrefService; +class ProxyConfigServiceQt; + +// Tracks the ProxyConfig to use, and passes any updates to a NetworkContext's +// ProxyConfigClient. This also responds to errors related to proxy settings +// from the NetworkContext, and forwards them any listening Chrome extensions +// associated with the profile. +class ProxyConfigMonitor : public net::ProxyConfigService::Observer, + public network::mojom::ProxyConfigPollerClient +{ +public: + explicit ProxyConfigMonitor(PrefService *prefs = nullptr); + + ~ProxyConfigMonitor() override; + + // Populates proxy-related fields of |network_context_params|. Updated + // ProxyConfigs will be sent to a NetworkContext created with those params + // whenever the configuration changes. Can be called more than once to inform + // multiple NetworkContexts of proxy changes. + void AddToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params); + +private: + // net::ProxyConfigService::Observer implementation: + void OnProxyConfigChanged(const net::ProxyConfigWithAnnotation &config, + net::ProxyConfigService::ConfigAvailability availability) override; + + // network::mojom::ProxyConfigPollerClient implementation: + void OnLazyProxyConfigPoll() override; + + std::unique_ptr<ProxyConfigServiceQt> proxy_config_service_; + + mojo::BindingSet<network::mojom::ProxyConfigPollerClient> poller_binding_set_; + + mojo::InterfacePtrSet<network::mojom::ProxyConfigClient> proxy_config_client_set_; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigMonitor); +}; + +#endif // !PROXY_CONFIG_MONITOR_H diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp index 8016c7e83..59884961d 100644 --- a/src/core/net/proxy_config_service_qt.cpp +++ b/src/core/net/proxy_config_service_qt.cpp @@ -46,8 +46,9 @@ #include "proxy_config_service_qt.h" #include "base/bind.h" -#include "content/public/browser/browser_thread.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" +#include "content/public/browser/browser_thread.h" +#include "net/proxy_resolution/proxy_resolution_service.h" using content::BrowserThread; @@ -69,34 +70,40 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt } } -ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService, - const net::ProxyConfigWithAnnotation &initialConfig, - ProxyPrefs::ConfigState initialState) - : m_baseService(baseService.release()) +ProxyConfigServiceQt::ProxyConfigServiceQt(PrefService *prefService, + const scoped_refptr<base::SingleThreadTaskRunner> &taskRunner) + : m_baseService(net::ProxyResolutionService::CreateSystemProxyConfigService(taskRunner)) , m_usesSystemConfiguration(false) , m_registeredObserver(false) - , m_prefConfig(initialConfig) - , m_perfState(initialState) -{} + , m_prefState(prefService + ? PrefProxyConfigTrackerImpl::ReadPrefConfig(prefService, &m_prefConfig) + : ProxyPrefs::CONFIG_UNSET) +{ + DETACH_FROM_SEQUENCE(m_sequenceChecker); +} ProxyConfigServiceQt::~ProxyConfigServiceQt() { + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); if (m_registeredObserver && m_baseService.get()) m_baseService->RemoveObserver(this); } void ProxyConfigServiceQt::AddObserver(net::ProxyConfigService::Observer *observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); m_observers.AddObserver(observer); } void ProxyConfigServiceQt::RemoveObserver(net::ProxyConfigService::Observer *observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); m_observers.RemoveObserver(observer); } net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfigWithAnnotation *config) { + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); m_usesSystemConfiguration = QNetworkProxyFactory::usesSystemConfiguration(); if (m_usesSystemConfiguration) { // Use Chromium's base service to retrieve system settings @@ -106,7 +113,7 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); ProxyPrefs::ConfigState configState; systemAvailability = PrefProxyConfigTrackerImpl::GetEffectiveProxyConfig( - m_perfState, m_prefConfig, systemAvailability, systemConfig, + m_prefState, m_prefConfig, systemAvailability, systemConfig, false, &configState, config); RegisterObserver(); return systemAvailability; @@ -151,7 +158,7 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy void ProxyConfigServiceQt::OnLazyPoll() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); // We need to update if // - setUseSystemConfiguration() was called in between @@ -168,7 +175,7 @@ void ProxyConfigServiceQt::OnLazyPoll() // Called when the base service changed void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfigWithAnnotation &config, ConfigAvailability availability) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); Q_UNUSED(config); if (!m_usesSystemConfiguration) @@ -180,6 +187,7 @@ void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfigWithAnnota // Update our observers void ProxyConfigServiceQt::Update() { + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); net::ProxyConfigWithAnnotation actual_config; ConfigAvailability availability = GetLatestProxyConfig(&actual_config); if (availability == CONFIG_PENDING) @@ -193,7 +201,7 @@ void ProxyConfigServiceQt::Update() // in the constructor. void ProxyConfigServiceQt::RegisterObserver() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CALLED_ON_VALID_SEQUENCE(m_sequenceChecker); if (!m_registeredObserver && m_baseService.get()) { m_baseService->AddObserver(this); m_registeredObserver = true; diff --git a/src/core/net/proxy_config_service_qt.h b/src/core/net/proxy_config_service_qt.h index 4d8619055..c0928bc03 100644 --- a/src/core/net/proxy_config_service_qt.h +++ b/src/core/net/proxy_config_service_qt.h @@ -42,6 +42,7 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" +#include "base/single_thread_task_runner.h" #include "net/proxy_resolution/proxy_config.h" #include "net/proxy_resolution/proxy_config_service.h" @@ -50,6 +51,8 @@ #include <QNetworkProxy> +class PrefService; + class ProxyConfigServiceQt : public net::ProxyConfigService , public net::ProxyConfigService::Observer @@ -57,9 +60,8 @@ class ProxyConfigServiceQt public: static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &); - explicit ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService, - const net::ProxyConfigWithAnnotation &initialConfig, - ProxyPrefs::ConfigState initialState); + explicit ProxyConfigServiceQt(PrefService *prefService, + const scoped_refptr<base::SingleThreadTaskRunner> &taskRunner); ~ProxyConfigServiceQt() override; // ProxyConfigService implementation: @@ -92,7 +94,9 @@ private: // Configuration as defined by prefs. net::ProxyConfigWithAnnotation m_prefConfig; - ProxyPrefs::ConfigState m_perfState; + ProxyPrefs::ConfigState m_prefState; + + SEQUENCE_CHECKER(m_sequenceChecker); DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceQt); }; diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp new file mode 100644 index 000000000..b6abeb567 --- /dev/null +++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +// originally based on android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc: +// Copyright 2019 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 file. + +#include "proxying_restricted_cookie_manager_qt.h" + +#include "api/qwebenginecookiestore.h" +#include "api/qwebenginecookiestore_p.h" +#include "profile_adapter.h" +#include "profile_qt.h" +#include "type_conversion.h" + +#include "base/memory/ptr_util.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +namespace QtWebEngineCore { + +class ProxyingRestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener { +public: + ProxyingRestrictedCookieManagerListenerQt(const GURL &url, + const GURL &site_for_cookies, + base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager, + network::mojom::CookieChangeListenerPtr client_listener) + : url_(url) + , site_for_cookies_(site_for_cookies) + , restricted_cookie_manager_(restricted_cookie_manager) + , client_listener_(std::move(client_listener)) + {} + + void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override + { + if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) + client_listener_->OnCookieChange(cookie, cause); + } + +private: + const GURL url_; + const GURL site_for_cookies_; + base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager_; + network::mojom::CookieChangeListenerPtr client_listener_; +}; + +// static +void ProxyingRestrictedCookieManagerQt::CreateAndBind(ProfileIODataQt *profileIoData, + network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + bool is_service_worker, + int process_id, + int frame_id, + network::mojom::RestrictedCookieManagerRequest request) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread, + profileIoData, + std::move(underlying_rcm), + is_service_worker, process_id, frame_id, + std::move(request))); +} + + +// static +void ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, + network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + bool is_service_worker, + int process_id, + int frame_id, + network::mojom::RestrictedCookieManagerRequest request) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + auto wrapper = base::WrapUnique(new ProxyingRestrictedCookieManagerQt( + profileIoData->getWeakPtrOnIOThread(), + network::mojom::RestrictedCookieManagerPtr(std::move(underlying_rcm)), + is_service_worker, process_id, frame_id)); + mojo::MakeStrongBinding(std::move(wrapper), std::move(request)); +} + +ProxyingRestrictedCookieManagerQt::ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, + network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, + bool is_service_worker, + int32_t process_id, + int32_t frame_id) + : m_profileIoData(std::move(profileIoData)) + , underlying_restricted_cookie_manager_(std::move(underlyingRestrictedCookieManager)) + , is_service_worker_(is_service_worker) + , process_id_(process_id) + , frame_id_(frame_id) + , weak_factory_(this) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, + const GURL &site_for_cookies, + network::mojom::CookieManagerGetOptionsPtr options, + GetAllForUrlCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (allowCookies(url, site_for_cookies)) { + underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); + } else { + std::move(callback).Run(std::vector<net::CanonicalCookie>()); + } +} + +void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, + const GURL &url, + const GURL &site_for_cookies, + SetCanonicalCookieCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (allowCookies(url, site_for_cookies)) { + underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); + } else { + std::move(callback).Run(false); + } +} + +void ProxyingRestrictedCookieManagerQt::AddChangeListener(const GURL &url, + const GURL &site_for_cookies, + network::mojom::CookieChangeListenerPtr listener, + AddChangeListenerCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + network::mojom::CookieChangeListenerPtr proxy_listener_ptr; + auto proxy_listener = + std::make_unique<ProxyingRestrictedCookieManagerListenerQt>( + url, site_for_cookies, weak_factory_.GetWeakPtr(), + std::move(listener)); + + mojo::MakeStrongBinding(std::move(proxy_listener), + mojo::MakeRequest(&proxy_listener_ptr)); + + underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, std::move(proxy_listener_ptr), std::move(callback)); +} + +void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, + const GURL &site_for_cookies, + const std::string &cookie, + SetCookieFromStringCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (allowCookies(url, site_for_cookies)) { + underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, cookie, std::move(callback)); + } else { + std::move(callback).Run(); + } +} + +void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, + const GURL &site_for_cookies, + GetCookiesStringCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (allowCookies(url, site_for_cookies)) { + underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, std::move(callback)); + } else { + std::move(callback).Run(""); + } +} + +void ProxyingRestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, + const GURL &site_for_cookies, + CookiesEnabledForCallback callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + std::move(callback).Run(allowCookies(url, site_for_cookies)); +} + +bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const +{ + if (!m_profileIoData) + return false; + return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h index 9154f671d..7a9f0e3ab 100644 --- a/src/core/net/restricted_cookie_manager_qt.h +++ b/src/core/net/proxying_restricted_cookie_manager_qt.h @@ -37,30 +37,30 @@ ** ****************************************************************************/ -#ifndef RESTRICTED_COOKIE_MANAGER_QT_H -#define RESTRICTED_COOKIE_MANAGER_QT_H +#ifndef PROXYING_RESTRICTED_COOKIE_MANAGER_QT_H +#define PROXYING_RESTRICTED_COOKIE_MANAGER_QT_H #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "services/network/restricted_cookie_manager.h" +#include "services/network/public/mojom/restricted_cookie_manager.mojom.h" #include "url/gurl.h" namespace QtWebEngineCore { class ProfileIODataQt; -class RestrictedCookieManagerQt : public network::RestrictedCookieManager +class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCookieManager { public: - RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, + // Expects to be called on the UI thread. + static void CreateAndBind(ProfileIODataQt *profileIoData, + network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, bool is_service_worker, - int32_t process_id, - int32_t frame_id); - ~RestrictedCookieManagerQt() override; + int process_id, + int frame_id, + network::mojom::RestrictedCookieManagerRequest request); + + ~ProxyingRestrictedCookieManagerQt() override; // network::mojom::RestrictedCookieManager interface: void GetAllForUrl(const GURL &url, @@ -75,7 +75,10 @@ public: const GURL &site_for_cookies, network::mojom::CookieChangeListenerPtr listener, AddChangeListenerCallback callback) override; - + void SetCookieFromString(const GURL &url, + const GURL &site_for_cookies, + const std::string &cookie, + SetCookieFromStringCallback callback) override; void GetCookiesString(const GURL &url, const GURL &site_for_cookies, GetCookiesStringCallback callback) override; @@ -88,13 +91,31 @@ public: bool allowCookies(const GURL &url, const GURL &site_for_cookies) const; private: + ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, + network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, + bool is_service_worker, + int32_t process_id, + int32_t frame_id); + + static void CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, + network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + bool is_service_worker, + int process_id, + int frame_id, + network::mojom::RestrictedCookieManagerRequest request); + base::WeakPtr<ProfileIODataQt> m_profileIoData; - base::WeakPtrFactory<RestrictedCookieManagerQt> weak_factory_; + network::mojom::RestrictedCookieManagerPtr underlying_restricted_cookie_manager_; + bool is_service_worker_; + int process_id_; + int frame_id_; + + base::WeakPtrFactory<ProxyingRestrictedCookieManagerQt> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(RestrictedCookieManagerQt); + DISALLOW_COPY_AND_ASSIGN(ProxyingRestrictedCookieManagerQt); }; } // namespace QtWebEngineCore -#endif // RESTRICTED_COOKIE_MANAGER_QT_H +#endif // PROXYING_RESTRICTED_COOKIE_MANAGER_QT_H diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp new file mode 100644 index 000000000..51a226117 --- /dev/null +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -0,0 +1,560 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "proxying_url_loader_factory_qt.h" + +#include <utility> + +#include "base/bind.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/task/post_task.h" +#include "components/safe_browsing/common/safebrowsing_constants.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/global_request_id.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_constants.h" +#include "content/public/common/url_utils.h" +#include "net/base/load_flags.h" +#include "net/http/http_status_code.h" +#include "net/http/http_util.h" + +#include "api/qwebengineurlrequestinfo_p.h" +#include "profile_io_data_qt.h" +#include "type_conversion.h" +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" +#include <QVariant> + +// originally based on aw_proxying_url_loader_factory.cc: +// Copyright 2018 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 file. + +namespace QtWebEngineCore { + +extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); + +static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) +{ + if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) + return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); + return QWebEngineUrlRequestInfo::ResourceTypeUnknown; +} + +static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) +{ + return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); +} + +// Handles intercepted, in-progress requests/responses, so that they can be +// controlled and modified accordingly. +class InterceptedRequest : public network::mojom::URLLoader + , public network::mojom::URLLoaderClient +{ +public: + InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, + const network::ResourceRequest &request, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, + ProfileIODataQt *profileData, + network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, + network::mojom::URLLoaderFactoryPtr target_factory); + ~InterceptedRequest() override; + + void Restart(); + void InterceptOnUIThread(); + + // network::mojom::URLLoaderClient + void OnReceiveResponse(const network::ResourceResponseHead &head) override; + void OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) override; + void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) override; + void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override; + void OnTransferSizeUpdated(int32_t transfer_size_diff) override; + void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body) override; + void OnComplete(const network::URLLoaderCompletionStatus &status) override; + + // network::mojom::URLLoader + void FollowRedirect(const std::vector<std::string> &removed_headers, + const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override; + void ProceedWithResponse() override; + void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override; + void PauseReadingBodyFromNet() override; + void ResumeReadingBodyFromNet() override; + + void ContinueAfterIntercept(); + +private: + // This is called when the original URLLoaderClient has a connection error. + void OnURLLoaderClientError(); + + // This is called when the original URLLoader has a connection error. + void OnURLLoaderError(uint32_t custom_reason, const std::string &description); + + // Call OnComplete on |target_client_|. If |wait_for_loader_error| is true + // then this object will wait for |proxied_loader_binding_| to have a + // connection error before destructing. + void CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error); + + void SendErrorAndCompleteImmediately(int error_code); + + const int process_id_; + const uint64_t request_id_; + const int32_t routing_id_; + const uint32_t options_; + bool input_stream_previously_failed_ = false; + bool request_was_redirected_ = false; + + // If the |target_loader_| called OnComplete with an error this stores it. + // That way the destructor can send it to OnReceivedError if safe browsing + // error didn't occur. + int error_status_ = net::OK; + GURL m_originalUrl; + + network::ResourceRequest request_; + network::ResourceResponseHead current_response_; + + const net::MutableNetworkTrafficAnnotationTag traffic_annotation_; + + ProfileIODataQt *m_profileData; + mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_; + network::mojom::URLLoaderClientPtr target_client_; + + mojo::Binding<network::mojom::URLLoaderClient> proxied_client_binding_; + network::mojom::URLLoaderPtr target_loader_; + network::mojom::URLLoaderFactoryPtr target_factory_; + + base::WeakPtrFactory<InterceptedRequest> m_weakFactory; + base::WeakPtr<InterceptedRequest> m_weakPtr; + DISALLOW_COPY_AND_ASSIGN(InterceptedRequest); +}; + +InterceptedRequest::InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, + const network::ResourceRequest &request, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, + ProfileIODataQt *profileData, + network::mojom::URLLoaderRequest loader_request, + network::mojom::URLLoaderClientPtr client, + network::mojom::URLLoaderFactoryPtr target_factory) + : process_id_(process_id) + , request_id_(request_id) + , routing_id_(routing_id) + , options_(options) + , request_(request) + , traffic_annotation_(traffic_annotation) + , m_profileData(profileData) + , proxied_loader_binding_(this, std::move(loader_request)) + , target_client_(std::move(client)) + , proxied_client_binding_(this) + , target_factory_(std::move(target_factory)) + , m_weakFactory(this) + , m_weakPtr(m_weakFactory.GetWeakPtr()) +{ + // If there is a client error, clean up the request. + target_client_.set_connection_error_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, m_weakFactory.GetWeakPtr())); + proxied_loader_binding_.set_connection_error_with_reason_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderError, m_weakFactory.GetWeakPtr())); +} + +InterceptedRequest::~InterceptedRequest() +{ + m_weakFactory.InvalidateWeakPtrs(); +} + +void InterceptedRequest::Restart() +{ + // FIXME: Support deprecated interceptors here + + // FIXME: unretained post? + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&InterceptedRequest::InterceptOnUIThread, base::Unretained(this))); +} + +void InterceptedRequest::InterceptOnUIThread() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + content::ResourceType resourceType = content::ResourceType(request_.resource_type); + WebContentsAdapterClient::NavigationType navigationType = + pageTransitionToNavigationType(ui::PageTransition(request_.transition_type)); + + m_originalUrl = request_.url; + const QUrl qUrl = toQt(request_.url); + + const QUrl initiator = request_.request_initiator.has_value() ? toQt(request_.request_initiator->GetURL()) : QUrl(); + + QUrl firstPartyUrl; + if (resourceType == content::ResourceType::kSubFrame) + firstPartyUrl = toQt(request_.first_party_url); + else + firstPartyUrl = toQt(request_.site_for_cookies); + + QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), + toQt(navigationType), + qUrl, + firstPartyUrl, + initiator, + QByteArray::fromStdString(request_.method)); + QWebEngineUrlRequestInfo requestInfo(infoPrivate); + + content::WebContents *webContents = nullptr; + if (process_id_) { + content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); + webContents = content::WebContents::FromRenderFrameHost(frameHost); + } else + webContents = content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); + + if (webContents) { + int result = net::OK; + if (m_profileData) { + QWebEngineUrlRequestInterceptor *interceptor = m_profileData->requestInterceptor(); + if (interceptor && !interceptor->property("deprecated").toBool()) + interceptor->interceptRequest(requestInfo); + } + + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); + + if (!requestInfo.changed()) { + client->interceptRequest(requestInfo); + } + + if (requestInfo.changed()) { + result = requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; + // We handle the rest of the changes later when we are back in I/O thread + } + + if (result != net::OK) { + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&InterceptedRequest::SendErrorAndCompleteImmediately, m_weakPtr, result)); + return; + } + if (requestInfo.changed()) { + if (requestInfo.requestUrl() != qUrl) { + net::URLRequest::FirstPartyURLPolicy first_party_url_policy = + request_.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT + : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; + net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo(request_.method, request_.url, + request_.site_for_cookies, request_.top_frame_origin, + first_party_url_policy, request_.referrer_policy, + request_.referrer.spec(), net::HTTP_TEMPORARY_REDIRECT, + toGurl(requestInfo.requestUrl()), base::nullopt, + false /*insecure_scheme_was_upgraded*/); + + // FIXME: Should probably create a new header. + current_response_.encoded_data_length = 0; + // FIXME: unretained post. + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&network::mojom::URLLoaderClientProxy::OnReceiveRedirect, base::Unretained(&(*target_client_)), redirectInfo, current_response_)); + request_.method = redirectInfo.new_method; + request_.url = redirectInfo.new_url; + request_.site_for_cookies = redirectInfo.new_site_for_cookies; + request_.referrer = GURL(redirectInfo.new_referrer); + request_.referrer_policy = redirectInfo.new_referrer_policy; + if (request_.method == net::HttpRequestHeaders::kGetMethod) + request_.request_body = nullptr; + return; + } + + if (!requestInfo.d_ptr->extraHeaders.isEmpty()) { + auto end = requestInfo.d_ptr->extraHeaders.constEnd(); + for (auto header = requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { + std::string h = header.key().toStdString(); + if (base::LowerCaseEqualsASCII(h, "referer")) { + request_.referrer = GURL(header.value().toStdString()); + } else { + request_.headers.SetHeader(h, header.value().toStdString()); + } + } + } + } + } + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&InterceptedRequest::ContinueAfterIntercept, m_weakPtr)); +} + +void InterceptedRequest::ContinueAfterIntercept() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!target_loader_ && target_factory_) { + network::mojom::URLLoaderClientPtr proxied_client; + proxied_client_binding_.Bind(mojo::MakeRequest(&proxied_client)); + target_factory_->CreateLoaderAndStart(mojo::MakeRequest(&target_loader_), routing_id_, request_id_, options_, + request_, std::move(proxied_client), traffic_annotation_); + } +} + +// URLLoaderClient methods. + +void InterceptedRequest::OnReceiveResponse(const network::ResourceResponseHead &head) +{ + current_response_ = head; + + target_client_->OnReceiveResponse(head); +} + +void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) +{ + // TODO(timvolodine): handle redirect override. + request_was_redirected_ = true; + current_response_ = head; + target_client_->OnReceiveRedirect(redirect_info, head); + request_.url = redirect_info.new_url; + request_.method = redirect_info.new_method; + request_.site_for_cookies = redirect_info.new_site_for_cookies; + request_.referrer = GURL(redirect_info.new_referrer); + request_.referrer_policy = redirect_info.new_referrer_policy; +} + +void InterceptedRequest::OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) +{ + target_client_->OnUploadProgress(current_position, total_size, std::move(callback)); +} + +void InterceptedRequest::OnReceiveCachedMetadata(mojo_base::BigBuffer data) +{ + target_client_->OnReceiveCachedMetadata(std::move(data)); +} + +void InterceptedRequest::OnTransferSizeUpdated(int32_t transfer_size_diff) +{ + target_client_->OnTransferSizeUpdated(transfer_size_diff); +} + +void InterceptedRequest::OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body) +{ + target_client_->OnStartLoadingResponseBody(std::move(body)); +} + +void InterceptedRequest::OnComplete(const network::URLLoaderCompletionStatus &status) +{ + // Only wait for the original loader to possibly have a custom error if the + // target loader succeeded. If the target loader failed, then it was a race as + // to whether that error or the safe browsing error would be reported. + CallOnComplete(status, status.error_code == net::OK); +} + +// URLLoader methods. + +void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_headers, + const net::HttpRequestHeaders &modified_headers, + const base::Optional<GURL> &new_url) +{ + if (target_loader_) + target_loader_->FollowRedirect(removed_headers, modified_headers, new_url); + + // If |OnURLLoaderClientError| was called then we're just waiting for the + // connection error handler of |proxied_loader_binding_|. Don't restart the + // job since that'll create another URLLoader + if (!target_client_) + return; + + Restart(); +} + +void InterceptedRequest::ProceedWithResponse() +{ + if (target_loader_) + target_loader_->ProceedWithResponse(); +} + +void InterceptedRequest::SetPriority(net::RequestPriority priority, int32_t intra_priority_value) +{ + if (target_loader_) + target_loader_->SetPriority(priority, intra_priority_value); +} + +void InterceptedRequest::PauseReadingBodyFromNet() +{ + if (target_loader_) + target_loader_->PauseReadingBodyFromNet(); +} + +void InterceptedRequest::ResumeReadingBodyFromNet() +{ + if (target_loader_) + target_loader_->ResumeReadingBodyFromNet(); +} + +void InterceptedRequest::OnURLLoaderClientError() +{ + // We set |wait_for_loader_error| to true because if the loader did have a + // custom_reason error then the client would be reset as well and it would be + // a race as to which connection error we saw first. + CallOnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED), true /* wait_for_loader_error */); +} + +void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason, const std::string &description) +{ + // If CallOnComplete was already called, then this object is ready to be deleted. + if (!target_client_) + delete this; +} + +void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + // Save an error status so that we call onReceiveError at destruction if there + // was no safe browsing error. + if (status.error_code != net::OK) + error_status_ = status.error_code; + + if (target_client_) + target_client_->OnComplete(status); + + if (proxied_loader_binding_ && wait_for_loader_error) { + // Don't delete |this| yet, in case the |proxied_loader_binding_|'s + // error_handler is called with a reason to indicate an error which we want + // to send to the client bridge. Also reset |target_client_| so we don't + // get its error_handler called and then delete |this|. + target_client_.reset(); + + // Since the original client is gone no need to continue loading the + // request. + proxied_client_binding_.Close(); + target_loader_.reset(); + + // In case there are pending checks as to whether this request should be + // intercepted, we don't want that causing |target_client_| to be used + // later. + m_weakFactory.InvalidateWeakPtrs(); + } else { + delete this; + } +} + +void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + auto status = network::URLLoaderCompletionStatus(error_code); + target_client_->OnComplete(status); + delete this; +} + +ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(int process_id, + content::ResourceContext *resourceContext, + network::mojom::URLLoaderFactoryRequest loader_request, + network::mojom::URLLoaderFactoryPtrInfo target_factory_info) + : m_processId(process_id), m_resourceContext(resourceContext), m_weakFactory(this) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (target_factory_info) { + m_targetFactory.Bind(std::move(target_factory_info)); + m_targetFactory.set_connection_error_handler( + base::BindOnce(&ProxyingURLLoaderFactoryQt::OnTargetFactoryError, m_weakFactory.GetWeakPtr())); + } + m_proxyBindings.AddBinding(this, std::move(loader_request)); + m_proxyBindings.set_connection_error_handler( + base::BindRepeating(&ProxyingURLLoaderFactoryQt::OnProxyBindingError, m_weakFactory.GetWeakPtr())); +} + +ProxyingURLLoaderFactoryQt::~ProxyingURLLoaderFactoryQt() +{ + m_weakFactory.InvalidateWeakPtrs(); +} + +// static +void ProxyingURLLoaderFactoryQt::CreateProxy(int process_id, + content::ResourceContext *resourceContext, + network::mojom::URLLoaderFactoryRequest loader_request, + network::mojom::URLLoaderFactoryPtrInfo target_factory_info) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // Will manage its own lifetime + new ProxyingURLLoaderFactoryQt(process_id, resourceContext, std::move(loader_request), std::move(target_factory_info)); +} + +void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, + int32_t request_id, uint32_t options, + const network::ResourceRequest &request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + ProfileIODataQt *profileIOData = ProfileIODataQt::FromResourceContext(m_resourceContext); + + QWebEngineUrlRequestInterceptor *profileInterceptor = profileIOData ? profileIOData->requestInterceptor() : nullptr; + if (!profileIOData || !(profileInterceptor || profileIOData->hasPageInterceptors())) { + m_targetFactory->CreateLoaderAndStart( + std::move(loader), routing_id, request_id, options, request, + std::move(client), traffic_annotation); + return; + } + + network::mojom::URLLoaderFactoryPtr target_factory_clone; + if (m_targetFactory) + m_targetFactory->Clone(mojo::MakeRequest(&target_factory_clone)); + + + // Will manage its own lifetime + InterceptedRequest *req = new InterceptedRequest(m_processId, request_id, routing_id, options, request, + traffic_annotation, profileIOData, + std::move(loader), std::move(client), + std::move(target_factory_clone)); + req->Restart(); +} + +void ProxyingURLLoaderFactoryQt::OnTargetFactoryError() +{ + delete this; +} + +void ProxyingURLLoaderFactoryQt::OnProxyBindingError() +{ + if (m_proxyBindings.empty()) + delete this; +} + +void ProxyingURLLoaderFactoryQt::Clone(network::mojom::URLLoaderFactoryRequest loader_request) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + m_proxyBindings.AddBinding(this, std::move(loader_request)); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/proxying_url_loader_factory_qt.h b/src/core/net/proxying_url_loader_factory_qt.h new file mode 100644 index 000000000..a2f175885 --- /dev/null +++ b/src/core/net/proxying_url_loader_factory_qt.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROXYING_URL_LOADER_FACTORY_QT_H_ +#define PROXYING_URL_LOADER_FACTORY_QT_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_delete_on_sequence.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/resource_response.h" +#include "services/network/public/mojom/url_loader.mojom.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "url/gurl.h" + +// based on aw_proxying_url_loader_factory.h: +// Copyright 2018 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 file. + +namespace content { +class ResourceContext; +} + +namespace QtWebEngineCore { + +class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory +{ +public: + ProxyingURLLoaderFactoryQt(int process_id, content::ResourceContext *resourceContext, + network::mojom::URLLoaderFactoryRequest loader_request, + network::mojom::URLLoaderFactoryPtrInfo target_factory_info); + + ~ProxyingURLLoaderFactoryQt() override; + + // static + static void CreateProxy(int process_id, content::ResourceContext *resourceContext, + network::mojom::URLLoaderFactoryRequest loader, + network::mojom::URLLoaderFactoryPtrInfo target_factory_info); + + void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, int32_t request_id, + uint32_t options, const network::ResourceRequest &request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override; + + void Clone(network::mojom::URLLoaderFactoryRequest loader_request) override; + +private: + void OnTargetFactoryError(); + void OnProxyBindingError(); + + const int m_processId; + mojo::BindingSet<network::mojom::URLLoaderFactory> m_proxyBindings; + network::mojom::URLLoaderFactoryPtr m_targetFactory; + + content::ResourceContext *m_resourceContext; + + base::WeakPtrFactory<ProxyingURLLoaderFactoryQt> m_weakFactory; + + DISALLOW_COPY_AND_ASSIGN(ProxyingURLLoaderFactoryQt); +}; + +} // namespace QtWebEngineCore + +#endif // PROXYING_URL_LOADER_FACTORY_QT_H_ diff --git a/src/core/net/restricted_cookie_manager_qt.cpp b/src/core/net/restricted_cookie_manager_qt.cpp deleted file mode 100644 index 7f1ca163e..000000000 --- a/src/core/net/restricted_cookie_manager_qt.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ - -// originally based on android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc: -// Copyright 2019 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 file. - -#include "restricted_cookie_manager_qt.h" - -#include "api/qwebenginecookiestore.h" -#include "api/qwebenginecookiestore_p.h" -#include "profile_adapter.h" -#include "profile_qt.h" -#include "type_conversion.h" - -#include "base/memory/ptr_util.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace QtWebEngineCore { - -class RestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener -{ -public: - RestrictedCookieManagerListenerQt(const GURL &url, - const GURL &site_for_cookies, - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager, - network::mojom::CookieChangeListenerPtr client_listener) - : url_(url) - , site_for_cookies_(site_for_cookies) - , restricted_cookie_manager_(restricted_cookie_manager) - , client_listener_(std::move(client_listener)) - {} - - void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override - { - if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) - client_listener_->OnCookieChange(cookie, cause); - } - -private: - const GURL url_; - const GURL site_for_cookies_; - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager_; - network::mojom::CookieChangeListenerPtr client_listener_; -}; - -RestrictedCookieManagerQt::RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t frame_id) - : network::RestrictedCookieManager(role, cookie_store, cookie_settings, origin, - nullptr, is_service_worker, process_id, frame_id) - , m_profileIoData(profileIoData) - , weak_factory_(this) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -RestrictedCookieManagerQt::~RestrictedCookieManagerQt() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -void RestrictedCookieManagerQt::GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieManagerGetOptionsPtr options, - GetAllForUrlCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); - } else { - std::move(callback).Run(std::vector<net::CanonicalCookie>()); - } -} - -void RestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, - const GURL &url, - const GURL &site_for_cookies, - SetCanonicalCookieCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(false); - } -} - -void RestrictedCookieManagerQt::AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, - AddChangeListenerCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - network::mojom::CookieChangeListenerPtr proxy_listener_ptr; - auto proxy_listener = - std::make_unique<RestrictedCookieManagerListenerQt>( - url, site_for_cookies, weak_factory_.GetWeakPtr(), - std::move(listener)); - - mojo::MakeStrongBinding(std::move(proxy_listener), - mojo::MakeRequest(&proxy_listener_ptr)); - - network::RestrictedCookieManager::AddChangeListener( - url, site_for_cookies, std::move(proxy_listener_ptr), - std::move(callback)); -} - -void RestrictedCookieManagerQt::GetCookiesString(const GURL &url, - const GURL &site_for_cookies, - GetCookiesStringCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetCookiesString(url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(""); - } -} - -void RestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, - CookiesEnabledForCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::move(callback).Run(allowCookies(url, site_for_cookies)); -} - -bool RestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const -{ - if (!m_profileIoData) - return false; - return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp new file mode 100644 index 000000000..cf84b840b --- /dev/null +++ b/src/core/net/system_network_context_manager.cpp @@ -0,0 +1,351 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +// based on chrome/browser/net/system_network_context_manager.cc: +// Copyright 2017 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 file. + +#include "net/system_network_context_manager.h" + +#include <set> +#include <unordered_map> +#include <utility> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/feature_list.h" +#include "base/logging.h" +#include "base/sequence_checker.h" +#include "base/strings/string_split.h" +#include "base/task/post_task.h" +#include "base/values.h" +#include "build/build_config.h" +#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" +#include "chrome/common/chrome_switches.h" +#include "components/certificate_transparency/ct_known_logs.h" +#include "components/network_session_configurator/common/network_features.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/cors_exempt_headers.h" +#include "content/public/browser/network_service_instance.h" +#include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/service_names.mojom.h" +#include "content/public/common/user_agent.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr.h" +#include "net/dns/public/util.h" +#include "net/net_buildflags.h" +#include "net/third_party/uri_template/uri_template.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/mojom/host_resolver.mojom.h" +#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" +#include "url/gurl.h" + +namespace { + +// The global instance of the SystemNetworkContextmanager. +SystemNetworkContextManager *g_system_network_context_manager = nullptr; + +network::mojom::HttpAuthStaticParamsPtr CreateHttpAuthStaticParams() +{ + network::mojom::HttpAuthStaticParamsPtr auth_static_params = network::mojom::HttpAuthStaticParams::New(); + + auth_static_params->supported_schemes = { "basic", "digest", "ntlm", "negotiate" }; + + return auth_static_params; +} + +network::mojom::HttpAuthDynamicParamsPtr CreateHttpAuthDynamicParams() +{ + network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params = network::mojom::HttpAuthDynamicParams::New(); + + auto *command_line = base::CommandLine::ForCurrentProcess(); + auth_dynamic_params->server_whitelist = command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist); +// auth_dynamic_params->delegate_whitelist = command_line->GetSwitchValueASCII(switches::kAuthNegotiateDelegateWhitelist); +// auth_dynamic_params->enable_negotiate_port = command_line->HasSwitch(switches::kEnableAuthNegotiatePort); + + return auth_dynamic_params; +} + +} // namespace + +// SharedURLLoaderFactory backed by a SystemNetworkContextManager and its +// network context. Transparently handles crashes. +class SystemNetworkContextManager::URLLoaderFactoryForSystem : public network::SharedURLLoaderFactory +{ +public: + explicit URLLoaderFactoryForSystem(SystemNetworkContextManager *manager) : manager_(manager) + { + DETACH_FROM_SEQUENCE(sequence_checker_); + } + + // mojom::URLLoaderFactory implementation: + + void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, + uint32_t options, const network::ResourceRequest &url_request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override + { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!manager_) + return; + manager_->GetURLLoaderFactory()->CreateLoaderAndStart(std::move(request), routing_id, request_id, options, + url_request, std::move(client), traffic_annotation); + } + + void Clone(network::mojom::URLLoaderFactoryRequest request) override + { + if (!manager_) + return; + manager_->GetURLLoaderFactory()->Clone(std::move(request)); + } + + // SharedURLLoaderFactory implementation: + std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override + { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return std::make_unique<network::CrossThreadSharedURLLoaderFactoryInfo>(this); + } + + void Shutdown() { manager_ = nullptr; } + +private: + friend class base::RefCounted<URLLoaderFactoryForSystem>; + ~URLLoaderFactoryForSystem() override {} + + SEQUENCE_CHECKER(sequence_checker_); + SystemNetworkContextManager *manager_; + + DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryForSystem); +}; + +network::mojom::NetworkContext *SystemNetworkContextManager::GetContext() +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // SetUp should already have been called. + DCHECK(io_thread_network_context_); + return io_thread_network_context_.get(); + } + + if (!network_service_network_context_ || network_service_network_context_.encountered_error()) { + // This should call into OnNetworkServiceCreated(), which will re-create + // the network service, if needed. There's a chance that it won't be + // invoked, if the NetworkContext has encountered an error but the + // NetworkService has not yet noticed its pipe was closed. In that case, + // trying to create a new NetworkContext would fail, anyways, and hopefully + // a new NetworkContext will be created on the next GetContext() call. + content::GetNetworkService(); + DCHECK(network_service_network_context_); + } + return network_service_network_context_.get(); +} + +network::mojom::URLLoaderFactory *SystemNetworkContextManager::GetURLLoaderFactory() +{ + // Create the URLLoaderFactory as needed. + if (url_loader_factory_ && !url_loader_factory_.encountered_error()) { + return url_loader_factory_.get(); + } + + network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); + params->process_id = network::mojom::kBrowserProcessId; + params->is_corb_enabled = false; + GetContext()->CreateURLLoaderFactory(mojo::MakeRequest(&url_loader_factory_), std::move(params)); + return url_loader_factory_.get(); +} + +scoped_refptr<network::SharedURLLoaderFactory> SystemNetworkContextManager::GetSharedURLLoaderFactory() +{ + return shared_url_loader_factory_; +} + +void SystemNetworkContextManager::SetUp( + network::mojom::NetworkContextRequest *network_context_request, + network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, + base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, + network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, + network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + *network_context_request = mojo::MakeRequest(&io_thread_network_context_); + *network_context_params = CreateNetworkContextParams(); + } + *is_quic_allowed = false; + *http_auth_static_params = CreateHttpAuthStaticParams(); + *http_auth_dynamic_params = CreateHttpAuthDynamicParams(); + // GetStubResolverConfig(local_state_, stub_resolver_enabled, dns_over_https_servers); +} + +// static +SystemNetworkContextManager *SystemNetworkContextManager::CreateInstance() +{ + DCHECK(!g_system_network_context_manager); + g_system_network_context_manager = new SystemNetworkContextManager(); + return g_system_network_context_manager; +} + +// static +SystemNetworkContextManager *SystemNetworkContextManager::GetInstance() +{ + return g_system_network_context_manager; +} + +// static +void SystemNetworkContextManager::DeleteInstance() +{ + DCHECK(g_system_network_context_manager); + delete g_system_network_context_manager; +} + +SystemNetworkContextManager::SystemNetworkContextManager() +{ + shared_url_loader_factory_ = new URLLoaderFactoryForSystem(this); +} + +SystemNetworkContextManager::~SystemNetworkContextManager() +{ + shared_url_loader_factory_->Shutdown(); +} + +void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + // Disable QUIC globally + network_service->DisableQuic(); + + network_service->SetUpHttpAuth(CreateHttpAuthStaticParams()); + network_service->ConfigureHttpAuthPrefs(CreateHttpAuthDynamicParams()); + + // The system NetworkContext must be created first, since it sets + // |primary_network_context| to true. + network_service->CreateNetworkContext(MakeRequest(&network_service_network_context_), CreateNetworkContextParams()); + + // Configure the stub resolver. This must be done after the system + // NetworkContext is created, but before anything has the chance to use it. + // bool stub_resolver_enabled; + // base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> dns_over_https_servers; + // GetStubResolverConfig(local_state_, &stub_resolver_enabled, &dns_over_https_servers); + // content::GetNetworkService()->ConfigureStubHostResolver(stub_resolver_enabled, std::move(dns_over_https_servers)); +} + +void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params) +{ + network_context_params->initial_ssl_config = network::mojom::SSLConfig::New(); + network_context_params->initial_ssl_config->rev_checking_enabled = true; + network_context_params->initial_ssl_config->symantec_enforcement_disabled = true; +} + +network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefaultNetworkContextParams() +{ + network::mojom::NetworkContextParamsPtr network_context_params = network::mojom::NetworkContextParams::New(); + content::UpdateCorsExemptHeader(network_context_params.get()); + + network_context_params->enable_brotli = true; + + // network_context_params->user_agent = GetUserAgent(); + + // Disable referrers by default. Any consumer that enables referrers should + // respect prefs::kEnableReferrers from the appropriate pref store. + network_context_params->enable_referrers = false; + + // const base::CommandLine& command_line = + // *base::CommandLine::ForCurrentProcess(); + + // // TODO(eroman): Figure out why this doesn't work in single-process mode, + // // or if it does work, now. + // // Should be possible now that a private isolate is used. + // // http://crbug.com/474654 + // if (!command_line.HasSwitch(switches::kWinHttpProxyResolver)) { + // if (command_line.HasSwitch(switches::kSingleProcess)) { + // LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; + // } else { + network_context_params->proxy_resolver_factory = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver(); + // } + // } + + // network_context_params->pac_quick_check_enabled = local_state_->GetBoolean(prefs::kQuickCheckEnabled); + + // Use the SystemNetworkContextManager to populate and update SSL + // configuration. The SystemNetworkContextManager is owned by the + // BrowserProcess itself, so will only be destroyed on shutdown, at which + // point, all NetworkContexts will be destroyed as well. + AddSSLConfigToNetworkContextParams(network_context_params.get()); + + // CT is only enabled on Desktop platforms for now. + network_context_params->enforce_chrome_ct_policy = true; + for (const auto &ct_log : certificate_transparency::GetKnownLogs()) { + // TODO(rsleevi): https://crbug.com/702062 - Remove this duplication. + network::mojom::CTLogInfoPtr log_info = network::mojom::CTLogInfo::New(); + log_info->public_key = std::string(ct_log.log_key, ct_log.log_key_length); + log_info->name = ct_log.log_name; + network_context_params->ct_logs.push_back(std::move(log_info)); + } + + network_context_params->http_09_on_non_default_ports_enabled = false; + + return network_context_params; +} + +network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetworkContextParams() +{ + // TODO(mmenke): Set up parameters here (in memory cookie store, etc). + network::mojom::NetworkContextParamsPtr network_context_params = CreateDefaultNetworkContextParams(); + + network_context_params->context_name = std::string("system"); + + network_context_params->enable_referrers = false; + + network_context_params->http_cache_enabled = false; + + // These are needed for PAC scripts that use FTP URLs. +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + network_context_params->enable_ftp_url_support = true; +#endif + + network_context_params->primary_network_context = true; + + proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); + + return network_context_params; +} diff --git a/src/core/net/system_network_context_manager.h b/src/core/net/system_network_context_manager.h new file mode 100644 index 000000000..288af5195 --- /dev/null +++ b/src/core/net/system_network_context_manager.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +// based on chrome/browser/net/system_network_context_manager.h: +// Copyright 2017 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 file. + +#ifndef SYSTEM_NETWORK_CONTEXT_MANAGER_H_ +#define SYSTEM_NETWORK_CONTEXT_MANAGER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/optional.h" +#include "services/network/public/mojom/host_resolver.mojom-forward.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/network_service.mojom-forward.h" +#include "services/network/public/mojom/ssl_config.mojom-forward.h" +#include "services/network/public/mojom/url_loader_factory.mojom-forward.h" + +#include "net/proxy_config_monitor.h" + +namespace network { +namespace mojom { +class URLLoaderFactory; +} +class SharedURLLoaderFactory; +} // namespace network + +namespace net_log { +class NetExportFileWriter; +} + +// Responsible for creating and managing access to the system NetworkContext. +// Lives on the UI thread. The NetworkContext this owns is intended for requests +// not associated with a profile. It stores no data on disk, and has no HTTP +// cache, but it does have ephemeral cookie and channel ID stores. It also does +// not have access to HTTP proxy auth information the user has entered or that +// comes from extensions, and similarly, has no extension-provided per-profile +// proxy configuration information. +// +// This class is also responsible for configuring global NetworkService state. +// +// The "system" NetworkContext will either share a URLRequestContext with +// IOThread's SystemURLRequestContext and be part of IOThread's NetworkService +// (If the network service is disabled) or be an independent NetworkContext +// using the actual network service. +// +// This class is intended to eventually replace IOThread. Handling the two cases +// differently allows this to be used in production without breaking anything or +// requiring two separate paths, while IOThread consumers slowly transition over +// to being compatible with the network service. +class SystemNetworkContextManager +{ +public: + ~SystemNetworkContextManager(); + + // Creates the global instance of SystemNetworkContextManager. If an + // instance already exists, this will cause a DCHECK failure. + static SystemNetworkContextManager *CreateInstance(); + + // Gets the global SystemNetworkContextManager instance. + static SystemNetworkContextManager *GetInstance(); + + // Destroys the global SystemNetworkContextManager instance. + static void DeleteInstance(); + + // If the network service is disabled, |network_context_request| will be for + // the NetworkContext used by the SystemNetworkContextManager and + // |network_context_params| as needed to set up a system NetworkContext. + // Otherwise, this method can still be used to help set up the IOThread's + // in-process URLRequestContext. + // + // Must be called before the system NetworkContext is first used. + // + // |stub_resolver_enabled|, |dns_over_https_servers|, + // |http_auth_static_params|, |http_auth_dynamic_params|, and + // |is_quic_allowed| are used to pass initial NetworkService state to the + // caller, so the NetworkService can be configured appropriately. Using + // NetworkService's Mojo interface to set those options would lead to races + // with other UI->IO thread network-related tasks, since Mojo doesn't preserve + // execution order relative to PostTasks. + void SetUp(network::mojom::NetworkContextRequest *network_context_request, + network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, + base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, + network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, + network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed); + + // Returns the System NetworkContext. May only be called after SetUp(). Does + // any initialization of the NetworkService that may be needed when first + // called. + network::mojom::NetworkContext *GetContext(); + + // Returns a URLLoaderFactory owned by the SystemNetworkContextManager that is + // backed by the SystemNetworkContext. Allows sharing of the URLLoaderFactory. + // Prefer this to creating a new one. Call Clone() on the value returned by + // this method to get a URLLoaderFactory that can be used on other threads. + network::mojom::URLLoaderFactory *GetURLLoaderFactory(); + + // Returns a SharedURLLoaderFactory owned by the SystemNetworkContextManager + // that is backed by the SystemNetworkContext. + scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory(); + + // Called when content creates a NetworkService. Creates the + // SystemNetworkContext, if the network service is enabled. + void OnNetworkServiceCreated(network::mojom::NetworkService *network_service); + + // Populates |initial_ssl_config| and |ssl_config_client_request| members of + // |network_context_params|. As long as the SystemNetworkContextManager + // exists, any NetworkContext created with the params will continue to get + // SSL configuration updates. + void AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params); + + // Returns default set of parameters for configuring the network service. + network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(); + +private: + class URLLoaderFactoryForSystem; + + explicit SystemNetworkContextManager(); + + // Creates parameters for the NetworkContext. May only be called once, since + // it initializes some class members. + network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); + + // ProxyConfigMonitor proxy_config_monitor_; + + // NetworkContext using the network service, if the network service is + // enabled. nullptr, otherwise. + network::mojom::NetworkContextPtr network_service_network_context_; + + // This is a NetworkContext that wraps the IOThread's SystemURLRequestContext. + // Always initialized in SetUp, but it's only returned by Context() when the + // network service is disabled. + network::mojom::NetworkContextPtr io_thread_network_context_; + + // URLLoaderFactory backed by the NetworkContext returned by GetContext(), so + // consumers don't all need to create their own factory. + scoped_refptr<URLLoaderFactoryForSystem> shared_url_loader_factory_; + network::mojom::URLLoaderFactoryPtr url_loader_factory_; + + ProxyConfigMonitor proxy_config_monitor_; + + DISALLOW_COPY_AND_ASSIGN(SystemNetworkContextManager); +}; + +#endif // SYSTEM_NETWORK_CONTEXT_MANAGER_H_ diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp deleted file mode 100644 index 6081a5e9f..000000000 --- a/src/core/net/url_request_context_getter_qt.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "url_request_context_getter_qt.h" -#include "profile_io_data_qt.h" - -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" - -namespace QtWebEngineCore { - -URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -URLRequestContextGetterQt::~URLRequestContextGetterQt() -{ -} - -net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - return m_profileIOData->urlRequestContext(); -} - -scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const -{ - return base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}); -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_custom_job.cpp b/src/core/net/url_request_custom_job.cpp deleted file mode 100644 index 607e8d232..000000000 --- a/src/core/net/url_request_custom_job.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "url_request_custom_job.h" -#include "url_request_custom_job_proxy.h" - -#include "api/qwebengineurlscheme.h" - -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/io_buffer.h" -#include "net/http/http_util.h" - -#include <QIODevice> - -using namespace net; - -namespace QtWebEngineCore { - -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, - NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter) - : URLRequestJob(request, networkDelegate) - , m_proxy(new URLRequestCustomJobProxy(this, scheme, profileAdapter)) - , m_device(nullptr) - , m_error(0) - , m_pendingReadSize(0) - , m_pendingReadPos(0) - , m_pendingReadBuffer(nullptr) - , m_corsEnabled(QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(scheme)) - .flags().testFlag(QWebEngineUrlScheme::CorsEnabled)) -{ -} - -URLRequestCustomJob::~URLRequestCustomJob() -{ - m_proxy->m_job = nullptr; - if (m_device && m_device->isOpen()) - m_device->close(); - m_device = nullptr; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); -} - -void URLRequestCustomJob::Start() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - HttpRequestHeaders requestHeaders = request()->extra_request_headers(); - std::map<std::string, std::string> headers; - net::HttpRequestHeaders::Iterator it(requestHeaders); - while (it.GetNext()) - headers.emplace(it.name(), it.value()); - if (!request()->referrer().empty()) - headers.emplace("Referer", request()->referrer()); - - // TODO: handle UploadDataStream, for instance using a QIODevice wrapper. - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::initialize, - m_proxy, - request()->url(), - request()->method(), - request()->initiator(), - std::move(headers))); -} - -void URLRequestCustomJob::Kill() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_proxy->m_job = nullptr; - if (m_device && m_device->isOpen()) - m_device->close(); - if (m_pendingReadBuffer) { - m_pendingReadBuffer->Release(); - m_pendingReadBuffer = nullptr; - m_pendingReadSize = 0; - m_pendingReadPos = 0; - } - m_device = nullptr; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::release, - m_proxy)); - URLRequestJob::Kill(); -} - -bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_mimeType.size() > 0) { - *mimeType = m_mimeType; - return true; - } - return false; -} - -bool URLRequestCustomJob::GetCharset(std::string *charset) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_charset.size() > 0) { - *charset = m_charset; - return true; - } - return false; -} - -void URLRequestCustomJob::GetResponseInfo(HttpResponseInfo *info) -{ - // Based on net::URLRequestRedirectJob::StartAsync() - - if (m_error) - return; - - std::string headers; - if (m_redirect.is_valid()) { - headers += "HTTP/1.1 303 See Other\n"; - headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); - } else { - headers += base::StringPrintf("HTTP/1.1 %i OK\n", 200); - if (m_mimeType.size() > 0) { - headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); - if (m_charset.size() > 0) - headers += base::StringPrintf("; charset=%s", m_charset.c_str()); - headers += "\n"; - } - } - if (m_corsEnabled) { - std::string origin; - if (request_->extra_request_headers().GetHeader("Origin", &origin)) { - headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str()); - headers += "Access-Control-Allow-Credentials: true\n"; - } - } - - info->headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(headers)); -} - -bool URLRequestCustomJob::IsRedirectResponse(GURL *location, int *http_status_code, bool * /*insecure_scheme_was_upgraded*/) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_redirect.is_valid()) { - *location = m_redirect; - *http_status_code = 303; - return true; - } - return false; -} - -int URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_error) - return m_error; - qint64 rv = m_device ? m_device->read(buf->data(), bufSize) : -1; - if (rv > 0) { - return static_cast<int>(rv); - } else if (rv == 0) { - // Returning zero is interpreted as EOF by Chromium, so only - // return zero if we are the end of the file. - if (m_device->atEnd()) - return 0; - // Otherwise return IO_PENDING and call ReadRawDataComplete when we have data - // for them. - buf->AddRef(); - m_pendingReadPos = 0; - m_pendingReadSize = bufSize; - m_pendingReadBuffer = buf; - return ERR_IO_PENDING; - } else { - // QIODevice::read might have called fail on us. - if (m_error) - return m_error; - if (m_device && m_device->atEnd()) - return 0; - return ERR_FAILED; - } -} - -void URLRequestCustomJob::notifyReadyRead() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_device) - return; - if (!m_pendingReadSize) - return; - Q_ASSERT(m_pendingReadBuffer); - if (!m_pendingReadBuffer) - return; - - qint64 rv = m_device->read(m_pendingReadBuffer->data() + m_pendingReadPos, m_pendingReadSize - m_pendingReadPos); - if (rv == 0) - return; - if (rv < 0) { - if (m_error) - rv = m_error; - else if (m_device->atEnd()) - rv = 0; - else - rv = ERR_FAILED; - } else { - m_pendingReadPos += rv; - if (m_pendingReadPos < m_pendingReadSize && !m_device->atEnd()) - return; - rv = m_pendingReadPos; - } - // killJob may be called from ReadRawDataComplete - net::IOBuffer *buf = m_pendingReadBuffer; - m_pendingReadBuffer = nullptr; - m_pendingReadSize = 0; - m_pendingReadPos = 0; - ReadRawDataComplete(rv); - buf->Release(); -} - -} // namespace diff --git a/src/core/net/url_request_custom_job.h b/src/core/net/url_request_custom_job.h deleted file mode 100644 index af5a6f8e0..000000000 --- a/src/core/net/url_request_custom_job.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef URL_REQUEST_CUSTOM_JOB_H_ -#define URL_REQUEST_CUSTOM_JOB_H_ - -#include "net/url_request/url_request_job.h" -#include "url/gurl.h" -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace QtWebEngineCore { - -class ProfileAdapter; -class URLRequestCustomJobDelegate; -class URLRequestCustomJobProxy; - -// A request job that handles reading custom URL schemes -class URLRequestCustomJob : public net::URLRequestJob -{ -public: - URLRequestCustomJob(net::URLRequest *request, - net::NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter); - void Start() override; - void Kill() override; - int ReadRawData(net::IOBuffer *buf, int buf_size) override; - bool GetMimeType(std::string *mimeType) const override; - bool GetCharset(std::string *charset) override; - void GetResponseInfo(net::HttpResponseInfo *info) override; - bool IsRedirectResponse(GURL *location, int *http_status_code, bool *insecure_scheme_was_upgraded) override; - -protected: - virtual ~URLRequestCustomJob(); - -private: - void notifyReadyRead(); - scoped_refptr<URLRequestCustomJobProxy> m_proxy; - std::string m_mimeType; - std::string m_charset; - GURL m_redirect; - QIODevice *m_device; - int m_error; - int m_pendingReadSize; - int m_pendingReadPos; - net::IOBuffer *m_pendingReadBuffer; - const bool m_corsEnabled; - - friend class URLRequestCustomJobProxy; - - DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); -}; -} // namespace QtWebEngineCore - -#endif // URL_REQUEST_CUSTOM_JOB_H_ diff --git a/src/core/net/url_request_custom_job_delegate.cpp b/src/core/net/url_request_custom_job_delegate.cpp index f73296cf0..ff307bede 100644 --- a/src/core/net/url_request_custom_job_delegate.cpp +++ b/src/core/net/url_request_custom_job_delegate.cpp @@ -92,27 +92,27 @@ void URLRequestCustomJobDelegate::reply(const QByteArray &contentType, QIODevice { if (device) QObject::connect(device, &QIODevice::readyRead, this, &URLRequestCustomJobDelegate::slotReadyRead); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&URLRequestCustomJobProxy::reply, - m_proxy,contentType.toStdString(),device)); + m_proxy->m_ioTaskRunner->PostTask(FROM_HERE, + base::BindOnce(&URLRequestCustomJobProxy::reply, + m_proxy, contentType.toStdString(),device)); } void URLRequestCustomJobDelegate::slotReadyRead() { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&URLRequestCustomJobProxy::readyRead, m_proxy)); + m_proxy->m_ioTaskRunner->PostTask(FROM_HERE, + base::BindOnce(&URLRequestCustomJobProxy::readyRead, m_proxy)); } void URLRequestCustomJobDelegate::abort() { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&URLRequestCustomJobProxy::abort, m_proxy)); + m_proxy->m_ioTaskRunner->PostTask(FROM_HERE, + base::BindOnce(&URLRequestCustomJobProxy::abort, m_proxy)); } void URLRequestCustomJobDelegate::redirect(const QUrl &url) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&URLRequestCustomJobProxy::redirect, m_proxy, toGurl(url))); + m_proxy->m_ioTaskRunner->PostTask(FROM_HERE, + base::BindOnce(&URLRequestCustomJobProxy::redirect, m_proxy, toGurl(url))); } void URLRequestCustomJobDelegate::fail(Error error) @@ -138,8 +138,8 @@ void URLRequestCustomJobDelegate::fail(Error error) break; } if (net_error) { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&URLRequestCustomJobProxy::fail, m_proxy, net_error)); + m_proxy->m_ioTaskRunner->PostTask(FROM_HERE, + base::BindOnce(&URLRequestCustomJobProxy::fail, m_proxy, net_error)); } } diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index 72d14450e..d2df64f2f 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -38,28 +38,29 @@ ****************************************************************************/ #include "url_request_custom_job_proxy.h" -#include "url_request_custom_job.h" #include "url_request_custom_job_delegate.h" + +#include "content/public/browser/browser_thread.h" +#include "net/base/net_errors.h" + #include "api/qwebengineurlrequestjob.h" #include "profile_adapter.h" #include "type_conversion.h" -#include "content/public/browser/browser_thread.h" #include "web_engine_context.h" -using namespace net; - namespace QtWebEngineCore { -URLRequestCustomJobProxy::URLRequestCustomJobProxy(URLRequestCustomJob *job, +URLRequestCustomJobProxy::URLRequestCustomJobProxy(URLRequestCustomJobProxy::Client *client, const std::string &scheme, QPointer<ProfileAdapter> profileAdapter) - : m_job(job) + : m_client(client) , m_started(false) , m_scheme(scheme) , m_delegate(nullptr) , m_profileAdapter(profileAdapter) + , m_ioTaskRunner(m_client->taskRunner()) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(m_ioTaskRunner && m_ioTaskRunner->RunsTasksInCurrentSequence()); } URLRequestCustomJobProxy::~URLRequestCustomJobProxy() @@ -87,69 +88,74 @@ void URLRequestCustomJobProxy::setReplyCharset(const std::string &charset) */ void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_job) + if (!m_client) return; - m_job->m_mimeType = mimeType; - m_job->m_device = device; - if (m_job->m_device && !m_job->m_device->isReadable()) - m_job->m_device->open(QIODevice::ReadOnly); - - qint64 size = m_job->m_device ? m_job->m_device->size() : -1; - if (size > 0) - m_job->set_expected_content_size(size); - if (m_job->m_device && m_job->m_device->isReadable()) { + DCHECK (!m_ioTaskRunner || m_ioTaskRunner->RunsTasksInCurrentSequence()); + m_client->m_mimeType = mimeType; + m_client->m_device = device; + if (m_client->m_device && !m_client->m_device->isReadable()) + m_client->m_device->open(QIODevice::ReadOnly); + + if (m_client->m_firstBytePosition > 0) + m_client->m_device->seek(m_client->m_firstBytePosition); + + qint64 deviceSize = m_client->m_device ? m_client->m_device->size() : -1; + qint64 remainingBytes = deviceSize - m_client->m_firstBytePosition; + if (remainingBytes > 0) + m_client->notifyExpectedContentSize(remainingBytes); + + if (m_client->m_device && m_client->m_device->isReadable()) { m_started = true; - m_job->NotifyHeadersComplete(); + m_client->notifyHeadersComplete(); } else { - fail(ERR_INVALID_URL); + fail(net::ERR_INVALID_URL); } } void URLRequestCustomJobProxy::redirect(GURL url) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_job) + if (!m_client) return; - if (m_job->m_device || m_job->m_error) + DCHECK (!m_ioTaskRunner || m_ioTaskRunner->RunsTasksInCurrentSequence()); + if (m_client->m_device || m_client->m_error) return; - m_job->m_redirect = url; + m_client->m_redirect = url; m_started = true; - m_job->NotifyHeadersComplete(); + m_client->notifyHeadersComplete(); } void URLRequestCustomJobProxy::abort() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_job) + if (!m_client) return; - if (m_job->m_device && m_job->m_device->isOpen()) - m_job->m_device->close(); - m_job->m_device = nullptr; + DCHECK (!m_ioTaskRunner || m_ioTaskRunner->RunsTasksInCurrentSequence()); + if (m_client->m_device && m_client->m_device->isOpen()) + m_client->m_device->close(); + m_client->m_device = nullptr; if (m_started) - m_job->NotifyCanceled(); + m_client->notifyCanceled(); else - m_job->NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED)); + m_client->notifyAborted(); } void URLRequestCustomJobProxy::fail(int error) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!m_job) + if (!m_client) return; - m_job->m_error = error; - if (m_job->m_device) - m_job->m_device->close(); + DCHECK (m_ioTaskRunner->RunsTasksInCurrentSequence()); + m_client->m_error = error; + if (m_client->m_device) + m_client->m_device->close(); if (!m_started) - m_job->NotifyStartError(URLRequestStatus::FromError(error)); + m_client->notifyStartFailure(error); // else we fail on the next read, or the read that might already be in progress } void URLRequestCustomJobProxy::readyRead() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_job) - m_job->notifyReadyRead(); + DCHECK (m_ioTaskRunner->RunsTasksInCurrentSequence()); + if (m_client) + m_client->notifyReadyRead(); } void URLRequestCustomJobProxy::initialize(GURL url, std::string method, diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h index d4cd7e208..db38083dd 100644 --- a/src/core/net/url_request_custom_job_proxy.h +++ b/src/core/net/url_request_custom_job_proxy.h @@ -42,6 +42,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/task_runner.h" #include "url/gurl.h" #include "url/origin.h" #include <QtCore/QPointer> @@ -60,7 +61,24 @@ class URLRequestCustomJobProxy : public base::RefCountedThreadSafe<URLRequestCus { public: - URLRequestCustomJobProxy(URLRequestCustomJob *job, + class Client { + public: + std::string m_mimeType; + std::string m_charset; + GURL m_redirect; + QIODevice *m_device; + int64_t m_firstBytePosition; + int m_error; + virtual void notifyExpectedContentSize(qint64 size) = 0; + virtual void notifyHeadersComplete() = 0; + virtual void notifyCanceled() = 0; + virtual void notifyAborted() = 0; + virtual void notifyStartFailure(int) = 0; + virtual void notifyReadyRead() = 0; + virtual base::TaskRunner *taskRunner() = 0; + }; + + URLRequestCustomJobProxy(Client *client, const std::string &scheme, QPointer<ProfileAdapter> profileAdapter); ~URLRequestCustomJobProxy(); @@ -76,13 +94,14 @@ public: void readyRead(); // IO thread owned: - URLRequestCustomJob *m_job; + Client *m_client; bool m_started; // UI thread owned: std::string m_scheme; URLRequestCustomJobDelegate *m_delegate; QPointer<ProfileAdapter> m_profileAdapter; + scoped_refptr<base::TaskRunner> m_ioTaskRunner; }; } // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.cpp b/src/core/net/url_request_notification.cpp deleted file mode 100644 index fa6d61f65..000000000 --- a/src/core/net/url_request_notification.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "url_request_notification.h" - -#include "base/supports_user_data.h" -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_thread.h" -#include "net/url_request/url_request.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" -#include "profile_io_data_qt.h" -#include "qwebengineurlrequestinfo_p.h" -#include "type_conversion.h" - -namespace QtWebEngineCore { - -// Calls cancel() when the URLRequest is destroyed. -class UserData : public base::SupportsUserData::Data -{ -public: - UserData(URLRequestNotification *ptr) : m_ptr(ptr) {} - ~UserData() { m_ptr->cancel(); } - static const char key[]; - -private: - URLRequestNotification *m_ptr; -}; - -const char UserData::key[] = "QtWebEngineCore::URLRequestNotification"; - -static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType) -{ - return static_cast<content::ResourceType>(resourceType); -} - -URLRequestNotification::URLRequestNotification(net::URLRequest *request, bool isMainFrameRequest, GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, QPointer<ProfileAdapter> adapter) - : m_request(request) - , m_isMainFrameRequest(isMainFrameRequest) - , m_newUrl(newUrl) - , m_originalUrl(requestInfo.requestUrl()) - , m_requestInfo(std::move(requestInfo)) - , m_webContentsGetter(webContentsGetter) - , m_callback(std::move(callback)) - , m_profileAdapter(adapter) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - m_request->SetUserData(UserData::key, std::make_unique<UserData>(this)); - - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::UI}, - base::BindOnce(&URLRequestNotification::notify, base::Unretained(this))); -} - - -void URLRequestNotification::notify() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // May run concurrently with cancel() so no peeking at m_request here. - - int result = net::OK; - content::WebContents *webContents = m_webContentsGetter.Run(); - - if (webContents) { - - if (m_profileAdapter && m_profileAdapter->requestInterceptor()) { - QWebEngineUrlRequestInterceptor *interceptor = m_profileAdapter->requestInterceptor(); - if (!interceptor->property("deprecated").toBool()) - interceptor->interceptRequest(m_requestInfo); - } - - WebContentsAdapterClient *client = - WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - - if (!m_requestInfo.changed()) { - client->interceptRequest(m_requestInfo); - } - - if (m_requestInfo.changed()) { - result = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - // We handle the rest of the changes later when we are back in I/O thread - } - - // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources - if (result == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) { - int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; - client->navigationRequested(m_requestInfo.navigationType(), - m_requestInfo.requestUrl(), - navigationRequestAction, - m_isMainFrameRequest); - result = net::ERR_FAILED; - switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) { - case WebContentsAdapterClient::AcceptRequest: - result = net::OK; - break; - case WebContentsAdapterClient::IgnoreRequest: - result = net::ERR_ABORTED; - break; - } - DCHECK(result != net::ERR_FAILED); - } - } - - // Run the callback on the IO thread. - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::IO}, - base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), result)); -} - -void URLRequestNotification::cancel() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - // May run concurrently with notify() but we only touch m_request here. - - m_request = nullptr; -} - -void URLRequestNotification::complete(int error) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (m_request) { - if (m_requestInfo.changed()) { - if (m_originalUrl != m_requestInfo.d_ptr->url) - *m_newUrl = toGurl(m_requestInfo.d_ptr->url); - - if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) { - auto end = m_requestInfo.d_ptr->extraHeaders.constEnd(); - for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - m_request->SetReferrer(header.value().toStdString()); - } else { - m_request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - } - - if (m_request->status().status() != net::URLRequestStatus::CANCELED) - std::move(m_callback).Run(error); - m_request->RemoveUserData(UserData::key); - } - - delete this; -} - -} diff --git a/src/core/printing/pdfium_document_wrapper_qt.cpp b/src/core/printing/pdfium_document_wrapper_qt.cpp index 6f415b50b..dae6ec44b 100644 --- a/src/core/printing/pdfium_document_wrapper_qt.cpp +++ b/src/core/printing/pdfium_document_wrapper_qt.cpp @@ -48,64 +48,6 @@ namespace QtWebEngineCore { int PdfiumDocumentWrapperQt::m_libraryUsers = 0; -class PdfiumPageWrapperQt { -public: - PdfiumPageWrapperQt(FPDF_DOCUMENT data, int pageIndex) - : m_pageData(FPDF_LoadPage(data, pageIndex)) - , m_width(FPDF_GetPageWidth(m_pageData)) - , m_height(FPDF_GetPageHeight(m_pageData)) - , m_image(createImage()) - { - } - - PdfiumPageWrapperQt() - : m_pageData(nullptr) - , m_width(-1) - , m_height(-1) - , m_image(QImage()) - { - } - - virtual ~PdfiumPageWrapperQt() - { - FPDF_ClosePage(m_pageData); - } - - QImage image() - { - return m_image; - } - -private: - QImage createImage() - { - Q_ASSERT(m_pageData); - - QImage image(m_width * 2, m_height * 2, QImage::Format_ARGB32); - Q_ASSERT(!image.isNull()); - image.fill(0xFFFFFFFF); - - FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(image.width(), image.height(), - FPDFBitmap_BGRA, - image.scanLine(0), image.bytesPerLine()); - Q_ASSERT(bitmap); - - FPDF_RenderPageBitmap(bitmap, m_pageData, - 0, 0, image.width(), image.height(), - 0, 0); - FPDFBitmap_Destroy(bitmap); - bitmap = nullptr; - return image; - } - -private: - FPDF_PAGE m_pageData; - int m_width; - int m_height; - QImage m_image; -}; - - PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const char *password) { @@ -118,27 +60,41 @@ PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t siz m_pageCount = FPDF_GetPageCount((FPDF_DOCUMENT)m_documentHandle); } -QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) +QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t pageIndex,int width , int height) { if (!m_documentHandle || !m_pageCount) { qWarning("Failure to generate QImage from invalid or empty PDF document."); return QImage(); } - if (static_cast<int>(index) >= m_pageCount) { + if (static_cast<int>(pageIndex) >= m_pageCount) { qWarning("Failure to generate QImage from PDF data: index out of bounds."); return QImage(); } - PdfiumPageWrapperQt pageWrapper((FPDF_DOCUMENT)m_documentHandle, index); - return pageWrapper.image(); + FPDF_PAGE pageData(FPDF_LoadPage((FPDF_DOCUMENT)m_documentHandle, pageIndex)); + QImage image(width, height, QImage::Format_ARGB32); + Q_ASSERT(!image.isNull()); + image.fill(0xFFFFFFFF); + + FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(width, height, + FPDFBitmap_BGRA, + image.scanLine(0), image.bytesPerLine()); + Q_ASSERT(bitmap); + FPDF_RenderPageBitmap(bitmap, pageData, + 0, 0, width, height, + 0, 0); + FPDFBitmap_Destroy(bitmap); + bitmap = nullptr; + FPDF_ClosePage(pageData); + return image; } -bool PdfiumDocumentWrapperQt::pageIsLandscape(size_t index) +QSizeF PdfiumDocumentWrapperQt::pageSize(size_t index) { - double width = 0, height = 0; - FPDF_GetPageSizeByIndex((FPDF_DOCUMENT)m_documentHandle, index, &width, &height); - return (width > height); + QSizeF size; + FPDF_GetPageSizeByIndex((FPDF_DOCUMENT)m_documentHandle, index, &size.rwidth(), &size.rheight()); + return size; } PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() @@ -147,5 +103,4 @@ PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() if (--m_libraryUsers == 0) FPDF_DestroyLibrary(); } - } diff --git a/src/core/printing/pdfium_document_wrapper_qt.h b/src/core/printing/pdfium_document_wrapper_qt.h index 121742aa3..e0778c32b 100644 --- a/src/core/printing/pdfium_document_wrapper_qt.h +++ b/src/core/printing/pdfium_document_wrapper_qt.h @@ -56,15 +56,14 @@ #include <QtGui/qimage.h> namespace QtWebEngineCore { -class PdfiumPageWrapperQt; class Q_WEBENGINECORE_PRIVATE_EXPORT PdfiumDocumentWrapperQt { public: PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const char *password = nullptr); virtual ~PdfiumDocumentWrapperQt(); - QImage pageAsQImage(size_t index); - bool pageIsLandscape(size_t index); + QImage pageAsQImage(size_t index, int width , int height); + QSizeF pageSize(size_t index); int pageCount() const { return m_pageCount; } private: diff --git a/src/core/process_main.cpp b/src/core/process_main.cpp index d661d3b90..ade0f6e99 100644 --- a/src/core/process_main.cpp +++ b/src/core/process_main.cpp @@ -49,20 +49,27 @@ #include "sandbox/mac/seatbelt_exec.h" #endif -namespace QtWebEngine { +namespace QtWebEngineCore { + +#if defined(OS_WIN) +extern sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info = nullptr); +#endif /*! \internal */ int processMain(int argc, const char **argv) { - QtWebEngineCore::ContentMainDelegateQt delegate; + ContentMainDelegateQt delegate; content::ContentMainParams params(&delegate); #if defined(OS_WIN) HINSTANCE instance_handle = NULL; + params.sandbox_info = staticSandboxInterfaceInfo(); sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); + if (!params.sandbox_info) { + content::InitializeSandboxInfo(&sandbox_info); + params.sandbox_info = &sandbox_info; + } params.instance = instance_handle; - params.sandbox_info = &sandbox_info; #else params.argc = argc; params.argv = argv; @@ -78,4 +85,4 @@ int processMain(int argc, const char **argv) return content::ContentMain(params); } -} // namespace +} // namespace QtWebEngineCore diff --git a/src/core/process_main.h b/src/core/process_main.h index 00c029d9f..fed2f3064 100644 --- a/src/core/process_main.h +++ b/src/core/process_main.h @@ -50,7 +50,7 @@ #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> -namespace QtWebEngine { +namespace QtWebEngineCore { Q_WEBENGINECORE_PRIVATE_EXPORT int processMain(int argc, const char **argv); diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index d421edf00..80edf40bf 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -47,7 +47,6 @@ #include "api/qwebengineurlscheme.h" #include "content_browser_client_qt.h" #include "download_manager_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" #include "profile_adapter_client.h" #include "profile_qt.h" @@ -193,8 +192,7 @@ void ProfileAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *inte Q_ASSERT(!m_profile->m_profileIOData->requestInterceptor()); }); - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateRequestInterceptor(); + m_profile->m_profileIOData->updateRequestInterceptor(); } void ProfileAdapter::addClient(ProfileAdapterClient *adapterClient) @@ -210,16 +208,14 @@ void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient) void ProfileAdapter::addPageRequestInterceptor() { ++m_pageRequestInterceptors; - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateRequestInterceptor(); + m_profile->m_profileIOData->updateRequestInterceptor(); } void ProfileAdapter::removePageRequestInterceptor() { Q_ASSERT(m_pageRequestInterceptors > 0); --m_pageRequestInterceptors; - if (m_profile->m_urlRequestContextGetter.get()) - m_profile->m_profileIOData->updateRequestInterceptor(); + m_profile->m_profileIOData->updateRequestInterceptor(); } @@ -715,13 +711,6 @@ QString ProfileAdapter::determineDownloadPath(const QString &downloadDirectory, return suggestedFilePath; } -QString ProfileAdapter::updateDownloadPath(int downloadId, const QString &directory, const QString &fileName) -{ - download::DownloadItem *download = m_downloadManagerDelegate->findDownloadById(downloadId); - Q_ASSERT(download); - return determineDownloadPath(directory, fileName, download->GetStartTime().ToTimeT()); -} - #if QT_CONFIG(ssl) QWebEngineClientCertificateStore *ProfileAdapter::clientCertificateStore() { diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 01477d0d9..1b89a8004 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -214,7 +214,6 @@ public: { return m_persistentNotifications; } QString determineDownloadPath(const QString &downloadDirectory, const QString &suggestedFilename, const time_t &startTime); - QString updateDownloadPath(int downloadId, const QString &directory, const QString &filename); private: void updateCustomUrlSchemeHandlers(); diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h index dc0f508a1..394f92270 100644 --- a/src/core/profile_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -140,7 +140,7 @@ public: int downloadInterruptReason; WebContentsAdapterClient *page; QString suggestedFileName; - time_t startTime; + qint64 startTime; }; virtual ~ProfileAdapterClient() { } diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index 68be09ad2..ef8f30e10 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -40,131 +40,36 @@ #include "profile_io_data_qt.h" #include "base/task/post_task.h" -#include "components/certificate_transparency/ct_known_logs.h" -#include "components/network_session_configurator/common/network_features.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" -#include "content/public/browser/cookie_store_factory.h" +#include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/common/content_features.h" -#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" -#include "chrome/common/chrome_switches.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_policy_enforcer.h" -#include "net/cert/multi_log_ct_verifier.h" -#include "net/cert_net/cert_net_fetcher_impl.h" -#include "net/ftp/ftp_auth_cache.h" -#include "net/dns/host_resolver_manager.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_auth_scheme.h" -#include "net/http/http_auth_preferences.h" -#include "net/http/http_cache.h" -#include "net/http/http_server_properties_impl.h" -#include "net/http/http_network_session.h" -#include "net/http/transport_security_persister.h" -#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h" -#include "net/proxy_resolution/pac_file_fetcher_impl.h" #include "net/proxy_resolution/proxy_config_service.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/ssl/ssl_config_service_defaults.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/file_protocol_handler.h" -#include "net/url_request/ftp_protocol_handler.h" -#include "net/url_request/static_http_user_agent_settings.h" -#include "net/url_request/url_request_context_storage.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "net/url_request/url_request_intercepting_job_factory.h" #include "services/file/user_id_map.h" #include "services/network/proxy_service_mojo.h" -#include "services/network/restricted_cookie_manager.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/cors/origin_access_list.h" #include "net/client_cert_override.h" #include "net/client_cert_store_data.h" #include "net/cookie_monster_delegate_qt.h" -#include "net/custom_protocol_handler.h" -#include "net/network_delegate_qt.h" #include "net/proxy_config_service_qt.h" -#include "net/restricted_cookie_manager_qt.h" -#include "net/url_request_context_getter_qt.h" +#include "net/system_network_context_manager.h" #include "profile_qt.h" #include "resource_context_qt.h" #include "type_conversion.h" -#if defined(USE_NSS_CERTS) -#include "net/cert_net/nss_ocsp.h" -#endif - -#if defined(OS_LINUX) || defined(OS_MACOSX) -#include "net/cert/cert_net_fetcher.h" -#include "net/cert_net/cert_net_fetcher_impl.h" -#endif - #include <mutex> +#include <QVariant> namespace QtWebEngineCore { -static scoped_refptr<net::CertNetFetcherImpl> s_certNetFetcher; - -static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, - const net::HttpNetworkSession::Params &second) -{ - if (first.ignore_certificate_errors != second.ignore_certificate_errors) - return false; - return true; -} - -static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, - const net::HttpNetworkSession::Context &second) -{ - if (first.transport_security_state != second.transport_security_state) - return false; - if (first.cert_verifier != second.cert_verifier) - return false; - if (first.proxy_resolution_service != second.proxy_resolution_service) - return false; - if (first.ssl_config_service != second.ssl_config_service) - return false; - if (first.http_auth_handler_factory != second.http_auth_handler_factory) - return false; - if (first.http_user_agent_settings != second.http_user_agent_settings) - return false; - if (first.http_server_properties != second.http_server_properties) - return false; - if (first.host_resolver != second.host_resolver) - return false; - if (first.cert_transparency_verifier != second.cert_transparency_verifier) - return false; - if (first.ct_policy_enforcer != second.ct_policy_enforcer) - return false; - return true; -} - -static net::HttpNetworkSession::Context generateNetworkSessionContext(net::URLRequestContext *urlRequestContext) -{ - net::HttpNetworkSession::Context network_session_context; - network_session_context.transport_security_state = urlRequestContext->transport_security_state(); - network_session_context.cert_verifier = urlRequestContext->cert_verifier(); - network_session_context.proxy_resolution_service = urlRequestContext->proxy_resolution_service(); - network_session_context.ssl_config_service = urlRequestContext->ssl_config_service(); - network_session_context.http_auth_handler_factory = urlRequestContext->http_auth_handler_factory(); - network_session_context.http_user_agent_settings = urlRequestContext->http_user_agent_settings(); - network_session_context.http_server_properties = urlRequestContext->http_server_properties(); - network_session_context.host_resolver = urlRequestContext->host_resolver(); - network_session_context.cert_transparency_verifier = urlRequestContext->cert_transparency_verifier(); - network_session_context.ct_policy_enforcer = urlRequestContext->ct_policy_enforcer(); - return network_session_context; -} - -static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreCertificateErrors) -{ - net::HttpNetworkSession::Params network_session_params; - network_session_params.ignore_certificate_errors = ignoreCertificateErrors; - return network_session_params; -} - ProfileIODataQt::ProfileIODataQt(ProfileQt *profile) : m_profile(profile), #if QT_CONFIG(ssl) @@ -182,27 +87,7 @@ ProfileIODataQt::~ProfileIODataQt() if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO)) DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_useForGlobalCertificateVerification) { -#if defined(USE_NSS_CERTS) - net::SetURLRequestContextForNSSHttpIO(nullptr); -#endif - if (s_certNetFetcher) { - s_certNetFetcher->Shutdown(); - s_certNetFetcher.reset(); - } - } - - if (m_urlRequestContext) { - if (m_urlRequestContext->proxy_resolution_service()) - m_urlRequestContext->proxy_resolution_service()->OnShutdown(); - m_restrictedCookieManagerBindings.CloseAllBindings(); - cancelAllUrlRequests(); - } - m_resourceContext.reset(); - if (m_cookieDelegate) - m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted - m_networkDelegate.reset(); delete m_proxyConfigService.fetchAndStoreAcquire(0); } @@ -218,6 +103,9 @@ void ProfileIODataQt::shutdownOnUIThread() delete m_clientCertificateStoreData; m_clientCertificateStoreData = nullptr; #endif + if (m_cookieDelegate) + m_cookieDelegate->unsetMojoCookieManager(); + m_proxyConfigMonitor.reset(); bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this); if (!posted) { qWarning() << "Could not delete ProfileIODataQt on io thread !"; @@ -230,7 +118,7 @@ net::URLRequestContext *ProfileIODataQt::urlRequestContext() DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!m_initialized) initializeOnIOThread(); - return m_urlRequestContext.get(); + return nullptr; } content::ResourceContext *ProfileIODataQt::resourceContext() @@ -248,22 +136,23 @@ extensions::ExtensionSystemQt* ProfileIODataQt::GetExtensionSystem() base::WeakPtr<ProfileIODataQt> ProfileIODataQt::getWeakPtrOnUIThread() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(m_initialized); return m_weakPtr; } +base::WeakPtr<ProfileIODataQt> ProfileIODataQt::getWeakPtrOnIOThread() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + return m_weakPtrFactory.GetWeakPtr(); +} + void ProfileIODataQt::initializeOnIOThread() { - m_networkDelegate.reset(new NetworkDelegateQt(this)); - m_hostResolver = net::HostResolver::CreateStandaloneResolver(nullptr); - m_urlRequestContext.reset(new net::URLRequestContext()); - m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); - m_urlRequestContext->set_enable_brotli(true); - m_urlRequestContext->set_host_resolver(m_hostResolver.get()); // this binds factory to io thread m_weakPtr = m_weakPtrFactory.GetWeakPtr(); const std::lock_guard<QRecursiveMutex> lock(m_mutex); generateAllStorage(); - generateJobFactory(); +// generateJobFactory(); setGlobalCertificateVerification(); m_initialized = true; } @@ -279,294 +168,22 @@ void ProfileIODataQt::initializeOnUIThread() m_protocolHandlerRegistryIOThreadDelegate = protocolHandlerRegistry->io_thread_delegate(); m_cookieDelegate = new CookieMonsterDelegateQt(); m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore()); - createProxyConfig(); -} - -void ProfileIODataQt::cancelAllUrlRequests() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests(); - std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); - std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); - for ( ; it != end; ++it) { - net::URLRequest* request = const_cast<net::URLRequest*>(*it); - if (request) - request->Cancel(); - } + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + m_proxyConfigMonitor.reset(new ProxyConfigMonitor(m_profile->GetPrefs())); + else + createProxyConfig(); } void ProfileIODataQt::generateAllStorage() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); const std::lock_guard<QRecursiveMutex> lock(m_mutex); - generateStorage(); - generateCookieStore(); - generateUserAgent(); - generateHttpCache(); m_updateAllStorage = false; } -void ProfileIODataQt::generateStorage() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); -// Q_ASSERT(!m_mutex.tryLock()); // assert locked - - // We must stop all requests before deleting their backends. - if (m_storage) { - m_urlRequestContext->proxy_resolution_service()->OnShutdown(); - m_restrictedCookieManagerBindings.CloseAllBindings(); - m_cookieDelegate->setCookieMonster(nullptr); - m_storage->set_cookie_store(nullptr); - cancelAllUrlRequests(); - // we need to get rid of dangling pointer due to coming storage deletion - m_urlRequestContext->set_http_transaction_factory(nullptr); - m_httpNetworkSession.reset(); - m_transportSecurityPersister.reset(); - } - - m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); - - net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); - Q_ASSERT(proxyConfigService); - - std::unique_ptr<net::CertVerifier> cert_verifier = net::CertVerifier::CreateDefault(s_certNetFetcher); - net::CertVerifier::Config config; - // Enable revocation checking: - config.enable_rev_checking = true; - // Mirroring Android WebView (we have no beef with Symantec, and our users might use them): - config.disable_symantec_enforcement = true; - cert_verifier->SetConfig(config); - - m_storage->set_cert_verifier(std::move(cert_verifier)); - std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); - std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs; - for (const auto &ct_log : certificate_transparency::GetKnownLogs()) { - scoped_refptr<const net::CTLogVerifier> log_verifier = - net::CTLogVerifier::Create(std::string(ct_log.log_key, ct_log.log_key_length), - ct_log.log_name); - if (!log_verifier) - continue; - ct_logs.push_back(std::move(log_verifier)); - } - ct_verifier->AddLogs(ct_logs); - m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); - m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer())); - m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>()); - if (!m_httpAuthPreferences) { - m_httpAuthPreferences.reset(new net::HttpAuthPreferences()); - std::string serverWhitelist = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kAuthServerWhitelist); - m_httpAuthPreferences->SetServerWhitelist(serverWhitelist); - } - m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( - m_httpAuthPreferences.get())); - m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>()); - - if (!m_dataPath.isEmpty()) { - scoped_refptr<base::SequencedTaskRunner> background_task_runner( - base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), - base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})); - m_transportSecurityPersister = - std::make_unique<net::TransportSecurityPersister>( - m_urlRequestContext->transport_security_state(), - toFilePath(m_dataPath), - background_task_runner); - }; - - m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>( - new net::HttpServerPropertiesImpl)); - - // The System Proxy Resolver has issues on Windows with unconfigured network cards, - // which is why we want to use the v8 one - if (!m_dhcpPacFileFetcherFactory) - m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory); - - proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); - m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory( - std::move(proxyResolver), - std::unique_ptr<net::ProxyConfigService>(proxyConfigService), - net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()), - m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()), - m_urlRequestContext->host_resolver(), - nullptr /* NetLog */, - m_urlRequestContext->network_delegate())); - - m_storage->set_ftp_auth_cache(std::make_unique<net::FtpAuthCache>()); -} - - -void ProfileIODataQt::generateCookieStore() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - - // FIXME: Add code to remove the old channel-id database. - - std::unique_ptr<net::CookieStore> cookieStore; - switch (m_persistentCookiesPolicy) { - case ProfileAdapter::NoPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - base::FilePath(), - false, - false, - nullptr), - nullptr); - break; - case ProfileAdapter::AllowPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - false, - true, - nullptr), - nullptr); - break; - case ProfileAdapter::ForcePersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - true, - true, - nullptr), - nullptr); - break; - } - - net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get()); - m_cookieDelegate->setCookieMonster(cookieMonster); - m_storage->set_cookie_store(std::move(cookieStore)); - - const std::vector<std::string> cookieableSchemes(kCookieableSchemes, - kCookieableSchemes + base::size(kCookieableSchemes)); - cookieMonster->SetCookieableSchemes(cookieableSchemes, base::DoNothing()); -} - -void ProfileIODataQt::generateUserAgent() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( - new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), - m_httpUserAgent.toStdString()))); -} - -void ProfileIODataQt::generateHttpCache() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - - net::HttpCache::DefaultBackend* main_backend = 0; - switch (m_httpCacheType) { - case ProfileAdapter::MemoryHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::MEMORY_CACHE, - net::CACHE_BACKEND_DEFAULT, - base::FilePath(), - m_httpCacheMaxSize - ); - break; - case ProfileAdapter::DiskHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::DISK_CACHE, - net::CACHE_BACKEND_DEFAULT, - toFilePath(m_httpCachePath), - m_httpCacheMaxSize - ); - break; - case ProfileAdapter::NoCache: - // It's safe to not create BackendFactory. - break; - } - - net::HttpCache *cache = 0; - net::HttpNetworkSession::Context network_session_context = - generateNetworkSessionContext(m_urlRequestContext.get()); - net::HttpNetworkSession::Params network_session_params = - generateNetworkSessionParams(m_ignoreCertificateErrors); - - if (!m_httpNetworkSession - || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) - || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { - m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, - network_session_context)); - } - - cache = new net::HttpCache(m_httpNetworkSession.get(), - std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false); - - m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); -} - -void ProfileIODataQt::generateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(!m_jobFactory); - - const std::lock_guard<QRecursiveMutex> lock(m_mutex); - m_updateJobFactory = false; - - std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); - for (auto &it : m_protocolHandlers) - jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release())); - m_protocolHandlers.clear(); - - jobFactory->SetProtocolHandler(url::kDataScheme, - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new net::DataProtocolHandler())); - scoped_refptr<base::TaskRunner> taskRunner(base::CreateTaskRunnerWithTraits({base::MayBlock(), - base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); - jobFactory->SetProtocolHandler(url::kFileScheme, - std::make_unique<net::FileProtocolHandler>(taskRunner)); - jobFactory->SetProtocolHandler(url::kFtpScheme, - net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver(), m_urlRequestContext->ftp_auth_cache())); - - m_installedCustomSchemes = m_customUrlSchemes; - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - jobFactory->SetProtocolHandler(scheme.toStdString(), - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new CustomProtocolHandler(m_profileAdapter))); - } - - m_baseJobFactory = jobFactory.get(); - - // Set up interceptors in the reverse order. - std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); - content::URLRequestInterceptorScopedVector::reverse_iterator i; - for (i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { - topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), - std::move(*i))); - } - - m_requestInterceptors.clear(); - - m_jobFactory = std::move(topJobFactory); - - m_urlRequestContext->set_job_factory(m_jobFactory.get()); -} - void ProfileIODataQt::regenerateJobFactory() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_jobFactory); - Q_ASSERT(m_baseJobFactory); const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_updateJobFactory = false; @@ -574,31 +191,13 @@ void ProfileIODataQt::regenerateJobFactory() if (m_customUrlSchemes == m_installedCustomSchemes) return; - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); - } - m_installedCustomSchemes = m_customUrlSchemes; - for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), - std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( - new CustomProtocolHandler(m_profileAdapter))); - } } void ProfileIODataQt::setGlobalCertificateVerification() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); const std::lock_guard<QRecursiveMutex> lock(m_mutex); - if (m_useForGlobalCertificateVerification) { -#if defined(USE_NSS_CERTS) - // Set request context used by NSS for OCSP requests. - net::SetURLRequestContextForNSSHttpIO(m_urlRequestContext.get()); -#endif - if (!s_certNetFetcher) - s_certNetFetcher = base::MakeRefCounted<net::CertNetFetcherImpl>(); - s_certNetFetcher->SetURLRequestContext(m_urlRequestContext.get()); - } } void ProfileIODataQt::setRequestContextData(content::ProtocolHandlerMap *protocolHandlers, @@ -630,7 +229,8 @@ void ProfileIODataQt::requestStorageGeneration() { const std::lock_guard<QRecursiveMutex> lock(m_mutex); if (m_initialized && !m_updateAllStorage) { m_updateAllStorage = true; - createProxyConfig(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + createProxyConfig(); base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr)); } @@ -639,20 +239,17 @@ void ProfileIODataQt::requestStorageGeneration() { // TODO(miklocek): mojofy ProxyConfigServiceQt void ProfileIODataQt::createProxyConfig() { + Q_ASSERT(!base::FeatureList::IsEnabled(network::features::kNetworkService)); Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); const std::lock_guard<QRecursiveMutex> lock(m_mutex); // We must create the proxy config service on the UI loop on Linux because it // must synchronously run on the glib message loop. This will be passed to // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). Q_ASSERT(m_proxyConfigService == 0); - net::ProxyConfigWithAnnotation initialConfig; - ProxyPrefs::ConfigState initialConfigState = PrefProxyConfigTrackerImpl::ReadPrefConfig( - m_profileAdapter->profile()->GetPrefs(), &initialConfig); m_proxyConfigService = new ProxyConfigServiceQt( - net::ProxyResolutionService::CreateSystemProxyConfigService( - base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})), - initialConfig, initialConfigState); + m_profileAdapter->profile()->GetPrefs(), + base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})); //pass interface to io thread m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver(); } @@ -751,6 +348,7 @@ bool ProfileIODataQt::isInterceptorDeprecated() const QWebEngineUrlRequestInterceptor *ProfileIODataQt::acquireInterceptor() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); m_mutex.lock(); return m_requestInterceptor; } @@ -769,6 +367,7 @@ bool ProfileIODataQt::hasPageInterceptors() void ProfileIODataQt::releaseInterceptor() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); m_mutex.unlock(); } @@ -811,21 +410,56 @@ std::unique_ptr<net::ClientCertStore> ProfileIODataQt::CreateClientCertStore() #endif } -void ProfileIODataQt::CreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRequest request, - network::mojom::RestrictedCookieManagerRole role, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t routing_id) +network::mojom::NetworkContextParamsPtr ProfileIODataQt::CreateNetworkContextParams() { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - m_restrictedCookieManagerBindings.AddBinding( - std::make_unique<RestrictedCookieManagerQt>( - m_weakPtr, - role, urlRequestContext()->cookie_store(), - &m_cookieSettings, origin, - is_service_worker, process_id, routing_id), - std::move(request)); + updateStorageSettings(); + + network::mojom::NetworkContextParamsPtr network_context_params = + SystemNetworkContextManager::GetInstance()->CreateDefaultNetworkContextParams(); + + network_context_params->context_name = m_profile->profileAdapter()->storageName().toStdString(); + network_context_params->accept_language = m_httpAcceptLanguage.toStdString(); + + network_context_params->enable_referrers = true; + network_context_params->enable_encrypted_cookies = false; // ??? +// network_context_params->proxy_resolver_factory = std::move(m_proxyResolverFactoryInterface); + + network_context_params->http_cache_enabled = m_httpCacheType != ProfileAdapter::NoCache; + network_context_params->http_cache_max_size = m_httpCacheMaxSize; + if (m_httpCacheType == ProfileAdapter::DiskHttpCache) + network_context_params->http_cache_path = toFilePath(m_httpCachePath); + + if (m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies) { + base::FilePath cookie_path = toFilePath(m_dataPath); + cookie_path = cookie_path.AppendASCII("Cookies"); + network_context_params->cookie_path = cookie_path; + + network_context_params->restore_old_session_cookies = false; + network_context_params->persist_session_cookies = m_persistentCookiesPolicy == ProfileAdapter::ForcePersistentCookies; + } + if (!m_dataPath.isEmpty()) { + network_context_params->http_server_properties_path = toFilePath(m_dataPath).AppendASCII("Network Persistent State"); + network_context_params->transport_security_persister_path = toFilePath(m_dataPath); + } + +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + network_context_params->enable_ftp_url_support = true; +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + +// network_context_params->enable_certificate_reporting = true; +// network_context_params->enable_expect_ct_reporting = true; + network_context_params->enforce_chrome_ct_policy = false; + network_context_params->primary_network_context = m_useForGlobalCertificateVerification; + + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // Should be initialized with existing per-profile CORS access lists. + network_context_params->cors_origin_access_list = + m_profile->GetSharedCorsOriginAccessList()->GetOriginAccessList().CreateCorsOriginAccessPatternsList(); + } + + m_proxyConfigMonitor->AddToNetworkContextParams(network_context_params.get()); + + return network_context_params; } // static diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h index ec0a3dac9..25e03a4fd 100644 --- a/src/core/profile_io_data_qt.h +++ b/src/core/profile_io_data_qt.h @@ -42,13 +42,12 @@ #include "profile_adapter.h" #include "content/public/browser/browsing_data_remover.h" -#include "content/public/common/url_loader_throttle.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "extensions/buildflags/buildflags.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" +#include "net/proxy_config_monitor.h" #include "services/network/cookie_settings.h" -#include "services/network/public/mojom/restricted_cookie_manager.mojom.h" +#include "services/network/public/mojom/network_context.mojom.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" #include <QtCore/QString> @@ -57,16 +56,7 @@ namespace net { class ClientCertStore; -class DhcpPacFileFetcherFactory; -class HttpAuthPreferences; -class HttpNetworkSession; -class HostResolver; -class NetworkDelegate; class ProxyConfigService; -class URLRequestContext; -class URLRequestContextStorage; -class URLRequestJobFactoryImpl; -class TransportSecurityPersister; } namespace extensions { @@ -119,11 +109,6 @@ public: void cancelAllUrlRequests(); void generateAllStorage(); - void generateStorage(); - void generateCookieStore(); - void generateHttpCache(); - void generateUserAgent(); - void generateJobFactory(); void regenerateJobFactory(); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; @@ -149,12 +134,7 @@ public: void updateUsedForGlobalCertificateVerification(); // runs on ui thread bool hasPageInterceptors(); - void CreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRequest request, - network::mojom::RestrictedCookieManagerRole role, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t routing_id); + network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); #if QT_CONFIG(ssl) ClientCertificateStoreData *clientCertificateStoreData(); @@ -163,34 +143,27 @@ public: static ProfileIODataQt *FromBrowserContext(content::BrowserContext *browser_context); static ProfileIODataQt *FromResourceContext(content::ResourceContext *resource_context); + base::WeakPtr<ProfileIODataQt> getWeakPtrOnIOThread(); base::WeakPtr<ProfileIODataQt> getWeakPtrOnUIThread(); + CookieMonsterDelegateQt *cookieDelegate() const { return m_cookieDelegate.get(); } + private: void removeBrowsingDataRemoverObserver(); ProfileQt *m_profile; - std::unique_ptr<net::URLRequestContextStorage> m_storage; - std::unique_ptr<net::NetworkDelegate> m_networkDelegate; std::unique_ptr<content::ResourceContext> m_resourceContext; - std::unique_ptr<net::URLRequestContext> m_urlRequestContext; - std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; scoped_refptr<ProtocolHandlerRegistry::IOThreadDelegate> m_protocolHandlerRegistryIOThreadDelegate; - std::unique_ptr<net::DhcpPacFileFetcherFactory> m_dhcpPacFileFetcherFactory; - std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; - std::unique_ptr<net::URLRequestJobFactory> m_jobFactory; - std::unique_ptr<net::TransportSecurityPersister> m_transportSecurityPersister; - std::unique_ptr<net::HostResolver> m_hostResolver; base::WeakPtr<ProfileIODataQt> m_weakPtr; scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; content::URLRequestInterceptorScopedVector m_requestInterceptors; content::ProtocolHandlerMap m_protocolHandlers; mojo::InterfacePtrInfo<proxy_resolver::mojom::ProxyResolverFactory> m_proxyResolverFactoryInterface; - net::URLRequestJobFactoryImpl *m_baseJobFactory = nullptr; QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; QPointer<ProfileAdapter> m_profileAdapter; // never dereferenced in IO thread and it is passed by qpointer ProfileAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; - mojo::StrongBindingSet<network::mojom::RestrictedCookieManager> m_restrictedCookieManagerBindings; + std::unique_ptr<ProxyConfigMonitor> m_proxyConfigMonitor; #if QT_CONFIG(ssl) ClientCertificateStoreData *m_clientCertificateStoreData; diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index be55e7c49..4d4f588fa 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -44,7 +44,6 @@ #include "command_line_pref_store_qt.h" #include "download_manager_delegate_qt.h" #include "net/ssl_host_state_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" #include "platform_notification_service_qt.h" #include "qtwebenginecoreglobal_p.h" @@ -225,19 +224,7 @@ net::URLRequestContextGetter *ProfileQt::CreateRequestContext( content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!m_urlRequestContextGetter.get()); -#if BUILDFLAG(ENABLE_EXTENSIONS) - extensions::InfoMap *extension_info_map = GetExtensionSystem()->info_map(); - (*protocol_handlers)[extensions::kExtensionScheme] = - extensions::CreateExtensionProtocolHandler(IsOffTheRecord(), extension_info_map); -#endif - - m_profileIOData->setRequestContextData(protocol_handlers, std::move(request_interceptors)); - m_profileIOData->updateStorageSettings(); - m_profileIOData->updateRequestInterceptor(); - m_urlRequestContextGetter = new URLRequestContextGetterQt(m_profileIOData.get()); - return m_urlRequestContextGetter.get(); + return nullptr; } content::ClientHintsControllerDelegate *ProfileQt::GetClientHintsControllerDelegate() diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index cd8514352..f17f28495 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -20,6 +20,7 @@ deps = [ "//components/cdm/renderer", "//components/error_page/common", "//components/keyed_service/content", + "//components/navigation_interception", "//components/network_hints/browser", "//components/network_hints/common", "//components/network_hints/renderer", @@ -65,6 +66,10 @@ if (enable_extensions) { ] } +if (is_win) { + data_deps = [ ":qtwebengine_sandbox_win" ] +} + defines = [ "CHROMIUM_VERSION=\"" + chromium_version[0] + "\"" ] diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index b4a6b3b83..011a143b5 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -179,3 +179,9 @@ source_set("qtwebengine_sources") { } } +if (is_win) { + shared_library("qtwebengine_sandbox_win") { + create_pri_file = true + public_deps = [ "//sandbox/win:sandbox" ] + } +} diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index e2fd074ae..e9be587cf 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -340,7 +340,6 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget // May call SetNeedsBeginFrames host()->SetView(this); - host()->GetProcess()->AddObserver(this); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() @@ -354,7 +353,6 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() if (text_input_manager_) text_input_manager_->RemoveObserver(this); - host()->GetProcess()->RemoveObserver(this); m_touchSelectionController.reset(); m_touchSelectionControllerClient.reset(); @@ -704,18 +702,6 @@ void RenderWidgetHostViewQt::ImeCompositionRangeChanged(const gfx::Range&, const QT_NOT_YET_IMPLEMENTED } -void RenderWidgetHostViewQt::RenderProcessExited(content::RenderProcessHost *host, - const content::ChildProcessTerminationInfo &info) -{ - Q_UNUSED(host); - // RenderProcessHost::FastShutdownIfPossible results in TERMINATION_STATUS_STILL_RUNNING - if (m_adapterClient && info.status != base::TERMINATION_STATUS_STILL_RUNNING) { - m_adapterClient->renderProcessTerminated( - m_adapterClient->renderProcessExitStatus(info.status), - info.exit_code); - } -} - void RenderWidgetHostViewQt::RenderProcessGone() { Destroy(); @@ -1103,7 +1089,7 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) #endif }; - if (!inputMethodQuery(Qt::ImEnabled).toBool() && !acceptKeyOutOfInputField(keyEvent)) + if (!inputMethodQuery(Qt::ImEnabled).toBool() && !(inputMethodQuery(Qt::ImHints).toInt() & Qt::ImhHiddenText) && !acceptKeyOutOfInputField(keyEvent)) return false; Q_ASSERT(m_editCommand.empty()); @@ -1589,7 +1575,12 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) eventTimestamp += m_eventsToNowDelta; QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints()); - { + // Make sure that ACTION_POINTER_DOWN is delivered before ACTION_MOVE, + // and ACTION_MOVE before ACTION_POINTER_UP. + std::sort(touchPoints.begin(), touchPoints.end(), compareTouchPoints); + + // Check first if the touch event should be routed to the selectionController + if (!touchPoints.isEmpty()) { ui::MotionEvent::Action action; switch (touchPoints[0].state()) { case Qt::TouchPointPressed: @@ -1608,6 +1599,23 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), 0); if (m_touchSelectionController->WillHandleTouchEvent(motionEvent)) { + m_previousTouchPoints = touchPoints; + ev->accept(); + return; + } + } else { + // An empty touchPoints always corresponds to a TouchCancel event. + // We can't forward touch cancellations without a previously processed touch event, + // as Chromium expects the previous touchPoints for Action::CANCEL. + // If both are empty that means the TouchCancel was sent without an ongoing touch, + // so there's nothing to cancel anyway. + touchPoints = m_previousTouchPoints; + if (touchPoints.isEmpty()) + return; + + MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers()); + if (m_touchSelectionController->WillHandleTouchEvent(cancelEvent)) { + m_previousTouchPoints.clear(); ev->accept(); return; } @@ -1624,21 +1632,13 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) break; case QEvent::TouchCancel: { - // Don't process a TouchCancel event if no motion was started beforehand, or if there are - // no touch points in the current event or in the previously processed event. - if (!m_touchMotionStarted || (touchPoints.isEmpty() && m_previousTouchPoints.isEmpty())) { - clearPreviousTouchMotionState(); - return; + // Only process TouchCancel events received following a TouchBegin or TouchUpdate event + if (m_touchMotionStarted) { + MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers()); + processMotionEvent(cancelEvent); } - // Use last saved touch points for the cancel event, to get rid of a QList assert, - // because Chromium expects a MotionEvent::ACTION_CANCEL instance to contain at least - // one touch point, whereas a QTouchCancel may not contain any touch points at all. - if (touchPoints.isEmpty()) - touchPoints = m_previousTouchPoints; clearPreviousTouchMotionState(); - MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers()); - processMotionEvent(cancelEvent); return; } case QEvent::TouchEnd: @@ -1662,11 +1662,6 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) #endif } - // Make sure that ACTION_POINTER_DOWN is delivered before ACTION_MOVE, - // and ACTION_MOVE before ACTION_POINTER_UP. - std::sort(touchPoints.begin(), touchPoints.end(), compareTouchPoints); - - m_previousTouchPoints = touchPoints; for (int i = 0; i < touchPoints.size(); ++i) { ui::MotionEvent::Action action; switch (touchPoints[i].state()) { @@ -1693,6 +1688,8 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), i); processMotionEvent(motionEvent); } + + m_previousTouchPoints = touchPoints; } #if QT_CONFIG(tabletevent) @@ -1915,6 +1912,11 @@ std::unique_ptr<content::SyntheticGestureTarget> RenderWidgetHostViewQt::CreateS return nullptr; } +ui::Compositor *RenderWidgetHostViewQt::GetCompositor() +{ + return m_uiCompositor.get(); +} + void RenderWidgetHostViewQt::UpdateNeedsBeginFramesInternal() { if (m_enableViz) diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 76807b37a..dc6ccc8df 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -102,7 +102,6 @@ struct MultipleMouseClickHelper class RenderWidgetHostViewQt : public content::RenderWidgetHostViewBase - , public content::RenderProcessHostObserver , public ui::GestureProviderClient , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> @@ -175,10 +174,7 @@ public: void ResetFallbackToFirstNavigationSurface() override; void DidStopFlinging() override; std::unique_ptr<content::SyntheticGestureTarget> CreateSyntheticGestureTarget() override; - - // RenderProcessHostObserver implementation. - void RenderProcessExited(content::RenderProcessHost *host, - const content::ChildProcessTerminationInfo &info) override; + ui::Compositor *GetCompositor() override; // Overridden from ui::GestureProviderClient. void OnGestureEvent(const ui::GestureEventData& gesture) override; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index b9b199087..0201e5de4 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -113,8 +113,7 @@ namespace QtWebEngineCore { static const char kHttpErrorDomain[] = "http"; -ContentRendererClientQt::ContentRendererClientQt() - : m_serviceBinding(this) +ContentRendererClientQt::ContentRendererClientQt() : m_serviceBinding(this) { #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionsClient::Set(extensions::ExtensionsClientQt::GetInstance()); @@ -122,9 +121,7 @@ ContentRendererClientQt::ContentRendererClientQt() #endif } -ContentRendererClientQt::~ContentRendererClientQt() -{ -} +ContentRendererClientQt::~ContentRendererClientQt() {} void ContentRendererClientQt::RenderThreadStarted() { @@ -137,10 +134,9 @@ void ContentRendererClientQt::RenderThreadStarted() m_prescientNetworkingDispatcher.reset(new network_hints::PrescientNetworkingDispatcher()); auto registry = std::make_unique<service_manager::BinderRegistry>(); - registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), - base::ThreadTaskRunnerHandle::Get()); + registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), base::ThreadTaskRunnerHandle::Get()); content::ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( - std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); + std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); renderThread->AddObserver(m_renderThreadObserver.data()); renderThread->AddObserver(UserResourceController::instance()); @@ -153,32 +149,32 @@ void ContentRendererClientQt::RenderThreadStarted() // 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(), 0, - network::mojom::CorsDomainMatchMode::kAllowSubdomains, - network::mojom::CorsPortMatchMode::kAllowAnyPort, - network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); + blink::WebSecurityPolicy::AddOriginAccessAllowListEntry( + qrc, file, blink::WebString(), 0, network::mojom::CorsDomainMatchMode::kAllowSubdomains, + network::mojom::CorsPortMatchMode::kAllowAnyPort, + 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::WebString chromeResources(blink::WebString::FromASCII("chrome")); - blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(pdfViewerExtension, chromeResources, blink::WebString(), 0, - network::mojom::CorsDomainMatchMode::kAllowSubdomains, - network::mojom::CorsPortMatchMode::kAllowAnyPort, - 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::RenderViewCreated(content::RenderView *render_view) { // RenderViewObservers destroy themselves with their RenderView. new RenderViewObserverQt(render_view); UserResourceController::instance()->renderViewCreated(render_view); } -void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) +void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_frame) { QtWebEngineCore::RenderFrameObserverQt *render_frame_observer = new QtWebEngineCore::RenderFrameObserverQt(render_frame, m_webCacheImpl.data()); @@ -195,9 +191,7 @@ 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) #if BUILDFLAG(ENABLE_EXTENSIONS) auto registry = std::make_unique<service_manager::BinderRegistry>(); @@ -259,9 +253,9 @@ void ContentRendererClientQt::PrepareErrorPage(content::RenderFrame *renderFrame 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(web_error.url(), web_error.reason(), web_error.has_copy_in_cache()), errorHtml); } void ContentRendererClientQt::PrepareErrorPageForHttpStatusError(content::RenderFrame *renderFrame, @@ -277,7 +271,10 @@ void ContentRendererClientQt::PrepareErrorPageForHttpStatusError(content::Render 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) const bool isPost = QByteArray::fromStdString(httpMethod) == QByteArrayLiteral("POST"); @@ -322,9 +319,9 @@ blink::WebPrescientNetworking *ContentRendererClientQt::GetPrescientNetworking() return m_prescientNetworkingDispatcher.get(); } -bool ContentRendererClientQt::OverrideCreatePlugin( - content::RenderFrame* render_frame, - const blink::WebPluginParams& params, blink::WebPlugin** plugin) +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)) @@ -333,20 +330,21 @@ bool ContentRendererClientQt::OverrideCreatePlugin( return content::ContentRendererClient::OverrideCreatePlugin(render_frame, params, plugin); } -content::BrowserPluginDelegate* ContentRendererClientQt::CreateBrowserPluginDelegate(content::RenderFrame *render_frame, +content::BrowserPluginDelegate *ContentRendererClientQt::CreateBrowserPluginDelegate(content::RenderFrame *render_frame, const content::WebPluginInfo &info, const std::string &mime_type, const GURL &original_url) { #if BUILDFLAG(ENABLE_EXTENSIONS) - return ExtensionsRendererClientQt::GetInstance()->CreateBrowserPluginDelegate(render_frame, info, mime_type, original_url); + return ExtensionsRendererClientQt::GetInstance()->CreateBrowserPluginDelegate(render_frame, info, mime_type, + original_url); #else return nullptr; #endif } void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceInfo &remote_info, - const std::string& name, + const std::string &name, mojo::ScopedMessagePipeHandle handle) { Q_UNUSED(remote_info); @@ -355,9 +353,8 @@ void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceI 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)); + m_serviceBinding.GetConnector()->BindInterface(service_manager::ServiceFilter::ByName("qtwebengine"), + interface_name, std::move(interface_pipe)); } // The following is based on chrome/renderer/media/chrome_key_systems.cc: @@ -367,7 +364,7 @@ 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) +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. @@ -403,57 +400,58 @@ static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProp } concrete_key_systems->emplace_back( - new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); + new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); // Add support of decrypt-only mode in ClearKeyCdm. - concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( - kExternalClearKeyDecryptOnlyKeySystem)); + 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)); + 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)); + 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)); + 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)); + 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 cdm::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 cdm::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)); + 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)); + 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)); + 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)); + concrete_key_systems->emplace_back( + new cdm::ExternalClearKeyProperties(kExternalClearKeyCdmProxyTestKeySystem)); } #if BUILDFLAG(ENABLE_WIDEVINE) -static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, bool is_secure) +static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, + bool is_secure) { media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; @@ -469,7 +467,7 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC supported_codecs |= media::EME_CODEC_FLAC; #if BUILDFLAG(USE_PROPRIETARY_CODECS) supported_codecs |= media::EME_CODEC_AAC; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) } // Video codecs are determined by what was registered for the CDM. @@ -486,7 +484,7 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC case media::VideoCodec::kCodecH264: supported_codecs |= media::EME_CODEC_AVC1; break; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) default: DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); break; @@ -505,13 +503,11 @@ static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> } // Codecs and encryption schemes. - auto codecs = - GetSupportedCodecs(capability->video_codecs, /*is_secure=*/false); - const auto& encryption_schemes = capability->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; + const auto &hw_secure_encryption_schemes = capability->hw_secure_encryption_schemes; // Robustness. using Robustness = cdm::WidevineKeySystemProperties::Robustness; @@ -574,11 +570,13 @@ void ContentRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, bool *attach_same_site_cookies) { #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, initiator_origin, new_url, + attach_same_site_cookies); if (!new_url->is_empty()) return; #endif - content::ContentRendererClient::WillSendRequest(frame, transition_type, url, initiator_origin, new_url, attach_same_site_cookies); + content::ContentRendererClient::WillSendRequest(frame, transition_type, url, initiator_origin, new_url, + attach_same_site_cookies); } void ContentRendererClientQt::CreateRendererService(service_manager::mojom::ServiceRequest service_request) @@ -587,7 +585,7 @@ void ContentRendererClientQt::CreateRendererService(service_manager::mojom::Serv m_serviceBinding.Bind(std::move(service_request)); } -service_manager::Connector* ContentRendererClientQt::GetConnector() +service_manager::Connector *ContentRendererClientQt::GetConnector() { return m_serviceBinding.GetConnector(); } diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index a13d16b5c..4b394bd3e 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -74,9 +74,10 @@ namespace QtWebEngineCore { class RenderThreadObserverQt; -class ContentRendererClientQt : public content::ContentRendererClient - , public service_manager::Service - , public service_manager::LocalInterfaceProvider +class ContentRendererClientQt + : public content::ContentRendererClient + , public service_manager::Service + , public service_manager::LocalInterfaceProvider { public: ContentRendererClientQt(); @@ -85,7 +86,7 @@ public: // content::ContentRendererClient: void RenderThreadStarted() override; void RenderViewCreated(content::RenderView *render_view) override; - void RenderFrameCreated(content::RenderFrame* render_frame) override; + void RenderFrameCreated(content::RenderFrame *render_frame) override; bool ShouldSuppressErrorPage(content::RenderFrame *, const GURL &) override; bool HasErrorPage(int http_status_code) override; @@ -103,16 +104,19 @@ public: uint64_t VisitedLinkHash(const char *canonical_url, size_t length) override; bool IsLinkVisited(uint64_t linkHash) override; - blink::WebPrescientNetworking* GetPrescientNetworking() override; - void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) override; + blink::WebPrescientNetworking *GetPrescientNetworking() override; + void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems) override; void RunScriptsAtDocumentStart(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) override; void RunScriptsAtDocumentIdle(content::RenderFrame *render_frame) override; - bool OverrideCreatePlugin(content::RenderFrame* render_frame, - const blink::WebPluginParams& params, blink::WebPlugin** plugin) override; - content::BrowserPluginDelegate* CreateBrowserPluginDelegate(content::RenderFrame* render_frame, - const content::WebPluginInfo& info, const std::string& mime_type, const GURL& original_url) override; + bool OverrideCreatePlugin(content::RenderFrame *render_frame, + const blink::WebPluginParams ¶ms, + blink::WebPlugin **plugin) override; + content::BrowserPluginDelegate *CreateBrowserPluginDelegate(content::RenderFrame *render_frame, + const content::WebPluginInfo &info, + const std::string &mime_type, + const GURL &original_url) override; void WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, @@ -135,10 +139,10 @@ private: mojo::ScopedMessagePipeHandle handle) override; // service_manager::LocalInterfaceProvider: - void GetInterface(const std::string& name, mojo::ScopedMessagePipeHandle request_handle) override; + void GetInterface(const std::string &name, mojo::ScopedMessagePipeHandle request_handle) override; - void GetNavigationErrorStringsInternal(content::RenderFrame* renderFrame, const std::string &httpMethod, - const error_page::Error& error, std::string* errorHtml); + void GetNavigationErrorStringsInternal(content::RenderFrame *renderFrame, const std::string &httpMethod, + const error_page::Error &error, std::string *errorHtml); QScopedPointer<RenderThreadObserverQt> m_renderThreadObserver; QScopedPointer<visitedlink::VisitedLinkSlave> m_visitedLinkSlave; diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp index a9e89dfee..fc7019367 100644 --- a/src/core/renderer/content_settings_observer_qt.cpp +++ b/src/core/renderer/content_settings_observer_qt.cpp @@ -63,40 +63,37 @@ bool IsUniqueFrame(blink::WebFrame *frame) frame->Top()->GetSecurityOrigin().IsUnique(); } -} // namespace +} // namespace namespace QtWebEngineCore { ContentSettingsObserverQt::ContentSettingsObserverQt(content::RenderFrame *render_frame) - : content::RenderFrameObserver(render_frame) - , content::RenderFrameObserverTracker<ContentSettingsObserverQt>(render_frame) - , m_currentRequestId(0) + : content::RenderFrameObserver(render_frame) + , content::RenderFrameObserverTracker<ContentSettingsObserverQt>(render_frame) + , m_currentRequestId(0) { ClearBlockedContentSettings(); render_frame->GetWebFrame()->SetContentSettingsClient(this); } -ContentSettingsObserverQt::~ContentSettingsObserverQt() { -} +ContentSettingsObserverQt::~ContentSettingsObserverQt() {} -bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message& message) +bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserverQt, message) - IPC_MESSAGE_HANDLER(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, - OnRequestFileSystemAccessAsyncResponse) - IPC_MESSAGE_UNHANDLED(handled = false) + IPC_MESSAGE_HANDLER(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, OnRequestFileSystemAccessAsyncResponse) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition /*transition*/) +void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition /*transition*/) { - blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); if (frame->Parent()) - return; // Not a top-level navigation. + return; // Not a top-level navigation. if (!is_same_document_navigation) ClearBlockedContentSettings(); @@ -104,8 +101,7 @@ void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool is_same_document_n GURL url = frame->GetDocument().Url(); // If we start failing this DCHECK, please makes sure we don't regress // this bug: http://code.google.com/p/chromium/issues/detail?id=79304 - DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" || - !url.SchemeIs(url::kDataScheme)); + DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" || !url.SchemeIs(url::kDataScheme)); } void ContentSettingsObserverQt::OnDestruct() @@ -120,10 +116,8 @@ bool ContentSettingsObserverQt::AllowDatabase() return false; bool result = false; - Send(new QtWebEngineHostMsg_AllowDatabase( - routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), - &result)); + Send(new QtWebEngineHostMsg_AllowDatabase(routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), &result)); return result; } @@ -140,10 +134,9 @@ void ContentSettingsObserverQt::RequestFileSystemAccessAsync(base::OnceCallback< // Verify there are no duplicate insertions. DCHECK(inserted); - Send(new QtWebEngineHostMsg_RequestFileSystemAccessAsync( - routing_id(), m_currentRequestId, - url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL())); + Send(new QtWebEngineHostMsg_RequestFileSystemAccessAsync(routing_id(), m_currentRequestId, + url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL())); } bool ContentSettingsObserverQt::AllowIndexedDB(const WebSecurityOrigin &origin) @@ -153,10 +146,8 @@ bool ContentSettingsObserverQt::AllowIndexedDB(const WebSecurityOrigin &origin) return false; bool result = false; - Send(new QtWebEngineHostMsg_AllowIndexedDB( - routing_id(), url::Origin(origin).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), - &result)); + Send(new QtWebEngineHostMsg_AllowIndexedDB(routing_id(), url::Origin(origin).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), &result)); return result; } @@ -172,9 +163,8 @@ bool ContentSettingsObserverQt::AllowStorage(bool local) return permissions->second; bool result = false; - Send(new QtWebEngineHostMsg_AllowDOMStorage( - routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), - url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), local, &result)); + Send(new QtWebEngineHostMsg_AllowDOMStorage(routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), local, &result)); m_cachedStoragePermissions[key] = result; return result; } diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h index 9c071aa3c..71e1fbca5 100644 --- a/src/core/renderer/content_settings_observer_qt.h +++ b/src/core/renderer/content_settings_observer_qt.h @@ -58,9 +58,9 @@ namespace QtWebEngineCore { // Handles blocking content per content settings for each RenderFrame. class ContentSettingsObserverQt - : public content::RenderFrameObserver - , public content::RenderFrameObserverTracker<ContentSettingsObserverQt> - , public blink::WebContentSettingsClient + : public content::RenderFrameObserver + , public content::RenderFrameObserverTracker<ContentSettingsObserverQt> + , public blink::WebContentSettingsClient { public: ContentSettingsObserverQt(content::RenderFrame *render_frame); @@ -73,11 +73,9 @@ public: bool AllowStorage(bool local) override; private: - // RenderFrameObserver implementation: bool OnMessageReceived(const IPC::Message &message) override; - void DidCommitProvisionalLoad(bool is_same_document_navigation, - ui::PageTransition transition) override; + void DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition transition) override; void OnDestruct() override; // Message handlers. @@ -98,4 +96,4 @@ private: } // namespace QtWebEngineCore -#endif // RENDERER_CONTENT_SETTINGS_OBSERVER_QT_H +#endif // RENDERER_CONTENT_SETTINGS_OBSERVER_QT_H diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp index 67cdd6b66..b85ff7249 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -52,21 +52,17 @@ #include "web_engine_library_info.h" namespace QtWebEngineCore { -PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() -{ - -} +PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() {} bool PrintWebViewHelperDelegateQt::CancelPrerender(content::RenderFrame *) { return false; } -blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame* frame) +blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame *frame) { GURL url = frame->GetDocument().Url(); - if (url.SchemeIs(extensions::kExtensionScheme) && url.host() == extension_misc::kPdfExtensionId) - { + if (url.SchemeIs(extensions::kExtensionScheme) && url.host() == extension_misc::kPdfExtensionId) { // <object> with id="plugin" is created in // chrome/browser/resources/pdf/pdf.js. auto plugin_element = frame->GetDocument().GetElementById("plugin"); @@ -81,7 +77,7 @@ bool PrintWebViewHelperDelegateQt::IsPrintPreviewEnabled() return true; } -bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame* frame) +bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame *frame) { return false; } diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.h b/src/core/renderer/print_web_view_helper_delegate_qt.h index e3020922f..f02580b91 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.h +++ b/src/core/renderer/print_web_view_helper_delegate_qt.h @@ -57,15 +57,14 @@ class PrintWebViewHelperDelegateQt : public printing::PrintRenderFrameHelper::De public: ~PrintWebViewHelperDelegateQt() override; - bool CancelPrerender(content::RenderFrame* render_frame) override; + bool CancelPrerender(content::RenderFrame *render_frame) override; - blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override; + blink::WebElement GetPdfElement(blink::WebLocalFrame *frame) override; bool IsPrintPreviewEnabled() override; - bool OverridePrint(blink::WebLocalFrame* frame) override; -}; // class PrintWebViewHelperDelegateQt + bool OverridePrint(blink::WebLocalFrame *frame) override; +}; // class PrintWebViewHelperDelegateQt } #endif // PRINT_WEB_VIEW_HELPER_DELEGATE_QT_H - diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index c48ef3b5c..cc01acec6 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -55,30 +55,25 @@ namespace QtWebEngineCore { -RenderFrameObserverQt::RenderFrameObserverQt(content::RenderFrame* render_frame, - web_cache::WebCacheImpl* web_cache_impl) +RenderFrameObserverQt::RenderFrameObserverQt(content::RenderFrame *render_frame, web_cache::WebCacheImpl *web_cache_impl) : RenderFrameObserver(render_frame) , RenderFrameObserverTracker<RenderFrameObserverQt>(render_frame) , m_isFrameDetached(false) , m_web_cache_impl(web_cache_impl) -{ -} +{} -RenderFrameObserverQt::~RenderFrameObserverQt() -{ -} +RenderFrameObserverQt::~RenderFrameObserverQt() {} -void RenderFrameObserverQt::OnDestruct() { +void RenderFrameObserverQt::OnDestruct() +{ delete this; } #if QT_CONFIG(webengine_pepper_plugins) -void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host) +void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost *host) { - host->GetPpapiHost()->AddHostFactoryFilter( - base::WrapUnique(new PepperRendererHostFactoryQt(host))); - host->GetPpapiHost()->AddInstanceMessageFilter( - base::WrapUnique(new PepperSharedMemoryMessageFilter(host))); + host->GetPpapiHost()->AddHostFactoryFilter(base::WrapUnique(new PepperRendererHostFactoryQt(host))); + host->GetPpapiHost()->AddInstanceMessageFilter(base::WrapUnique(new PepperSharedMemoryMessageFilter(host))); } #endif diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index fb9fd3869..6bdf4ad23 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -57,23 +57,22 @@ class WebCacheImpl; namespace QtWebEngineCore { class RenderFrameObserverQt - : public content::RenderFrameObserver - , public content::RenderFrameObserverTracker<RenderFrameObserverQt> + : public content::RenderFrameObserver + , public content::RenderFrameObserverTracker<RenderFrameObserverQt> { public: - explicit RenderFrameObserverQt(content::RenderFrame* render_frame, - web_cache::WebCacheImpl* web_cache_impl); + explicit RenderFrameObserverQt(content::RenderFrame *render_frame, web_cache::WebCacheImpl *web_cache_impl); ~RenderFrameObserverQt(); #if QT_CONFIG(webengine_pepper_plugins) - void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; + void DidCreatePepperPlugin(content::RendererPpapiHost *host) override; #endif void OnDestruct() override; void FrameDetached() override; bool isFrameDetached() const; - service_manager::BinderRegistry* registry() { return ®istry_; } + service_manager::BinderRegistry *registry() { return ®istry_; } private: DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverQt); diff --git a/src/core/renderer/render_thread_observer_qt.cpp b/src/core/renderer/render_thread_observer_qt.cpp index 64b9fd961..6012099b8 100644 --- a/src/core/renderer/render_thread_observer_qt.cpp +++ b/src/core/renderer/render_thread_observer_qt.cpp @@ -52,7 +52,8 @@ bool RenderThreadObserverQt::m_isIncognitoProcess = false; void RenderThreadObserverQt::RegisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) { - associated_interfaces->AddInterface(base::Bind(&RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest, base::Unretained(this))); + associated_interfaces->AddInterface( + base::Bind(&RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest, base::Unretained(this))); } void RenderThreadObserverQt::UnregisterMojoInterfaces(blink::AssociatedInterfaceRegistry *associated_interfaces) @@ -65,7 +66,8 @@ void RenderThreadObserverQt::SetInitialConfiguration(bool is_incognito_process) m_isIncognitoProcess = is_incognito_process; } -void RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest(qtwebengine::mojom::RendererConfigurationAssociatedRequest request) +void RenderThreadObserverQt::OnRendererConfigurationAssociatedRequest( + qtwebengine::mojom::RendererConfigurationAssociatedRequest request) { m_rendererConfigurationBindings.AddBinding(this, std::move(request)); } diff --git a/src/core/renderer/render_thread_observer_qt.h b/src/core/renderer/render_thread_observer_qt.h index 29b842ab4..21acc6f13 100644 --- a/src/core/renderer/render_thread_observer_qt.h +++ b/src/core/renderer/render_thread_observer_qt.h @@ -46,10 +46,11 @@ namespace QtWebEngineCore { -class RenderThreadObserverQt : public content::RenderThreadObserver, - public qtwebengine::mojom::RendererConfiguration { +class RenderThreadObserverQt + : public content::RenderThreadObserver + , public qtwebengine::mojom::RendererConfiguration +{ public: - RenderThreadObserverQt() = default; ~RenderThreadObserverQt() override = default; diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp index 7e7c7bdf8..731d8b97d 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/render_view_observer_qt.cpp @@ -50,18 +50,15 @@ #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_view.h" -RenderViewObserverQt::RenderViewObserverQt( - content::RenderView* render_view) - : content::RenderViewObserver(render_view) -{ -} +RenderViewObserverQt::RenderViewObserverQt(content::RenderView *render_view) : content::RenderViewObserver(render_view) +{} void RenderViewObserverQt::onFetchDocumentMarkup(quint64 requestId) { blink::WebString markup; if (render_view()->GetWebView()->MainFrame()->IsWebLocalFrame()) markup = blink::WebFrameContentDumper::DumpAsMarkup( - static_cast<blink::WebLocalFrame*>(render_view()->GetWebView()->MainFrame())); + static_cast<blink::WebLocalFrame *>(render_view()->GetWebView()->MainFrame())); Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(routing_id(), requestId, markup.Utf16())); } @@ -69,9 +66,8 @@ void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) { blink::WebString text; if (render_view()->GetWebView()->MainFrame()->IsWebLocalFrame()) - text = blink::WebFrameContentDumper::DumpWebViewAsText( - render_view()->GetWebView(), - std::numeric_limits<std::size_t>::max()); + text = blink::WebFrameContentDumper::DumpWebViewAsText(render_view()->GetWebView(), + std::numeric_limits<std::size_t>::max()); Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text.Utf16())); } @@ -85,7 +81,7 @@ void RenderViewObserverQt::OnDestruct() delete this; } -bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message) +bool RenderViewObserverQt::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderViewObserverQt, message) diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h index a878eebe8..5c555b222 100644 --- a/src/core/renderer/render_view_observer_qt.h +++ b/src/core/renderer/render_view_observer_qt.h @@ -43,9 +43,10 @@ #include <QtGlobal> -class RenderViewObserverQt : public content::RenderViewObserver { +class RenderViewObserverQt : public content::RenderViewObserver +{ public: - RenderViewObserverQt(content::RenderView* render_view); + RenderViewObserverQt(content::RenderView *render_view); private: void onFetchDocumentMarkup(quint64 requestId); @@ -54,7 +55,7 @@ private: void OnDestruct() override; - bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message &message) override; DISALLOW_COPY_AND_ASSIGN(RenderViewObserverQt); }; diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 2613d262e..5c1bd301f 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -64,7 +64,7 @@ Q_GLOBAL_STATIC(UserResourceController, qt_webengine_userResourceController) -static content::RenderView * const globalScriptsIndex = 0; +static content::RenderView *const globalScriptsIndex = nullptr; // Scripts meant to run after the load event will be run 500ms after DOMContentLoaded if the load event doesn't come within that delay. static const int afterLoadTimeout = 500; @@ -74,7 +74,8 @@ static int validUserScriptSchemes() return URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | URLPattern::SCHEME_FILE | URLPattern::SCHEME_QRC; } -static bool regexMatchesURL(const std::string &pat, const GURL &url) { +static bool regexMatchesURL(const std::string &pat, const GURL &url) +{ QRegularExpression qre(QtWebEngineCore::toQt(pat)); qre.setPatternOptions(QRegularExpression::CaseInsensitiveOption); if (!qre.isValid()) @@ -96,7 +97,8 @@ static bool includeRuleMatchesURL(const std::string &pat, const GURL &url) return false; } -static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) { +static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) +{ // Logic taken from Chromium (extensions/common/user_script.cc) bool matchFound; if (!scriptData.urlPatterns.empty()) { @@ -133,7 +135,7 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) class UserResourceController::RenderFrameObserverHelper : public content::RenderFrameObserver { public: - RenderFrameObserverHelper(content::RenderFrame* render_frame); + RenderFrameObserverHelper(content::RenderFrame *render_frame); private: // RenderFrameObserver implementation. @@ -142,7 +144,7 @@ private: void DidFinishLoad() override; void FrameDetached() override; void OnDestruct() override; - bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message &message) override; void onUserScriptAdded(const UserScriptData &); void onUserScriptRemoved(const UserScriptData &); @@ -154,12 +156,10 @@ private: // Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to // avoid running scripts more than once per injection point. -class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner> { +class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner> +{ public: - explicit Runner(blink::WebLocalFrame *frame) - : m_frame(frame) - { - } + explicit Runner(blink::WebLocalFrame *frame) : m_frame(frame) {} void run(UserScriptData::InjectionPoint p) { @@ -179,7 +179,8 @@ private: class UserResourceController::RenderViewObserverHelper : public content::RenderViewObserver { public: - RenderViewObserverHelper(content::RenderView* render_view); + RenderViewObserverHelper(content::RenderView *render_view); + private: // RenderViewObserver implementation. void OnDestruct() override; @@ -201,8 +202,7 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink: for (uint64_t id : qAsConst(scriptsToRun)) { const UserScriptData &script = m_scripts.value(id); - if (script.injectionPoint != p - || (!script.injectForSubframes && !isMainFrame)) + if (script.injectionPoint != p || (!script.injectForSubframes && !isMainFrame)) continue; if (!scriptMatchesURL(script, frame->GetDocument().Url())) continue; @@ -221,13 +221,11 @@ void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *rende UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(content::RenderFrame *render_frame) : content::RenderFrameObserver(render_frame) -{ -} +{} UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view) : content::RenderViewObserver(render_view) -{ -} +{} void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition /*transitionbool*/) @@ -242,8 +240,7 @@ void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad m_runner.reset(new Runner(render_frame()->GetWebFrame())); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::DocumentElementCreation)); + FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::DocumentElementCreation)); } void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() @@ -252,18 +249,15 @@ void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() // called instead of DidCommitProvisionalLoad). if (m_runner) base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad), - base::TimeDelta::FromMilliseconds(afterLoadTimeout)); - + FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad), + base::TimeDelta::FromMilliseconds(afterLoadTimeout)); } void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() { if (m_runner) base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad)); + FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad)); } void UserResourceController::RenderFrameObserverHelper::FrameDetached() @@ -293,7 +287,7 @@ bool UserResourceController::RenderFrameObserverHelper::OnMessageReceived(const IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_ClearScripts, onScriptsCleared) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() - return handled; + return handled; } void UserResourceController::RenderFrameObserverHelper::onUserScriptAdded(const UserScriptData &script) @@ -411,4 +405,3 @@ void UserResourceController::onClearScripts() { clearScriptsForView(globalScriptsIndex); } - diff --git a/src/core/renderer/user_resource_controller.h b/src/core/renderer/user_resource_controller.h index 0b5e0a0c6..3a493b9b7 100644 --- a/src/core/renderer/user_resource_controller.h +++ b/src/core/renderer/user_resource_controller.h @@ -56,7 +56,8 @@ class RenderFrame; class RenderView; } -class UserResourceController : public content::RenderThreadObserver { +class UserResourceController : public content::RenderThreadObserver +{ public: static UserResourceController *instance(); diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 108686068..8e961566c 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -61,11 +61,13 @@ namespace QtWebEngineCore { -class WebChannelTransport : public gin::Wrappable<WebChannelTransport> { +class WebChannelTransport : public gin::Wrappable<WebChannelTransport> +{ public: static gin::WrapperInfo kWrapperInfo; static void Install(blink::WebLocalFrame *frame, uint worldId); static void Uninstall(blink::WebLocalFrame *frame, uint worldId); + private: WebChannelTransport() {} void NativeQtSendMessage(gin::Arguments *args); @@ -152,9 +154,7 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) v8::Local<v8::String> jsonString = v8::Local<v8::String>::Cast(jsonValue); QByteArray json(jsonString->Utf8Length(isolate), 0); - jsonString->WriteUtf8(isolate, - json.data(), json.size(), - nullptr, v8::String::REPLACE_INVALID_UTF8); + jsonString->WriteUtf8(isolate, json.data(), json.size(), nullptr, v8::String::REPLACE_INVALID_UTF8); QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json, &error); @@ -172,21 +172,19 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) { - return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate) - .SetMethod("send", &WebChannelTransport::NativeQtSendMessage); + return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate).SetMethod( + "send", &WebChannelTransport::NativeQtSendMessage); } WebChannelIPCTransport::WebChannelIPCTransport(content::RenderFrame *renderFrame) - : content::RenderFrameObserver(renderFrame) - , m_worldId(0) - , m_worldInitialized(false) + : content::RenderFrameObserver(renderFrame), m_worldId(0), m_worldInitialized(false) { renderFrame->GetAssociatedInterfaceRegistry()->AddInterface( - base::Bind(&WebChannelIPCTransport::BindRequest, base::Unretained(this))); + base::Bind(&WebChannelIPCTransport::BindRequest, base::Unretained(this))); } -void WebChannelIPCTransport::BindRequest( - qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request) { +void WebChannelIPCTransport::BindRequest(qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request) +{ m_binding.AddBinding(this, std::move(request)); } @@ -208,7 +206,7 @@ void WebChannelIPCTransport::SetWorldId(uint32_t worldId) void WebChannelIPCTransport::ResetWorldId() { - if (m_worldInitialized && m_canUseContext) + if (m_worldInitialized && m_canUseContext) WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); m_worldInitialized = false; @@ -222,8 +220,8 @@ void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector<uint8_t if (!m_canUseContext) return; - QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), - binaryJson.size(), QJsonDocument::BypassValidation); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size(), + QJsonDocument::BypassValidation); DCHECK(doc.isObject()); QByteArray json = doc.toJson(QJsonDocument::Compact); @@ -242,22 +240,23 @@ void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector<uint8_t if (qtObjectValue.IsEmpty() || !qtObjectValue.ToLocalChecked()->IsObject()) return; v8::Local<v8::Object> qtObject = v8::Local<v8::Object>::Cast(qtObjectValue.ToLocalChecked()); - v8::MaybeLocal<v8::Value> webChannelObjectValue(qtObject->Get(context, gin::StringToV8(isolate, "webChannelTransport"))); + v8::MaybeLocal<v8::Value> webChannelObjectValue( + qtObject->Get(context, gin::StringToV8(isolate, "webChannelTransport"))); if (webChannelObjectValue.IsEmpty() || !webChannelObjectValue.ToLocalChecked()->IsObject()) return; v8::Local<v8::Object> webChannelObject = v8::Local<v8::Object>::Cast(webChannelObjectValue.ToLocalChecked()); v8::MaybeLocal<v8::Value> callbackValue(webChannelObject->Get(context, gin::StringToV8(isolate, "onmessage"))); if (callbackValue.IsEmpty() || !callbackValue.ToLocalChecked()->IsFunction()) { - LOG(WARNING) << "onmessage is not a callable property of qt.webChannelTransport. Some things might not work as expected."; + LOG(WARNING) << "onmessage is not a callable property of qt.webChannelTransport. Some things might not work as " + "expected."; return; } v8::Local<v8::Object> messageObject(v8::Object::New(isolate)); v8::Maybe<bool> wasSet = messageObject->DefineOwnProperty( - context, - v8::String::NewFromUtf8(isolate, "data").ToLocalChecked(), - v8::String::NewFromUtf8(isolate, json.constData(), v8::NewStringType::kNormal, json.size()).ToLocalChecked(), - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); + context, v8::String::NewFromUtf8(isolate, "data").ToLocalChecked(), + v8::String::NewFromUtf8(isolate, json.constData(), v8::NewStringType::kNormal, json.size()).ToLocalChecked(), + v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); DCHECK(!wasSet.IsNothing() && wasSet.FromJust()); v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(callbackValue.ToLocalChecked()); diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 178c20ed1..a80eecf24 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -49,8 +49,10 @@ namespace QtWebEngineCore { -class WebChannelIPCTransport: private content::RenderFrameObserver, - public qtwebchannel::mojom::WebChannelTransportRender { +class WebChannelIPCTransport + : private content::RenderFrameObserver + , public qtwebchannel::mojom::WebChannelTransportRender +{ public: WebChannelIPCTransport(content::RenderFrame *); @@ -58,7 +60,7 @@ private: // qtwebchannel::mojom::WebChannelTransportRender void SetWorldId(uint32_t worldId) override; void ResetWorldId() override; - void DispatchWebChannelMessage(const std::vector<uint8_t>& binaryJson, uint32_t worldId) override; + void DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson, uint32_t worldId) override; // RenderFrameObserver void WillReleaseScriptContext(v8::Local<v8::Context> context, int worldId) override; diff --git a/src/core/renderer_host/render_view_observer_host_qt.cpp b/src/core/renderer_host/render_view_observer_host_qt.cpp index c097e102d..165a9d86a 100644 --- a/src/core/renderer_host/render_view_observer_host_qt.cpp +++ b/src/core/renderer_host/render_view_observer_host_qt.cpp @@ -69,7 +69,7 @@ void RenderViewObserverHostQt::fetchDocumentInnerText(quint64 requestId) web_contents()->GetRenderViewHost()->GetRoutingID(), requestId)); } -bool RenderViewObserverHostQt::OnMessageReceived(const IPC::Message& message) +bool RenderViewObserverHostQt::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderViewObserverHostQt, message) @@ -80,15 +80,14 @@ bool RenderViewObserverHostQt::OnMessageReceived(const IPC::Message& message) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; - } -void RenderViewObserverHostQt::onDidFetchDocumentMarkup(quint64 requestId, const base::string16& markup) +void RenderViewObserverHostQt::onDidFetchDocumentMarkup(quint64 requestId, const base::string16 &markup) { m_adapterClient->didFetchDocumentMarkup(requestId, toQt(markup)); } -void RenderViewObserverHostQt::onDidFetchDocumentInnerText(quint64 requestId, const base::string16& innerText) +void RenderViewObserverHostQt::onDidFetchDocumentInnerText(quint64 requestId, const base::string16 &innerText) { m_adapterClient->didFetchDocumentInnerText(requestId, toQt(innerText)); } diff --git a/src/core/renderer_host/render_view_observer_host_qt.h b/src/core/renderer_host/render_view_observer_host_qt.h index a08263e07..8590ecbc5 100644 --- a/src/core/renderer_host/render_view_observer_host_qt.h +++ b/src/core/renderer_host/render_view_observer_host_qt.h @@ -45,7 +45,7 @@ #include <QtGlobal> namespace content { - class WebContents; +class WebContents; } namespace QtWebEngineCore { @@ -55,14 +55,14 @@ class WebContentsAdapterClient; class RenderViewObserverHostQt : public content::WebContentsObserver { public: - RenderViewObserverHostQt(content::WebContents*, WebContentsAdapterClient *adapterClient); + RenderViewObserverHostQt(content::WebContents *, WebContentsAdapterClient *adapterClient); void fetchDocumentMarkup(quint64 requestId); void fetchDocumentInnerText(quint64 requestId); private: - bool OnMessageReceived(const IPC::Message& message) override; - void onDidFetchDocumentMarkup(quint64 requestId, const base::string16& markup); - void onDidFetchDocumentInnerText(quint64 requestId, const base::string16& innerText); + bool OnMessageReceived(const IPC::Message &message) override; + void onDidFetchDocumentMarkup(quint64 requestId, const base::string16 &markup); + void onDidFetchDocumentInnerText(quint64 requestId, const base::string16 &innerText); WebContentsAdapterClient *m_adapterClient; }; diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp deleted file mode 100644 index a08e2cf88..000000000 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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 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. - -#include "resource_dispatcher_host_delegate_qt.h" - -#include "base/bind.h" -#include "base/guid.h" -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_task_traits.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/navigation_controller.h" - -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_dispatcher_host.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/browser/stream_info.h" -#include "content/public/browser/web_contents.h" - -#include "extensions/extension_system_qt.h" -#include "extensions/browser/info_map.h" -#include "extensions/common/constants.h" -#include "extensions/common/extension.h" -#include "extensions/common/manifest_handlers/mime_types_handler.h" - -#include "net/base/escape.h" -#include "net/url_request/url_request.h" - -#include "profile_io_data_qt.h" -#include "type_conversion.h" -#include "web_contents_delegate_qt.h" -#include "web_engine_settings.h" - -namespace QtWebEngineCore { - -void OnPdfStreamIntercepted( - const GURL& original_url, - std::string extension_id, - int frame_tree_node_id, - const content::ResourceRequestInfo::WebContentsGetter& - web_contents_getter) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(web_contents->GetDelegate()); - if (!contentsDelegate) - return; - - WebEngineSettings *settings = contentsDelegate->webEngineSettings(); - if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) - || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) { - // If the applications has been set up to always download PDF files to open them in an - // external viewer, trigger the download. - std::unique_ptr<download::DownloadUrlParameters> params( - content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( - web_contents, original_url, MISSING_TRAFFIC_ANNOTATION)); - content::BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()) - ->DownloadUrl(std::move(params)); - return; - } - - // The URL passes the original pdf resource url, that will be requested - // by the pdf viewer extension page. - content::NavigationController::LoadURLParams params( - GURL(base::StringPrintf("%s://%s/index.html?%s", extensions::kExtensionScheme, - extension_id.c_str(), - original_url.spec().c_str()))); - - params.frame_tree_node_id = frame_tree_node_id; - web_contents->GetController().LoadURLWithParams(params); -} - -bool ResourceDispatcherHostDelegateQt::ShouldInterceptResourceAsStream(net::URLRequest *request, - const std::string &mime_type, - GURL *origin, - std::string *payload) -{ - content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - - int render_process_host_id = -1; - int render_frame_id = -1; - if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_host_id, &render_frame_id)) - return false; - - std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist(); - - extensions::ExtensionSystemQt *extensionSystem = ProfileIODataQt::FromResourceContext(info->GetContext())->GetExtensionSystem(); - if (!extensionSystem) - return false; - - const scoped_refptr<const extensions::InfoMap> extension_info_map(extensionSystem->info_map()); - - for (const std::string &extension_id : whitelist) { - const extensions::Extension *extension = extension_info_map->extensions().GetByID(extension_id); - if (!extension) - continue; - - MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); - if (!handler) - continue; - if (handler->CanHandleMIMEType(mime_type)) { - StreamTargetInfo target_info; - *origin = extensions::Extension::GetBaseURLFromExtensionId(extension_id); - target_info.extension_id = extension_id; - target_info.view_id = base::GenerateGUID(); - *payload = target_info.view_id; - stream_target_info_[request] = target_info; - return true; - } - } - return false; -} - -// Informs the delegate that a Stream was created. The Stream can be read from -// the blob URL of the Stream, but can only be read once. -void ResourceDispatcherHostDelegateQt::OnStreamCreated(net::URLRequest *request, - std::unique_ptr<content::StreamInfo> stream) -{ - content::ResourceRequestInfo *info = content::ResourceRequestInfo::ForRequest(request); - std::map<net::URLRequest *, StreamTargetInfo>::iterator ix = stream_target_info_.find(request); - CHECK(ix != stream_target_info_.end()); - int render_frame_id = -1; - int render_process_id = -1; - if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_id, &render_frame_id)) { - stream_target_info_.erase(request); - request->Cancel(); - return; - } - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&OnPdfStreamIntercepted, - request->url(), ix->second.extension_id, - info->GetFrameTreeNodeId(), info->GetWebContentsGetterForRequest() - ) - ); - stream_target_info_.erase(request); -} - -} // namespace QtWebEngineCore diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h deleted file mode 100644 index 3039fd03e..000000000 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H -#define RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H - -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "extensions/buildflags/buildflags.h" - -#include "web_contents_adapter_client.h" - -namespace QtWebEngineCore { - -class ResourceDispatcherHostDelegateQt : public content::ResourceDispatcherHostDelegate { -public: - // If the stream will be rendered in a BrowserPlugin, |payload| will contain - // the data that should be given to the old ResourceHandler to forward to the - // renderer process. - bool ShouldInterceptResourceAsStream(net::URLRequest *request, - const std::string &mime_type, - GURL *origin, - std::string *payload) override; - - // Informs the delegate that a Stream was created. The Stream can be read from - // the blob URL of the Stream, but can only be read once. - void OnStreamCreated(net::URLRequest *request, - std::unique_ptr<content::StreamInfo> stream) override; -private: -#if BUILDFLAG(ENABLE_EXTENSIONS) - struct StreamTargetInfo { - std::string extension_id; - std::string view_id; - }; - std::map<net::URLRequest *, StreamTargetInfo> stream_target_info_; -#endif - -}; - -} // namespace QtWebEngineCore - -#endif // RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H diff --git a/src/core/renderer_host/user_resource_controller_host.cpp b/src/core/renderer_host/user_resource_controller_host.cpp index ed4d736f2..96625c13f 100644 --- a/src/core/renderer_host/user_resource_controller_host.cpp +++ b/src/core/renderer_host/user_resource_controller_host.cpp @@ -51,39 +51,37 @@ namespace QtWebEngineCore { -class UserResourceControllerHost::WebContentsObserverHelper : public content::WebContentsObserver { +class UserResourceControllerHost::WebContentsObserverHelper : public content::WebContentsObserver +{ public: WebContentsObserverHelper(UserResourceControllerHost *, content::WebContents *); // WebContentsObserver overrides: void RenderFrameCreated(content::RenderFrameHost *renderFrameHost) override; - void RenderFrameHostChanged(content::RenderFrameHost *oldHost, - content::RenderFrameHost *newHost) override; + void RenderFrameHostChanged(content::RenderFrameHost *oldHost, content::RenderFrameHost *newHost) override; void WebContentsDestroyed() override; private: UserResourceControllerHost *m_controllerHost; }; -UserResourceControllerHost::WebContentsObserverHelper::WebContentsObserverHelper(UserResourceControllerHost *controller, content::WebContents *contents) - : content::WebContentsObserver(contents) - , m_controllerHost(controller) +UserResourceControllerHost::WebContentsObserverHelper::WebContentsObserverHelper(UserResourceControllerHost *controller, + content::WebContents *contents) + : content::WebContentsObserver(contents) + , m_controllerHost(controller) { } -void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated( - content::RenderFrameHost *renderFrameHost) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated(content::RenderFrameHost *renderFrameHost) { content::WebContents *contents = web_contents(); const QList<UserScript> scripts = m_controllerHost->m_perContentsScripts.value(contents); for (const UserScript &script : scripts) - renderFrameHost->Send(new RenderFrameObserverHelper_AddScript( - renderFrameHost->GetRoutingID(), script.data())); + renderFrameHost->Send(new RenderFrameObserverHelper_AddScript(renderFrameHost->GetRoutingID(), script.data())); } -void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameHostChanged( - content::RenderFrameHost *oldHost, - content::RenderFrameHost *newHost) +void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameHostChanged(content::RenderFrameHost *oldHost, + content::RenderFrameHost *newHost) { if (oldHost) oldHost->Send(new RenderFrameObserverHelper_ClearScripts(oldHost->GetRoutingID())); @@ -95,10 +93,12 @@ void UserResourceControllerHost::WebContentsObserverHelper::WebContentsDestroyed delete this; } -class UserResourceControllerHost::RenderProcessObserverHelper : public content::RenderProcessHostObserver { +class UserResourceControllerHost::RenderProcessObserverHelper : public content::RenderProcessHostObserver +{ public: RenderProcessObserverHelper(UserResourceControllerHost *); void RenderProcessHostDestroyed(content::RenderProcessHost *) override; + private: UserResourceControllerHost *m_controllerHost; }; @@ -142,9 +142,9 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont } } contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_AddScript( - contents->GetRenderViewHost()->GetMainFrame()->GetRoutingID(), - script.data())); + new RenderFrameObserverHelper_AddScript( + contents->GetRenderViewHost()->GetMainFrame()->GetRoutingID(), + script.data())); } } @@ -165,8 +165,7 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC return false; const bool isProfileWideScript = !adapter; if (isProfileWideScript) { - QList<UserScript>::iterator it - = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); + QList<UserScript>::iterator it = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); if (it == m_profileWideScripts.end()) return false; for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) @@ -181,9 +180,7 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC if (it == list.end()) return false; contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_RemoveScript( - contents->GetMainFrame()->GetRoutingID(), - (*it).data())); + new RenderFrameObserverHelper_RemoveScript(contents->GetMainFrame()->GetRoutingID(), (*it).data())); list.erase(it); } return true; @@ -200,7 +197,7 @@ void UserResourceControllerHost::clearAllScripts(WebContentsAdapter *adapter) content::WebContents *contents = adapter->webContents(); m_perContentsScripts.remove(contents); contents->GetRenderViewHost()->Send( - new RenderFrameObserverHelper_ClearScripts(contents->GetMainFrame()->GetRoutingID())); + new RenderFrameObserverHelper_ClearScripts(contents->GetMainFrame()->GetRoutingID())); } } diff --git a/src/core/renderer_host/user_resource_controller_host.h b/src/core/renderer_host/user_resource_controller_host.h index 16a73f5fb..9d828feb6 100644 --- a/src/core/renderer_host/user_resource_controller_host.h +++ b/src/core/renderer_host/user_resource_controller_host.h @@ -66,7 +66,8 @@ namespace QtWebEngineCore { class WebContentsAdapter; -class Q_WEBENGINECORE_PRIVATE_EXPORT UserResourceControllerHost { +class Q_WEBENGINECORE_PRIVATE_EXPORT UserResourceControllerHost +{ public: UserResourceControllerHost(); diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index 4547b7fcf..6dbf2a370 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -61,7 +61,7 @@ inline QDebug operator<<(QDebug stream, content::RenderFrameHost *frame) return stream << "frame " << frame->GetRoutingID() << " in process " << frame->GetProcess()->GetID(); } -template <class T> +template<class T> inline QDebug operator<<(QDebug stream, const base::Optional<T> &opt) { if (opt) @@ -140,8 +140,7 @@ void WebChannelIPCTransportHost::DispatchWebChannelMessage(const std::vector<uin return; } - QJsonDocument doc = QJsonDocument::fromRawData( - reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size()); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), binaryJson.size()); if (!doc.isObject()) { qCCritical(log).nospace() << "received invalid webchannel message from " << frame; diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.h b/src/core/renderer_host/web_channel_ipc_transport_host.h index 94891f25f..d53b24b6b 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -53,9 +53,11 @@ QT_FORWARD_DECLARE_CLASS(QString) namespace QtWebEngineCore { -class WebChannelIPCTransportHost : public QWebChannelAbstractTransport +class WebChannelIPCTransportHost + : public QWebChannelAbstractTransport , private content::WebContentsObserver - , qtwebchannel::mojom::WebChannelTransportHost { + , qtwebchannel::mojom::WebChannelTransportHost +{ public: WebChannelIPCTransportHost(content::WebContents *webContents, uint32_t worldId = 0, QObject *parent = nullptr); ~WebChannelIPCTransportHost() override; diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp index dc7507f34..0e80859ae 100644 --- a/src/core/resource_bundle_qt.cpp +++ b/src/core/resource_bundle_qt.cpp @@ -66,9 +66,7 @@ void ResourceBundle::LoadCommonResources() gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { - LOG(WARNING) << "Unable to load image with id " << resource_id; - NOTREACHED(); // Want to assert in debug mode. - return GetEmptyImage(); + return GetImageNamed(resource_id); } // static diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 4cfcf6acd..6d763faa5 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -710,8 +710,6 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) if (!adapter) return; adapter->webContents()->GetController().LoadURLWithParams(params); - // Follow chrome::Navigate and invalidate the URL immediately. - adapter->m_webContentsDelegate->NavigationStateChanged(adapter->webContents(), content::INVALIDATE_TYPE_URL); adapter->focusIfNecessary(); }; @@ -769,7 +767,7 @@ void WebContentsAdapter::save(const QString &filePath, int savePageFormat) QUrl WebContentsAdapter::activeUrl() const { CHECK_INITIALIZED(QUrl()); - return m_webContentsDelegate->url(); + return m_webContentsDelegate->url(webContents()); } QUrl WebContentsAdapter::requestedUrl() const @@ -1141,6 +1139,17 @@ bool WebContentsAdapter::recentlyAudible() const return m_webContents->IsCurrentlyAudible(); } +qint64 WebContentsAdapter::renderProcessPid() const +{ + CHECK_INITIALIZED(0); + + content::RenderProcessHost *renderProcessHost = m_webContents->GetMainFrame()->GetProcess(); + const base::Process &process = renderProcessHost->GetProcess(); + if (!process.IsValid()) + return 0; + return process.Pid(); +} + void WebContentsAdapter::copyImageAt(const QPoint &location) { CHECK_INITIALIZED(); @@ -1894,7 +1903,7 @@ void WebContentsAdapter::discard() // Based on TabLifecycleUnitSource::TabLifecycleUnit::FinishDiscard if (m_webContents->IsLoading()) { - m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(), net::Error::ERR_ABORTED, + m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(webContents()), net::Error::ERR_ABORTED, QStringLiteral("Discarded")); } diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 11f8f9cb1..1afcdc01a 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -166,6 +166,7 @@ public: bool isAudioMuted() const; void setAudioMuted(bool mute); bool recentlyAudible() const; + qint64 renderProcessPid() const; // Must match blink::WebMediaPlayerAction::Type. enum MediaPlayerAction { diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 4bdb55b4c..3a75185f8 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -125,7 +125,9 @@ public: QUrl linkUrl; QUrl unfilteredLinkUrl; QUrl mediaUrl; + QString altText; QString linkText; + QString titleText; QString selectedText; QString suggestedFileName; QString misspelledWord; @@ -215,6 +217,14 @@ public: return d->unfilteredLinkUrl; } + void setAltText(const QString &text) { + d->altText = text; + } + + QString altText() const { + return d->altText; + } + void setLinkText(const QString &text) { d->linkText = text; } @@ -223,6 +233,14 @@ public: return d->linkText; } + void setTitleText(const QString &text) { + d->titleText = text; + } + + QString titleText() const { + return d->titleText; + } + void setSelectedText(const QString &text) { d->selectedText = text; } @@ -434,12 +452,13 @@ public: virtual void recommendedStateChanged(LifecycleState) = 0; virtual void visibleChanged(bool) = 0; virtual void titleChanged(const QString&) = 0; - virtual void urlChanged(const QUrl&) = 0; + virtual void urlChanged() = 0; virtual void iconChanged(const QUrl&) = 0; virtual void loadProgressChanged(int progress) = 0; virtual void didUpdateTargetURL(const QUrl&) = 0; virtual void selectionChanged() = 0; virtual void recentlyAudibleChanged(bool recentlyAudible) = 0; + virtual void renderProcessPidChanged(qint64 pid) = 0; virtual QRectF viewportRect() const = 0; virtual QColor backgroundColor() const = 0; virtual void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 255ff0034..f409d8a7c 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -49,7 +49,6 @@ #include "favicon_manager.h" #include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" -#include "net/network_delegate_qt.h" #include "profile_qt.h" #include "qwebengineregisterprotocolhandlerrequest.h" #include "register_protocol_handler_request_controller_impl.h" @@ -189,36 +188,20 @@ static bool shouldUseActualURL(content::NavigationEntry *entry) void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) { - if (changed_flags & content::INVALIDATE_TYPE_URL) { - content::NavigationEntry *entry = source->GetController().GetVisibleEntry(); - - QUrl newUrl; - if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme)) { - Q_ASSERT(entry); - GURL url = entry->GetURL(); - - // Strip user name, password and reference section from view-source URLs - if (url.has_password() || url.has_username() || url.has_ref()) { - GURL strippedUrl = net::SimplifyUrlForRequest(entry->GetURL()); - newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); - } - } - - // If there is a visible entry there are special cases when we dont wan't to use the actual URL - if (entry && newUrl.isEmpty()) - newUrl = shouldUseActualURL(entry) ? toQt(entry->GetURL()) : toQt(entry->GetVirtualURL()); - - if (m_url != newUrl) { - m_url = newUrl; - m_viewClient->urlChanged(m_url); - } + if (changed_flags & content::INVALIDATE_TYPE_URL && !m_pendingUrlUpdate) { + m_pendingUrlUpdate = true; + base::WeakPtr<WebContentsDelegateQt> delegate = AsWeakPtr(); + QTimer::singleShot(0, [delegate, this](){ if (delegate) m_viewClient->urlChanged();}); } if (changed_flags & content::INVALIDATE_TYPE_TITLE) { QString newTitle = toQt(source->GetTitle()); if (m_title != newTitle) { m_title = newTitle; - m_viewClient->titleChanged(m_title); + QTimer::singleShot(0, [delegate = AsWeakPtr(), title = newTitle] () { + if (delegate) + delegate->adapterClient()->titleChanged(title); + }); } } @@ -232,6 +215,25 @@ void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, } } +QUrl WebContentsDelegateQt::url(content::WebContents* source) const { + + content::NavigationEntry *entry = source->GetController().GetVisibleEntry(); + QUrl newUrl; + if (entry) { + GURL url = entry->GetURL(); + // Strip user name, password and reference section from view-source URLs + if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) && + (url.has_password() || url.has_username() || url.has_ref())) { + GURL strippedUrl = net::SimplifyUrlForRequest(url); + newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); + } + // If there is a visible entry there are special cases when we dont wan't to use the actual URL + if (newUrl.isEmpty()) + newUrl = shouldUseActualURL(entry) ? toQt(url) : toQt(entry->GetVirtualURL()); + } + m_pendingUrlUpdate = false; + return newUrl; +} void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) @@ -286,10 +288,17 @@ void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_ void WebContentsDelegateQt::RenderProcessGone(base::TerminationStatus status) { + // RenderProcessHost::FastShutdownIfPossible results in TERMINATION_STATUS_STILL_RUNNING + if (status != base::TERMINATION_STATUS_STILL_RUNNING) { + m_viewClient->renderProcessTerminated( + m_viewClient->renderProcessExitStatus(status), + web_contents()->GetCrashedErrorCode()); + } + // Based one TabLoadTracker::RenderProcessGone - if (status == base::TerminationStatus::TERMINATION_STATUS_NORMAL_TERMINATION - || status == base::TerminationStatus::TERMINATION_STATUS_STILL_RUNNING) { + if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION + || status == base::TERMINATION_STATUS_STILL_RUNNING) { return; } @@ -306,6 +315,14 @@ void WebContentsDelegateQt::RenderFrameHostChanged(content::RenderFrameHost *old if (new_host) { content::FrameTreeNode *new_node = static_cast<content::RenderFrameHostImpl *>(new_host)->frame_tree_node(); m_frameFocusedObserver.addNode(new_node); + + // Is this a main frame? + if (new_host->GetFrameOwnerElementType() == blink::FrameOwnerElementType::kNone) { + content::RenderProcessHost *renderProcessHost = new_host->GetProcess(); + const base::Process &process = renderProcessHost->GetProcess(); + if (process.IsValid()) + m_viewClient->renderProcessPidChanged(process.Pid()); + } } } @@ -475,8 +492,10 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame return; } - if (render_frame_host->GetParent()) + if (render_frame_host->GetParent()) { + m_viewClient->updateNavigationActions(); return; + } if (!m_faviconManager->hasCandidate()) m_viewClient->iconChanged(QUrl()); @@ -803,7 +822,6 @@ WebContentsAdapter *WebContentsDelegateQt::webContentsAdapter() const void WebContentsDelegateQt::copyStateFrom(WebContentsDelegateQt *source) { - m_url = source->m_url; m_title = source->m_title; NavigationStateChanged(web_contents(), content::INVALIDATE_TYPE_URL); m_faviconManager->copyStateFrom(source->m_faviconManager.data()); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index ba8c6b5a1..33fd49b3d 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -114,7 +114,7 @@ public: WebContentsDelegateQt(content::WebContents*, WebContentsAdapterClient *adapterClient); ~WebContentsDelegateQt(); - QUrl url() const { return m_url; } + QUrl url(content::WebContents *source) const; QString title() const { return m_title; } // WebContentsDelegate overrides @@ -223,12 +223,12 @@ private: bool m_didStartLoadingSeen; FrameFocusedObserver m_frameFocusedObserver; - QUrl m_url; QString m_title; int m_audioStreamCount = 0; int m_videoStreamCount = 0; int m_mirroringStreamCount = 0; int m_desktopStreamCount = 0; + mutable bool m_pendingUrlUpdate = false; base::WeakPtrFactory<WebContentsDelegateQt> m_weakPtrFactory { this }; }; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index ef7c09665..e50835f74 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -195,6 +195,8 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara ret.setPosition(QPoint(params.x, params.y)); ret.setLinkUrl(toQt(params.link_url)); ret.setLinkText(toQt(params.link_text.data())); + ret.setAltText(toQt(params.alt_text.data())); + ret.setTitleText(toQt(params.title_text.data())); ret.setUnfilteredLinkUrl(toQt(params.unfiltered_link_url)); ret.setSelectedText(toQt(params.selection_text.data())); ret.setMediaUrl(toQt(params.src_url)); diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index a4ceb3a97..79c093fab 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -49,6 +49,7 @@ #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" +#include "chrome/common/chrome_switches.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "chrome/browser/printing/print_job_manager.h" #include "components/printing/browser/features.h" @@ -73,6 +74,7 @@ #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" +#include "content/public/common/network_service_util.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "media/audio/audio_manager.h" @@ -182,6 +184,18 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) namespace QtWebEngineCore { +#if defined(Q_OS_WIN) +sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info) +{ + static sandbox::SandboxInterfaceInfo *g_info = nullptr; + if (info) { + Q_ASSERT(g_info == nullptr); + g_info = info; + } + return g_info; +} +#endif + extern std::unique_ptr<base::MessagePump> messagePumpFactory(); bool usingSoftwareDynamicGL() @@ -199,6 +213,21 @@ bool usingSoftwareDynamicGL() #endif } +void setupProxyPac(base::CommandLine *commandLine){ + if (commandLine->HasSwitch(switches::kProxyPacUrl)) { + QUrl pac_url(toQt(commandLine->GetSwitchValueASCII(switches::kProxyPacUrl))); + if (pac_url.isValid() && pac_url.isLocalFile()) { + QFile file(pac_url.toLocalFile()); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QByteArray ba = file.readAll(); + commandLine->RemoveSwitch(switches::kProxyPacUrl); + commandLine->AppendSwitchASCII(switches::kProxyPacUrl, + ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); + } + } + } +} + scoped_refptr<QtWebEngineCore::WebEngineContext> WebEngineContext::m_handle; bool WebEngineContext::m_destroyed = false; @@ -248,7 +277,7 @@ void WebEngineContext::destroy() // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. - destroyGpuProcess(); + destroyGpuProcess(m_threadedGpu); base::MessagePump::Delegate *delegate = static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( @@ -400,7 +429,8 @@ static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *fe } WebEngineContext::WebEngineContext() - : m_mainDelegate(new ContentMainDelegateQt) + : m_threadedGpu(true) + , m_mainDelegate(new ContentMainDelegateQt) , m_globalQObject(new QObject()) { #if defined(Q_OS_MACOS) @@ -449,15 +479,13 @@ WebEngineContext::WebEngineContext() #endif base::CommandLine* parsedCommandLine = commandLine(); - + setupProxyPac(parsedCommandLine); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); // Enable sandboxing on OS X and Linux (Desktop / Embedded) by default. bool disable_sandbox = qEnvironmentVariableIsSet(kDisableSandboxEnv); if (!disable_sandbox) { -#if defined(Q_OS_WIN) - parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); -#elif defined(Q_OS_LINUX) +#if defined(Q_OS_LINUX) parsedCommandLine->AppendSwitch(service_manager::switches::kDisableSetuidSandbox); #endif } else { @@ -466,20 +494,6 @@ WebEngineContext::WebEngineContext() } parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); - // These are currently only default on OS X, and we don't support them: - parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy); - parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferCompositorResources); - - // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X. - parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); - -#if defined(Q_OS_MACOS) - // Accelerated decoding currently does not work on macOS due to issues with OpenGL Rectangle - // texture support. See QTBUG-60002. - parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); - // Same problem with Pepper using OpenGL images. - parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium); -#endif #if defined(Q_OS_WIN) // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create @@ -505,13 +519,12 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); #endif - bool threadedGpu = true; #ifndef QT_NO_OPENGL - threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); + m_threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); #endif - threadedGpu = threadedGpu && !qEnvironmentVariableIsSet(kDisableInProcGpuThread); + m_threadedGpu = m_threadedGpu && !qEnvironmentVariableIsSet(kDisableInProcGpuThread); - bool enableViz = ((threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) + bool enableViz = ((m_threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) || parsedCommandLine->HasSwitch("enable-viz-display-compositor")); parsedCommandLine->RemoveSwitch("disable-viz-display-compositor"); parsedCommandLine->RemoveSwitch("enable-viz-display-compositor"); @@ -529,8 +542,12 @@ WebEngineContext::WebEngineContext() // The video-capture service is not functioning at this moment (since 69) appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); - // We do not yet support the network-service, but it is enabled by default since 75. - appendToFeatureList(disableFeatures, network::features::kNetworkService.name); + // We do not yet fully support the network-service, but it has been enabled by default since 75. + bool enableNetworkService = !parsedCommandLine->HasSwitch("disable-network-service"); + parsedCommandLine->RemoveSwitch("disable-network-service"); + if (!enableNetworkService) + appendToFeatureList(disableFeatures, network::features::kNetworkService.name); + // BlinkGenPropertyTrees is enabled by default in 75, but causes regressions. appendToFeatureList(disableFeatures, blink::features::kBlinkGenPropertyTrees.name); @@ -556,6 +573,21 @@ WebEngineContext::WebEngineContext() } if (!enableViz) { + // These are currently only default on OS X, and we don't support them: + parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy); + parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferCompositorResources); + + // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X. + parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); + +#if defined(Q_OS_MACOS) + // Accelerated decoding currently does not work on macOS due to issues with OpenGL Rectangle + // texture support. See QTBUG-60002. + parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); + // Same problem with Pepper using OpenGL images. + parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium); +#endif + // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); // VideoSurfaceLayer is enabled by default since 75. We don't support it. @@ -650,15 +682,18 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - registerMainThreadFactories(threadedGpu); + registerMainThreadFactories(m_threadedGpu); SetContentClient(new ContentClientQt); content::ContentMainParams contentMainParams(m_mainDelegate.get()); #if defined(OS_WIN) + contentMainParams.sandbox_info = staticSandboxInterfaceInfo(); sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); - contentMainParams.sandbox_info = &sandbox_info; + if (!contentMainParams.sandbox_info) { + content::InitializeSandboxInfo(&sandbox_info); + contentMainParams.sandbox_info = &sandbox_info; + } #endif m_contentRunner->Initialize(contentMainParams); @@ -677,6 +712,9 @@ WebEngineContext::WebEngineContext() m_serviceManagerEnvironment = std::make_unique<content::ServiceManagerEnvironment>(content::BrowserTaskExecutor::CreateIOThread()); m_startupData = m_serviceManagerEnvironment->CreateBrowserStartupData(); + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + content::ForceInProcessNetworkService(true); + // Once the MessageLoop has been created, attach a top-level RunLoop. m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 5892017c5..edced9b42 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -40,9 +40,12 @@ #ifndef WEB_ENGINE_CONTEXT_H #define WEB_ENGINE_CONTEXT_H +#include "qtwebenginecoreglobal_p.h" + #include "build_config_qt.h" #include "base/memory/ref_counted.h" #include "base/values.h" + #include <QVector> namespace base { @@ -75,6 +78,12 @@ class PrintJobManager; } #endif +#ifdef Q_OS_WIN +namespace sandbox { +struct SandboxInterfaceInfo; +} +#endif + QT_FORWARD_DECLARE_CLASS(QObject) namespace QtWebEngineCore { @@ -86,6 +95,10 @@ class ProfileAdapter; bool usingSoftwareDynamicGL(); +#ifdef Q_OS_WIN +Q_WEBENGINECORE_PRIVATE_EXPORT sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info = nullptr); +#endif + typedef std::tuple<bool, QString, QString> ProxyAuthentication; class WebEngineContext : public base::RefCounted<WebEngineContext> { @@ -116,8 +129,9 @@ private: ~WebEngineContext(); static void registerMainThreadFactories(bool threaded); - static void destroyGpuProcess(); + static void destroyGpuProcess(bool threaded); + bool m_threadedGpu; std::unique_ptr<base::RunLoop> m_runLoop; std::unique_ptr<ContentMainDelegateQt> m_mainDelegate; std::unique_ptr<content::ContentMainRunner> m_contentRunner; diff --git a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp index e92cf3e9b..f0f055676 100644 --- a/src/core/web_engine_context_threads.cpp +++ b/src/core/web_engine_context_threads.cpp @@ -57,6 +57,8 @@ #include <memory> +#include <QEventLoop> + namespace QtWebEngineCore { struct GpuThreadControllerQt : content::GpuThreadController @@ -90,6 +92,20 @@ struct GpuThreadControllerQt : content::GpuThreadController s_gpuProcess->set_main_thread(childThread); } + static void cleanupVizProcess() + { + auto gpuChildThread = content::GpuChildThread::instance(); + if (!gpuChildThread) + return; + auto vizMain = gpuChildThread->viz_main(); + auto vizCompositorThreadRunner = vizMain->viz_compositor_thread_runner(); + if (!vizCompositorThreadRunner) + return; + QEventLoop loop; + vizCompositorThreadRunner->CleanupForShutdown(base::BindOnce(&QEventLoop::quit, base::Unretained(&loop))); + loop.exec(); + } + static void destroyGpuProcess() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -117,8 +133,10 @@ static std::unique_ptr<content::GpuThreadController> createGpuThreadController( } // static -void WebEngineContext::destroyGpuProcess() +void WebEngineContext::destroyGpuProcess(bool threaded) { + if (!threaded) + GpuThreadControllerQt::cleanupVizProcess(); GpuThreadControllerQt::destroyGpuProcess(); } |