diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-12 12:41:40 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-16 12:03:57 +0100 |
commit | 3c544a5d0d59b0533f507a6131fbbc093ed223ea (patch) | |
tree | c64d3ae8e17280350037ff1d6687ec797ca4715c /src/core/net | |
parent | e7c869c225075d898cb5d20b194af4b939d2dbc1 (diff) | |
parent | fdec85eba16d6321597e93b447bc13a611cfdd23 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I0dd7c64669f4b130047a4a3836f62f7ee5b5f8d9
Diffstat (limited to 'src/core/net')
-rw-r--r-- | src/core/net/plugin_response_interceptor_url_loader_throttle.cpp | 152 | ||||
-rw-r--r-- | src/core/net/plugin_response_interceptor_url_loader_throttle.h | 12 |
2 files changed, 108 insertions, 56 deletions
diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp index 334b147a5..bca059ae6 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -40,59 +40,27 @@ #include "plugin_response_interceptor_url_loader_throttle.h" #include "base/bind.h" +#include "base/guid.h" #include "base/task/post_task.h" +#include "chrome/browser/extensions/api/streams_private/streams_private_api.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/download_request_utils.h" #include "content/public/browser/download_utils.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" +#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" +#include "extensions/extension_system_qt.h" #include "web_contents_delegate_qt.h" #include <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(QWebEngineSettings::PdfViewerEnabled) - || !settings->testAttribute(QWebEngineSettings::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) @@ -102,31 +70,111 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL network::mojom::URLResponseHead *response_head, bool *defer) { - Q_UNUSED(defer); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 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); - } + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(m_frame_tree_node_id); + if (!web_contents) + return; std::string extension_id; - // FIXME: We should use extensions::InfoMap in the future: if (response_head->mime_type == "application/pdf") extension_id = extension_misc::kPdfExtensionId; if (extension_id.empty()) return; - *defer = true; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); + if (!contentsDelegate) + return; + + WebEngineSettings *settings = contentsDelegate->webEngineSettings(); + if (!settings->testAttribute(QWebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(QWebEngineSettings::PluginsEnabled)) { + // PluginServiceFilterQt will inform the URLLoader about the disabled state of plugins + // and we can expect the download to be triggered automatically. It's unnecessary to + // go further and start the guest view embedding process. + return; + } + + // Chrome's PDF Extension does not work properly in the face of a restrictive + // Content-Security-Policy, and does not currently respect the policy anyway. + // Ignore CSP served on a PDF response. https://crbug.com/271452 + if (extension_id == extension_misc::kPdfExtensionId && response_head->headers) + response_head->headers->RemoveHeader("Content-Security-Policy"); + + MimeTypesHandler::ReportUsedHandler(extension_id); + + std::string view_id = base::GenerateGUID(); + // The string passed down to the original client with the response body. + std::string payload = view_id; + + mojo::PendingRemote<network::mojom::URLLoader> dummy_new_loader; + ignore_result(dummy_new_loader.InitWithNewPipeAndPassReceiver()); + mojo::Remote<network::mojom::URLLoaderClient> new_client; + mojo::PendingReceiver<network::mojom::URLLoaderClient> new_client_receiver = + new_client.BindNewPipeAndPassReceiver(); + + + uint32_t data_pipe_size = 64U; + // Provide the MimeHandlerView code a chance to override the payload. This is + // the case where the resource is handled by frame-based MimeHandlerView. + *defer = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, view_id, + &payload, &data_pipe_size, + base::BindOnce( + &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, + weak_factory_.GetWeakPtr())); + + mojo::DataPipe data_pipe(data_pipe_size); + uint32_t len = static_cast<uint32_t>(payload.size()); + CHECK_EQ(MOJO_RESULT_OK, + data_pipe.producer_handle->WriteData( + payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + + + new_client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle)); + + network::URLLoaderCompletionStatus status(net::OK); + status.decoded_body_length = len; + new_client->OnComplete(status); + + mojo::PendingRemote<network::mojom::URLLoader> original_loader; + mojo::PendingReceiver<network::mojom::URLLoaderClient> original_client; + delegate_->InterceptResponse(std::move(dummy_new_loader), + std::move(new_client_receiver), &original_loader, + &original_client); + + // Make a deep copy of URLResponseHead before passing it cross-thread. + auto deep_copied_response = response_head->Clone(); + if (response_head->headers) { + deep_copied_response->headers = + base::MakeRefCounted<net::HttpResponseHeaders>( + response_head->headers->raw_headers()); + } + + auto transferrable_loader = blink::mojom::TransferrableURLLoader::New(); + transferrable_loader->url = GURL( + extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() + + base::GenerateGUID()); + transferrable_loader->url_loader = std::move(original_loader); + transferrable_loader->url_loader_client = std::move(original_client); + transferrable_loader->head = std::move(deep_copied_response); + transferrable_loader->head->intercepted_by_plugin = true; + + bool embedded = m_resource_type != + static_cast<int>(blink::mojom::ResourceType::kMainFrame); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, + extension_id, view_id, embedded, m_frame_tree_node_id, + -1 /* render_process_id */, -1 /* render_frame_id */, + std::move(transferrable_loader), response_url)); +} - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&onPdfStreamIntercepted, - response_url, - extension_id, - m_frame_tree_node_id)); +void PluginResponseInterceptorURLLoaderThrottle::ResumeLoad() { + delegate_->Resume(); } } // namespace QtWebEngineCore diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index 7b9db6490..205ab25e6 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -41,11 +41,11 @@ #define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" namespace content { class BrowserContext; -class ResourceContext; } namespace QtWebEngineCore { @@ -53,8 +53,6 @@ namespace QtWebEngineCore { class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle { public: - PluginResponseInterceptorURLLoaderThrottle(content::ResourceContext *resource_context, - int resource_type, int frame_tree_node_id); PluginResponseInterceptorURLLoaderThrottle(content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id); ~PluginResponseInterceptorURLLoaderThrottle() override = default; @@ -63,11 +61,17 @@ private: // content::URLLoaderThrottle overrides; void WillProcessResponse(const GURL &response_url, network::mojom::URLResponseHead *response_head, bool *defer) override; - content::ResourceContext *m_resource_context = nullptr; + // Resumes loading for an intercepted response. This would give the extension + // layer chance to initialize its browser side state. + void ResumeLoad(); + content::BrowserContext *m_browser_context = nullptr; const int m_resource_type; const int m_frame_tree_node_id; + base::WeakPtrFactory<PluginResponseInterceptorURLLoaderThrottle> + weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; |