diff --git a/BUILD.gn b/BUILD.gn index 4d51c2e66..0a232f7a1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -600,6 +600,8 @@ static_library("libcef_static") { "libcef/renderer/render_urlrequest_impl.cc", "libcef/renderer/render_urlrequest_impl.h", "libcef/renderer/thread_util.h", + "libcef/renderer/url_loader_throttle_provider_impl.cc", + "libcef/renderer/url_loader_throttle_provider_impl.h", "libcef/renderer/v8_impl.cc", "libcef/renderer/v8_impl.h", "libcef/utility/content_utility_client.cc", diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index a46087f3b..64b03724a 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -62,6 +62,7 @@ #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/plugins/plugin_info_host_impl.h" #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" +#include "chrome/browser/plugins/plugin_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/common/chrome_paths.h" @@ -1442,6 +1443,16 @@ blink::UserAgentMetadata CefContentBrowserClient::GetUserAgentMetadata() const { return metadata; } +base::flat_set +CefContentBrowserClient::GetPluginMimeTypesWithExternalHandlers( + content::ResourceContext* resource_context) { + base::flat_set mime_types; + auto map = PluginUtils::GetMimeTypeToExtensionIdMap(resource_context); + for (const auto& pair : map) + mime_types.insert(pair.first); + return mime_types; +} + void CefContentBrowserClient::RegisterCustomScheme(const std::string& scheme) { // Register as a Web-safe scheme so that requests for the scheme from a // render process will be allowed in resource_dispatcher_host_impl.cc diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index d661f60b1..48d49b0cf 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -211,6 +211,8 @@ class CefContentBrowserClient : public content::ContentBrowserClient { std::string GetChromeProduct() const override; std::string GetUserAgent() const override; blink::UserAgentMetadata GetUserAgentMetadata() const override; + base::flat_set GetPluginMimeTypesWithExternalHandlers( + content::ResourceContext* resource_context) override; // Perform browser process registration for the custom scheme. void RegisterCustomScheme(const std::string& scheme); diff --git a/libcef/browser/extensions/extension_system.cc b/libcef/browser/extensions/extension_system.cc index d67498a95..2fdfb3ed5 100644 --- a/libcef/browser/extensions/extension_system.cc +++ b/libcef/browser/extensions/extension_system.cc @@ -199,7 +199,7 @@ void CefExtensionSystem::Init() { // mime_handler_private.idl), and returns the unique View ID via the // |payload| argument. // 5. The unique View ID arrives in the renderer process via - // ResourceLoader::didReceiveData and triggers creation of a new Document. + // ResourceLoader::DidReceiveData and triggers creation of a new Document. // DOMImplementation::createDocument indirectly calls // RendererBlinkPlatformImpl::getPluginList to retrieve the list of // supported plugins from the browser process. If a plugin supports the diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index 3cc1b2b70..dd6b88f9e 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -564,6 +564,13 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) { disable_features.push_back(network::features::kOutOfBlinkCors.name); } + if (features::kMimeHandlerViewInCrossProcessFrame.default_state == + base::FEATURE_ENABLED_BY_DEFAULT) { + // TODO: Add support for cross-process mime handler view (see issue #2727) + disable_features.push_back( + features::kMimeHandlerViewInCrossProcessFrame.name); + } + if (!disable_features.empty()) { DCHECK(!base::FeatureList::GetInstance()); std::string disable_features_str = diff --git a/libcef/renderer/content_renderer_client.cc b/libcef/renderer/content_renderer_client.cc index 11375ef7c..e6807b6e9 100644 --- a/libcef/renderer/content_renderer_client.cc +++ b/libcef/renderer/content_renderer_client.cc @@ -37,6 +37,7 @@ #include "libcef/renderer/render_message_filter.h" #include "libcef/renderer/render_thread_observer.h" #include "libcef/renderer/thread_util.h" +#include "libcef/renderer/url_loader_throttle_provider_impl.h" #include "libcef/renderer/v8_impl.h" #include "base/command_line.h" @@ -53,6 +54,7 @@ #include "chrome/common/constants.mojom.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/chrome_content_renderer_client.h" +#include "chrome/renderer/extensions/chrome_extensions_renderer_client.h" #include "chrome/renderer/loadtimes_extension_bindings.h" #include "chrome/renderer/media/chrome_key_systems.h" #include "chrome/renderer/pepper/chrome_pdf_print_client.h" @@ -74,6 +76,7 @@ #include "content/public/common/content_constants.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" +#include "content/public/common/mime_handler_view_mode.h" #include "content/public/renderer/plugin_instance_throttler.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" @@ -497,6 +500,46 @@ void CefContentRendererClient::RenderViewCreated( MaybeCreateBrowser(render_view, render_view->GetMainRenderFrame()); } +bool CefContentRendererClient::IsPluginHandledExternally( + content::RenderFrame* render_frame, + const blink::WebElement& plugin_element, + const GURL& original_url, + const std::string& mime_type) { + if (!extensions::ExtensionsEnabled()) + return false; + + DCHECK(plugin_element.HasHTMLTagName("object") || + plugin_element.HasHTMLTagName("embed")); + if (!content::MimeHandlerViewMode::UsesCrossProcessFrame()) + return false; + // Blink will next try to load a WebPlugin which would end up in + // OverrideCreatePlugin, sending another IPC only to find out the plugin is + // not supported. Here it suffices to return false but there should perhaps be + // a more unified approach to avoid sending the IPC twice. + chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New(); + ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo( + render_frame->GetRoutingID(), original_url, + render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), mime_type, + &plugin_info); + // TODO(ekaramad): Not continuing here due to a disallowed status should take + // us to CreatePlugin. See if more in depths investigation of |status| is + // necessary here (see https://crbug.com/965747). For now, returning false + // should take us to CreatePlugin after HTMLPlugInElement which is called + // through HTMLPlugInElement::LoadPlugin code path. + if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed && + plugin_info->status != + chrome::mojom::PluginStatus::kPlayImportantContent) { + // We could get here when a MimeHandlerView is loaded inside a + // which is using permissions API (see WebViewPluginTests). + ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin( + plugin_element); + return false; + } + return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( + plugin_element, original_url, plugin_info->actual_mime_type, + plugin_info->plugin); +} + bool CefContentRendererClient::OverrideCreatePlugin( content::RenderFrame* render_frame, const blink::WebPluginParams& params, @@ -628,6 +671,12 @@ void CefContentRendererClient::CreateRendererService( service_binding_.Bind(std::move(service_request)); } +std::unique_ptr +CefContentRendererClient::CreateURLLoaderThrottleProvider( + content::URLLoaderThrottleProviderType provider_type) { + return std::make_unique(provider_type); +} + void CefContentRendererClient::OnBindInterface( const service_manager::BindSourceInfo& remote_info, const std::string& name, diff --git a/libcef/renderer/content_renderer_client.h b/libcef/renderer/content_renderer_client.h index 1c3a0253e..0e10d37ce 100644 --- a/libcef/renderer/content_renderer_client.h +++ b/libcef/renderer/content_renderer_client.h @@ -106,6 +106,10 @@ class CefContentRendererClient void RenderThreadConnected() override; void RenderFrameCreated(content::RenderFrame* render_frame) override; void RenderViewCreated(content::RenderView* render_view) override; + bool IsPluginHandledExternally(content::RenderFrame* render_frame, + const blink::WebElement& plugin_element, + const GURL& original_url, + const std::string& mime_type) override; bool OverrideCreatePlugin(content::RenderFrame* render_frame, const blink::WebPluginParams& params, blink::WebPlugin** plugin) override; @@ -138,6 +142,9 @@ class CefContentRendererClient void DevToolsAgentDetached() override; void CreateRendererService( service_manager::mojom::ServiceRequest service_request) override; + std::unique_ptr + CreateURLLoaderThrottleProvider( + content::URLLoaderThrottleProviderType provider_type) override; // service_manager::Service implementation. void OnBindInterface(const service_manager::BindSourceInfo& remote_info, diff --git a/libcef/renderer/url_loader_throttle_provider_impl.cc b/libcef/renderer/url_loader_throttle_provider_impl.cc new file mode 100644 index 000000000..b85e42b9e --- /dev/null +++ b/libcef/renderer/url_loader_throttle_provider_impl.cc @@ -0,0 +1,78 @@ +// 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. + +#include "libcef/renderer/url_loader_throttle_provider_impl.h" + +#include "libcef/common/extensions/extensions_util.h" + +#include + +#include "base/feature_list.h" +#include "content/public/common/content_features.h" +#include "content/public/renderer/render_frame.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h" +#include "services/network/public/cpp/features.h" +#include "third_party/blink/public/platform/web_url.h" + +CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl( + content::URLLoaderThrottleProviderType type) + : type_(type) { + DETACH_FROM_THREAD(thread_checker_); +} + +CefURLLoaderThrottleProviderImpl::~CefURLLoaderThrottleProviderImpl() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl( + const CefURLLoaderThrottleProviderImpl& other) + : type_(other.type_) { + DETACH_FROM_THREAD(thread_checker_); +} + +std::unique_ptr +CefURLLoaderThrottleProviderImpl::Clone() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return base::WrapUnique(new CefURLLoaderThrottleProviderImpl(*this)); +} + +std::vector> +CefURLLoaderThrottleProviderImpl::CreateThrottles( + int render_frame_id, + const blink::WebURLRequest& request, + content::ResourceType resource_type) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + std::vector> throttles; + + bool network_service_enabled = + base::FeatureList::IsEnabled(network::features::kNetworkService); + // Some throttles have already been added in the browser for frame resources. + // Don't add them for frame requests. + bool is_frame_resource = content::IsResourceTypeFrame(resource_type); + + DCHECK(!is_frame_resource || + type_ == content::URLLoaderThrottleProviderType::kFrame); + + if (extensions::ExtensionsEnabled() && network_service_enabled && + type_ == content::URLLoaderThrottleProviderType::kFrame && + resource_type == content::ResourceType::kObject) { + content::RenderFrame* render_frame = + content::RenderFrame::FromRoutingID(render_frame_id); + auto mime_handlers = + extensions::MimeHandlerViewContainer::FromRenderFrame(render_frame); + GURL gurl(request.Url()); + for (auto* handler : mime_handlers) { + auto throttle = handler->MaybeCreatePluginThrottle(gurl); + if (throttle) { + throttles.push_back(std::move(throttle)); + break; + } + } + } + + return throttles; +} + +void CefURLLoaderThrottleProviderImpl::SetOnline(bool is_online) {} diff --git a/libcef/renderer/url_loader_throttle_provider_impl.h b/libcef/renderer/url_loader_throttle_provider_impl.h new file mode 100644 index 000000000..a1269f4e9 --- /dev/null +++ b/libcef/renderer/url_loader_throttle_provider_impl.h @@ -0,0 +1,45 @@ +// 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. + +#ifndef CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_ +#define CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_ + +#include +#include + +#include "base/threading/thread_checker.h" +#include "content/public/renderer/url_loader_throttle_provider.h" + +// Instances must be constructed on the render thread, and then used and +// destructed on a single thread, which can be different from the render thread. +class CefURLLoaderThrottleProviderImpl + : public content::URLLoaderThrottleProvider { + public: + explicit CefURLLoaderThrottleProviderImpl( + content::URLLoaderThrottleProviderType type); + + ~CefURLLoaderThrottleProviderImpl() override; + + // content::URLLoaderThrottleProvider implementation. + std::unique_ptr Clone() override; + std::vector> CreateThrottles( + int render_frame_id, + const blink::WebURLRequest& request, + content::ResourceType resource_type) override; + void SetOnline(bool is_online) override; + + private: + // This copy constructor works in conjunction with Clone(), not intended for + // general use. + CefURLLoaderThrottleProviderImpl( + const CefURLLoaderThrottleProviderImpl& other); + + content::URLLoaderThrottleProviderType type_; + + THREAD_CHECKER(thread_checker_); + + DISALLOW_ASSIGN(CefURLLoaderThrottleProviderImpl); +}; + +#endif // CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_