From 1ad95eca4a8e7505d860874332f91c2f486be9b9 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Ali Date: Fri, 13 Oct 2017 10:52:11 +0200 Subject: [PATCH 01/13] Add support for pdf in sub frames (https://github.com/electron/electron/issues/9192#issuecomment-335543866) --- .../atom_resource_dispatcher_host_delegate.cc | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 53d91b4be954..4094b240dca7 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -15,6 +15,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/stream_info.h" +#include "content/public/browser/render_frame_host.h" #include "net/base/escape.h" #include "net/ssl/client_cert_store.h" #include "net/url_request/url_request.h" @@ -65,34 +66,33 @@ void HandleExternalProtocolInUI( } void OnPdfResourceIntercepted( - const GURL& original_url, - const content::ResourceRequestInfo::WebContentsGetter& - web_contents_getter) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; + const GURL& original_url, + int frame_tree_node_id, + const content::ResourceRequestInfo::WebContentsGetter& + web_contents_getter) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; - if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { - auto browser_context = web_contents->GetBrowserContext(); - auto download_manager = - content::BrowserContext::GetDownloadManager(browser_context); + if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { + auto browser_context = web_contents->GetBrowserContext(); + auto download_manager = + content::BrowserContext::GetDownloadManager(browser_context); - download_manager->DownloadUrl( - content::DownloadUrlParameters::CreateForWebContentsMainFrame( - web_contents, original_url)); - return; - } + download_manager->DownloadUrl( + content::DownloadUrlParameters::CreateForWebContentsMainFrame( + web_contents, original_url)); + return; + } - // The URL passes the original pdf resource url, that will be requested - // by the webui page. - // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf - content::NavigationController::LoadURLParams params( - GURL(base::StringPrintf( - "%sindex.html?%s=%s", - kPdfViewerUIOrigin, - kPdfPluginSrc, - net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); - web_contents->GetController().LoadURLWithParams(params); + // The URL passes the original pdf resource url, that will be requested + // by the webui page. + // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf + content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( + "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, + net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); + params.frame_tree_node_id = frame_tree_node_id; + web_contents->GetController().LoadURLWithParams(params); } } // namespace @@ -134,22 +134,31 @@ AtomResourceDispatcherHostDelegate::CreateClientCertStore( } bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( - net::URLRequest* request, - const base::FilePath& plugin_path, - const std::string& mime_type, - GURL* origin, - std::string* payload) { - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - if (mime_type == "application/pdf" && info->IsMainFrame()) { - *origin = GURL(kPdfViewerUIOrigin); - content::BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&OnPdfResourceIntercepted, request->url(), - info->GetWebContentsGetterForRequest())); - return true; - } - return false; + net::URLRequest* request, + const base::FilePath& plugin_path, + const std::string& mime_type, + GURL* origin, + std::string* payload) { + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + + int render_process_host_id; + int render_frame_id; + info->GetAssociatedRenderFrame(&render_process_host_id, &render_frame_id); + content::RenderFrameHost* rfh = + content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); + + int frame_tree_node_id = rfh->GetFrameTreeNodeId(); + + if (mime_type == "application/pdf") { + *origin = GURL(kPdfViewerUIOrigin); + content::BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&OnPdfResourceIntercepted, request->url(), + frame_tree_node_id, info->GetWebContentsGetterForRequest())); + return true; + } + return false; } } // namespace atom From 5030db000aedf28c1d39c338892fe2a661d10008 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Ali Date: Sat, 14 Oct 2017 11:09:05 +0200 Subject: [PATCH 02/13] Applying changes requested by @deepak1556 after the review: - Move RenderFrameHost methods in the UI thread - Check GetAssociatedRenderFrame return value --- .../atom_resource_dispatcher_host_delegate.cc | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 4094b240dca7..d017e832793d 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -67,7 +67,8 @@ void HandleExternalProtocolInUI( void OnPdfResourceIntercepted( const GURL& original_url, - int frame_tree_node_id, + int render_process_host_id, + int render_frame_id, const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter) { content::WebContents* web_contents = web_contents_getter.Run(); @@ -91,7 +92,15 @@ void OnPdfResourceIntercepted( content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); - params.frame_tree_node_id = frame_tree_node_id; + + content::RenderFrameHost* frame_host = + content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); + if (!frame_host) + { + return; + } + + params.frame_tree_node_id = frame_host->GetFrameTreeNodeId(); web_contents->GetController().LoadURLWithParams(params); } @@ -144,18 +153,17 @@ bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( int render_process_host_id; int render_frame_id; - info->GetAssociatedRenderFrame(&render_process_host_id, &render_frame_id); - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); - - int frame_tree_node_id = rfh->GetFrameTreeNodeId(); - + if (!info->GetAssociatedRenderFrame(&render_process_host_id, &render_frame_id)) + { + return false; + } + if (mime_type == "application/pdf") { *origin = GURL(kPdfViewerUIOrigin); content::BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&OnPdfResourceIntercepted, request->url(), - frame_tree_node_id, info->GetWebContentsGetterForRequest())); + render_process_host_id, render_frame_id, info->GetWebContentsGetterForRequest())); return true; } return false; From 8763e8ee3577831245565cfa2676d0e93d1d9e5b Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Ali Date: Sat, 14 Oct 2017 11:17:52 +0200 Subject: [PATCH 03/13] Fixing coding style --- .../atom_resource_dispatcher_host_delegate.cc | 341 +++++++++--------- 1 file changed, 169 insertions(+), 172 deletions(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index d017e832793d..c61434117c4b 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -1,172 +1,169 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_resource_dispatcher_host_delegate.h" - -#include "atom/browser/atom_browser_context.h" -#include "atom/browser/login_handler.h" -#include "atom/browser/web_contents_permission_helper.h" -#include "atom/browser/web_contents_preferences.h" -#include "atom/common/atom_constants.h" -#include "atom/common/platform_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/stream_info.h" -#include "content/public/browser/render_frame_host.h" -#include "net/base/escape.h" -#include "net/ssl/client_cert_store.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" - -#if defined(USE_NSS_CERTS) -#include "net/ssl/client_cert_store_nss.h" -#elif defined(OS_WIN) -#include "net/ssl/client_cert_store_win.h" -#elif defined(OS_MACOSX) -#include "net/ssl/client_cert_store_mac.h" -#endif - -using content::BrowserThread; - -namespace atom { - -namespace { - -void OnOpenExternal(const GURL& escaped_url, - bool allowed) { - if (allowed) - platform_util::OpenExternal( -#if defined(OS_WIN) - base::UTF8ToUTF16(escaped_url.spec()), -#else - escaped_url, -#endif - true); -} - -void HandleExternalProtocolInUI( - const GURL& url, - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - bool has_user_gesture) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - auto permission_helper = - WebContentsPermissionHelper::FromWebContents(web_contents); - if (!permission_helper) - return; - - GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); - auto callback = base::Bind(&OnOpenExternal, escaped_url); - permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); -} - -void OnPdfResourceIntercepted( - const GURL& original_url, - int render_process_host_id, - int render_frame_id, - const content::ResourceRequestInfo::WebContentsGetter& - web_contents_getter) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { - auto browser_context = web_contents->GetBrowserContext(); - auto download_manager = - content::BrowserContext::GetDownloadManager(browser_context); - - download_manager->DownloadUrl( - content::DownloadUrlParameters::CreateForWebContentsMainFrame( - web_contents, original_url)); - return; - } - - // The URL passes the original pdf resource url, that will be requested - // by the webui page. - // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf - content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( - "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, - net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); - - content::RenderFrameHost* frame_host = - content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); - if (!frame_host) - { - return; - } - - params.frame_tree_node_id = frame_host->GetFrameTreeNodeId(); - web_contents->GetController().LoadURLWithParams(params); -} - -} // namespace - -AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() { -} - -bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - content::ResourceRequestInfo* info) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&HandleExternalProtocolInUI, - url, - info->GetWebContentsGetterForRequest(), - info->HasUserGesture())); - return true; -} - -content::ResourceDispatcherHostLoginDelegate* -AtomResourceDispatcherHostDelegate::CreateLoginDelegate( - net::AuthChallengeInfo* auth_info, - net::URLRequest* request) { - return new LoginHandler(auth_info, request); -} - -std::unique_ptr -AtomResourceDispatcherHostDelegate::CreateClientCertStore( - content::ResourceContext* resource_context) { - #if defined(USE_NSS_CERTS) - return std::unique_ptr(new net::ClientCertStoreNSS( - net::ClientCertStoreNSS::PasswordDelegateFactory())); - #elif defined(OS_WIN) - return std::unique_ptr(new net::ClientCertStoreWin()); - #elif defined(OS_MACOSX) - return std::unique_ptr(new net::ClientCertStoreMac()); - #elif defined(USE_OPENSSL) - return std::unique_ptr(); - #endif -} - -bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( - net::URLRequest* request, - const base::FilePath& plugin_path, - const std::string& mime_type, - GURL* origin, - std::string* payload) { - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - - int render_process_host_id; - int render_frame_id; - if (!info->GetAssociatedRenderFrame(&render_process_host_id, &render_frame_id)) - { - return false; - } - - if (mime_type == "application/pdf") { - *origin = GURL(kPdfViewerUIOrigin); - content::BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&OnPdfResourceIntercepted, request->url(), - render_process_host_id, render_frame_id, info->GetWebContentsGetterForRequest())); - return true; - } - return false; -} - -} // namespace atom +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_resource_dispatcher_host_delegate.h" + +#include "atom/browser/atom_browser_context.h" +#include "atom/browser/login_handler.h" +#include "atom/browser/web_contents_permission_helper.h" +#include "atom/browser/web_contents_preferences.h" +#include "atom/common/atom_constants.h" +#include "atom/common/platform_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/stream_info.h" +#include "net/base/escape.h" +#include "net/ssl/client_cert_store.h" +#include "net/url_request/url_request.h" +#include "url/gurl.h" + +#if defined(USE_NSS_CERTS) +#include "net/ssl/client_cert_store_nss.h" +#elif defined(OS_WIN) +#include "net/ssl/client_cert_store_win.h" +#elif defined(OS_MACOSX) +#include "net/ssl/client_cert_store_mac.h" +#endif + +using content::BrowserThread; + +namespace atom { + +namespace { + +void OnOpenExternal(const GURL& escaped_url, bool allowed) { + if (allowed) + platform_util::OpenExternal( +#if defined(OS_WIN) + base::UTF8ToUTF16(escaped_url.spec()), +#else + escaped_url, +#endif + true); +} + +void HandleExternalProtocolInUI( + const GURL& url, + const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, + bool has_user_gesture) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; + + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(web_contents); + if (!permission_helper) + return; + + GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); + auto callback = base::Bind(&OnOpenExternal, escaped_url); + permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); +} + +void OnPdfResourceIntercepted( + const GURL& original_url, + int render_process_host_id, + int render_frame_id, + const content::ResourceRequestInfo::WebContentsGetter& + web_contents_getter) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; + + if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { + auto browser_context = web_contents->GetBrowserContext(); + auto download_manager = + content::BrowserContext::GetDownloadManager(browser_context); + + download_manager->DownloadUrl( + content::DownloadUrlParameters::CreateForWebContentsMainFrame( + web_contents, original_url)); + return; + } + + // The URL passes the original pdf resource url, that will be requested + // by the webui page. + // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf + content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( + "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, + net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); + + content::RenderFrameHost* frame_host = + content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); + if (!frame_host) { + return; + } + + params.frame_tree_node_id = frame_host->GetFrameTreeNodeId(); + web_contents->GetController().LoadURLWithParams(params); +} + +} // namespace + +AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {} + +bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( + const GURL& url, + content::ResourceRequestInfo* info) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&HandleExternalProtocolInUI, url, + info->GetWebContentsGetterForRequest(), + info->HasUserGesture())); + return true; +} + +content::ResourceDispatcherHostLoginDelegate* +AtomResourceDispatcherHostDelegate::CreateLoginDelegate( + net::AuthChallengeInfo* auth_info, + net::URLRequest* request) { + return new LoginHandler(auth_info, request); +} + +std::unique_ptr +AtomResourceDispatcherHostDelegate::CreateClientCertStore( + content::ResourceContext* resource_context) { +#if defined(USE_NSS_CERTS) + return std::unique_ptr(new net::ClientCertStoreNSS( + net::ClientCertStoreNSS::PasswordDelegateFactory())); +#elif defined(OS_WIN) + return std::unique_ptr(new net::ClientCertStoreWin()); +#elif defined(OS_MACOSX) + return std::unique_ptr(new net::ClientCertStoreMac()); +#elif defined(USE_OPENSSL) + return std::unique_ptr(); +#endif +} + +bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( + net::URLRequest* request, + const base::FilePath& plugin_path, + const std::string& mime_type, + GURL* origin, + std::string* payload) { + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + + int render_process_host_id; + int render_frame_id; + if (!info->GetAssociatedRenderFrame(&render_process_host_id, + &render_frame_id)) { + return false; + } + + if (mime_type == "application/pdf") { + *origin = GURL(kPdfViewerUIOrigin); + content::BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&OnPdfResourceIntercepted, request->url(), + render_process_host_id, render_frame_id, + info->GetWebContentsGetterForRequest())); + return true; + } + return false; +} + +} // namespace atom From 05035eb1e3c0935798d4f6ca0c57b401b1ed96d2 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Ali Date: Wed, 18 Oct 2017 17:36:56 +0200 Subject: [PATCH 04/13] Fix linefeeds --- .../atom_resource_dispatcher_host_delegate.cc | 338 +++++++++--------- 1 file changed, 169 insertions(+), 169 deletions(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index c61434117c4b..653d81ee463c 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -1,169 +1,169 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_resource_dispatcher_host_delegate.h" - -#include "atom/browser/atom_browser_context.h" -#include "atom/browser/login_handler.h" -#include "atom/browser/web_contents_permission_helper.h" -#include "atom/browser/web_contents_preferences.h" -#include "atom/common/atom_constants.h" -#include "atom/common/platform_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/stream_info.h" -#include "net/base/escape.h" -#include "net/ssl/client_cert_store.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" - -#if defined(USE_NSS_CERTS) -#include "net/ssl/client_cert_store_nss.h" -#elif defined(OS_WIN) -#include "net/ssl/client_cert_store_win.h" -#elif defined(OS_MACOSX) -#include "net/ssl/client_cert_store_mac.h" -#endif - -using content::BrowserThread; - -namespace atom { - -namespace { - -void OnOpenExternal(const GURL& escaped_url, bool allowed) { - if (allowed) - platform_util::OpenExternal( -#if defined(OS_WIN) - base::UTF8ToUTF16(escaped_url.spec()), -#else - escaped_url, -#endif - true); -} - -void HandleExternalProtocolInUI( - const GURL& url, - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - bool has_user_gesture) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - auto permission_helper = - WebContentsPermissionHelper::FromWebContents(web_contents); - if (!permission_helper) - return; - - GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); - auto callback = base::Bind(&OnOpenExternal, escaped_url); - permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); -} - -void OnPdfResourceIntercepted( - const GURL& original_url, - int render_process_host_id, - int render_frame_id, - const content::ResourceRequestInfo::WebContentsGetter& - web_contents_getter) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { - auto browser_context = web_contents->GetBrowserContext(); - auto download_manager = - content::BrowserContext::GetDownloadManager(browser_context); - - download_manager->DownloadUrl( - content::DownloadUrlParameters::CreateForWebContentsMainFrame( - web_contents, original_url)); - return; - } - - // The URL passes the original pdf resource url, that will be requested - // by the webui page. - // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf - content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( - "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, - net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); - - content::RenderFrameHost* frame_host = - content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); - if (!frame_host) { - return; - } - - params.frame_tree_node_id = frame_host->GetFrameTreeNodeId(); - web_contents->GetController().LoadURLWithParams(params); -} - -} // namespace - -AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {} - -bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - content::ResourceRequestInfo* info) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&HandleExternalProtocolInUI, url, - info->GetWebContentsGetterForRequest(), - info->HasUserGesture())); - return true; -} - -content::ResourceDispatcherHostLoginDelegate* -AtomResourceDispatcherHostDelegate::CreateLoginDelegate( - net::AuthChallengeInfo* auth_info, - net::URLRequest* request) { - return new LoginHandler(auth_info, request); -} - -std::unique_ptr -AtomResourceDispatcherHostDelegate::CreateClientCertStore( - content::ResourceContext* resource_context) { -#if defined(USE_NSS_CERTS) - return std::unique_ptr(new net::ClientCertStoreNSS( - net::ClientCertStoreNSS::PasswordDelegateFactory())); -#elif defined(OS_WIN) - return std::unique_ptr(new net::ClientCertStoreWin()); -#elif defined(OS_MACOSX) - return std::unique_ptr(new net::ClientCertStoreMac()); -#elif defined(USE_OPENSSL) - return std::unique_ptr(); -#endif -} - -bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( - net::URLRequest* request, - const base::FilePath& plugin_path, - const std::string& mime_type, - GURL* origin, - std::string* payload) { - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - - int render_process_host_id; - int render_frame_id; - if (!info->GetAssociatedRenderFrame(&render_process_host_id, - &render_frame_id)) { - return false; - } - - if (mime_type == "application/pdf") { - *origin = GURL(kPdfViewerUIOrigin); - content::BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&OnPdfResourceIntercepted, request->url(), - render_process_host_id, render_frame_id, - info->GetWebContentsGetterForRequest())); - return true; - } - return false; -} - -} // namespace atom +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_resource_dispatcher_host_delegate.h" + +#include "atom/browser/atom_browser_context.h" +#include "atom/browser/login_handler.h" +#include "atom/browser/web_contents_permission_helper.h" +#include "atom/browser/web_contents_preferences.h" +#include "atom/common/atom_constants.h" +#include "atom/common/platform_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/stream_info.h" +#include "net/base/escape.h" +#include "net/ssl/client_cert_store.h" +#include "net/url_request/url_request.h" +#include "url/gurl.h" + +#if defined(USE_NSS_CERTS) +#include "net/ssl/client_cert_store_nss.h" +#elif defined(OS_WIN) +#include "net/ssl/client_cert_store_win.h" +#elif defined(OS_MACOSX) +#include "net/ssl/client_cert_store_mac.h" +#endif + +using content::BrowserThread; + +namespace atom { + +namespace { + +void OnOpenExternal(const GURL& escaped_url, bool allowed) { + if (allowed) + platform_util::OpenExternal( +#if defined(OS_WIN) + base::UTF8ToUTF16(escaped_url.spec()), +#else + escaped_url, +#endif + true); +} + +void HandleExternalProtocolInUI( + const GURL& url, + const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, + bool has_user_gesture) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; + + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(web_contents); + if (!permission_helper) + return; + + GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); + auto callback = base::Bind(&OnOpenExternal, escaped_url); + permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); +} + +void OnPdfResourceIntercepted( + const GURL& original_url, + int render_process_host_id, + int render_frame_id, + const content::ResourceRequestInfo::WebContentsGetter& + web_contents_getter) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; + + if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { + auto browser_context = web_contents->GetBrowserContext(); + auto download_manager = + content::BrowserContext::GetDownloadManager(browser_context); + + download_manager->DownloadUrl( + content::DownloadUrlParameters::CreateForWebContentsMainFrame( + web_contents, original_url)); + return; + } + + // The URL passes the original pdf resource url, that will be requested + // by the webui page. + // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf + content::NavigationController::LoadURLParams params(GURL(base::StringPrintf( + "%sindex.html?%s=%s", kPdfViewerUIOrigin, kPdfPluginSrc, + net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); + + content::RenderFrameHost* frame_host = + content::RenderFrameHost::FromID(render_process_host_id, render_frame_id); + if (!frame_host) { + return; + } + + params.frame_tree_node_id = frame_host->GetFrameTreeNodeId(); + web_contents->GetController().LoadURLWithParams(params); +} + +} // namespace + +AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {} + +bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( + const GURL& url, + content::ResourceRequestInfo* info) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&HandleExternalProtocolInUI, url, + info->GetWebContentsGetterForRequest(), + info->HasUserGesture())); + return true; +} + +content::ResourceDispatcherHostLoginDelegate* +AtomResourceDispatcherHostDelegate::CreateLoginDelegate( + net::AuthChallengeInfo* auth_info, + net::URLRequest* request) { + return new LoginHandler(auth_info, request); +} + +std::unique_ptr +AtomResourceDispatcherHostDelegate::CreateClientCertStore( + content::ResourceContext* resource_context) { +#if defined(USE_NSS_CERTS) + return std::unique_ptr(new net::ClientCertStoreNSS( + net::ClientCertStoreNSS::PasswordDelegateFactory())); +#elif defined(OS_WIN) + return std::unique_ptr(new net::ClientCertStoreWin()); +#elif defined(OS_MACOSX) + return std::unique_ptr(new net::ClientCertStoreMac()); +#elif defined(USE_OPENSSL) + return std::unique_ptr(); +#endif +} + +bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( + net::URLRequest* request, + const base::FilePath& plugin_path, + const std::string& mime_type, + GURL* origin, + std::string* payload) { + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + + int render_process_host_id; + int render_frame_id; + if (!info->GetAssociatedRenderFrame(&render_process_host_id, + &render_frame_id)) { + return false; + } + + if (mime_type == "application/pdf") { + *origin = GURL(kPdfViewerUIOrigin); + content::BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&OnPdfResourceIntercepted, request->url(), + render_process_host_id, render_frame_id, + info->GetWebContentsGetterForRequest())); + return true; + } + return false; +} + +} // namespace atom From 44f91e12e1179024a5d2a465b1a0413c55b04f72 Mon Sep 17 00:00:00 2001 From: Ahmed Mohamed Ali Date: Thu, 19 Oct 2017 16:15:02 +0200 Subject: [PATCH 05/13] Add tests for fix described in #10793 --- spec/chromium-spec.js | 52 ++++++++++++++++--- .../preload-pdf-loaded-in-nested-subframe.js | 16 ++++++ .../module/preload-pdf-loaded-in-subframe.js | 11 ++++ spec/fixtures/pages/pdf-in-iframe.html | 8 +++ spec/fixtures/pages/pdf-in-nested-iframe.html | 7 +++ 5 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 spec/fixtures/module/preload-pdf-loaded-in-nested-subframe.js create mode 100644 spec/fixtures/module/preload-pdf-loaded-in-subframe.js create mode 100644 spec/fixtures/pages/pdf-in-iframe.html create mode 100644 spec/fixtures/pages/pdf-in-nested-iframe.html diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 2f9f2b2795ad..bb4027853c3f 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -991,19 +991,47 @@ describe('chromium feature', function () { protocol: 'file', slashes: true }) + + + - function createBrowserWindow ({plugins}) { + function createBrowserWindow ({plugins,preload}) { w = new BrowserWindow({ show: false, webPreferences: { - preload: path.join(fixtures, 'module', 'preload-pdf-loaded.js'), + preload: path.join(fixtures, 'module', preload), plugins: plugins } }) } - + + + + function testPDFIsLoadedInSubFrame(page,preloadFile,done) { + const pagePath = url.format({ + pathname: path.join(fixtures, 'pages',page ).replace(/\\/g, '/'), + protocol: 'file', + slashes: true + }) + + createBrowserWindow({plugins: true,preload:preloadFile}) + ipcMain.once('pdf-loaded', function (event, state) { + assert.equal(state, 'success') + done() + }) + w.webContents.on('page-title-updated', function () { + const parsedURL = url.parse(w.webContents.getURL(), true) + assert.equal(parsedURL.protocol, 'chrome:') + assert.equal(parsedURL.hostname, 'pdf-viewer') + assert.equal(parsedURL.query.src, pagePath) + assert.equal(w.webContents.getTitle(), 'cat.pdf') + }) + w.webContents.loadURL(pagePath) + } + + it('opens when loading a pdf resource as top level navigation', function (done) { - createBrowserWindow({plugins: true}) + createBrowserWindow({plugins: true,preload:'preload-pdf-loaded.js'}) ipcMain.once('pdf-loaded', function (event, state) { assert.equal(state, 'success') done() @@ -1019,7 +1047,7 @@ describe('chromium feature', function () { }) it('opens a pdf link given params, the query string should be escaped', function (done) { - createBrowserWindow({plugins: true}) + createBrowserWindow({plugins: true,preload:'preload-pdf-loaded.js'}) ipcMain.once('pdf-loaded', function (event, state) { assert.equal(state, 'success') done() @@ -1037,7 +1065,7 @@ describe('chromium feature', function () { }) it('should download a pdf when plugins are disabled', function (done) { - createBrowserWindow({plugins: false}) + createBrowserWindow({plugins: false,preload:'preload-pdf-loaded.js'}) ipcRenderer.sendSync('set-download-option', false, false) ipcRenderer.once('download-done', function (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assert.equal(state, 'completed') @@ -1050,7 +1078,7 @@ describe('chromium feature', function () { }) it('should not open when pdf is requested as sub resource', function (done) { - createBrowserWindow({plugins: true}) + createBrowserWindow({plugins: true,preload:'preload-pdf-loaded.js'}) webFrame.registerURLSchemeAsPrivileged('file', { secure: false, bypassCSP: false, @@ -1065,6 +1093,16 @@ describe('chromium feature', function () { done(e) }) }) + + it('opens when loading a pdf resource in a iframe', function (done) { + testPDFIsLoadedInSubFrame('pdf-in-iframe.html','preload-pdf-loaded-in-subframe.js',done) + }) + + it('opens when loading a pdf resource in a nested iframe', function (done) { + testPDFIsLoadedInSubFrame('pdf-in-nested-iframe.html','preload-pdf-loaded-in-nested-subframe.js',done) + }) + + }) describe('window.alert(message, title)', function () { diff --git a/spec/fixtures/module/preload-pdf-loaded-in-nested-subframe.js b/spec/fixtures/module/preload-pdf-loaded-in-nested-subframe.js new file mode 100644 index 000000000000..cba1d012aeac --- /dev/null +++ b/spec/fixtures/module/preload-pdf-loaded-in-nested-subframe.js @@ -0,0 +1,16 @@ +const {ipcRenderer} = require('electron') + +document.addEventListener("DOMContentLoaded", function(event) { + var outerFrame = document.getElementById('outer-frame'); + if (outerFrame) { + outerFrame.onload = function() { + var pdframe = outerFrame.contentWindow.document.getElementById('pdf-frame'); + if (pdframe) { + pdframe.contentWindow.addEventListener('pdf-loaded', function (event) { + ipcRenderer.send('pdf-loaded', event.detail) + }); + } + } + } +}); + diff --git a/spec/fixtures/module/preload-pdf-loaded-in-subframe.js b/spec/fixtures/module/preload-pdf-loaded-in-subframe.js new file mode 100644 index 000000000000..aa027eaf66b7 --- /dev/null +++ b/spec/fixtures/module/preload-pdf-loaded-in-subframe.js @@ -0,0 +1,11 @@ +const {ipcRenderer} = require('electron') + +document.addEventListener("DOMContentLoaded", function(event) { + var subframe = document.getElementById('pdf-frame'); + if (subframe) { + subframe.contentWindow.addEventListener('pdf-loaded', function (event) { + ipcRenderer.send('pdf-loaded', event.detail) + }); + } +}); + diff --git a/spec/fixtures/pages/pdf-in-iframe.html b/spec/fixtures/pages/pdf-in-iframe.html new file mode 100644 index 000000000000..9371ceed18cb --- /dev/null +++ b/spec/fixtures/pages/pdf-in-iframe.html @@ -0,0 +1,8 @@ + + +