Fix printing from iframes (fixes issue #2753)

This commit is contained in:
Marshall Greenblatt 2019-10-15 13:52:26 +02:00
parent 066762217f
commit b560f04046
2 changed files with 48 additions and 19 deletions

View File

@ -154,14 +154,19 @@ bool IsStandaloneExtensionProcess() {
// Placeholder object for guest views. // Placeholder object for guest views.
class CefGuestView : public content::RenderViewObserver { class CefGuestView : public content::RenderViewObserver {
public: public:
explicit CefGuestView(content::RenderView* render_view) CefGuestView(content::RenderView* render_view, bool is_windowless)
: content::RenderViewObserver(render_view) {} : content::RenderViewObserver(render_view),
is_windowless_(is_windowless) {}
bool is_windowless() const { return is_windowless_; }
private: private:
// RenderViewObserver methods. // RenderViewObserver methods.
void OnDestruct() override { void OnDestruct() override {
CefContentRendererClient::Get()->OnGuestViewDestroyed(this); CefContentRendererClient::Get()->OnGuestViewDestroyed(this);
} }
const bool is_windowless_;
}; };
CefContentRendererClient::CefContentRendererClient() CefContentRendererClient::CefContentRendererClient()
@ -226,11 +231,14 @@ void CefContentRendererClient::OnBrowserDestroyed(CefBrowserImpl* browser) {
NOTREACHED(); NOTREACHED();
} }
bool CefContentRendererClient::HasGuestViewForView(content::RenderView* view) { CefGuestView* CefContentRendererClient::GetGuestViewForView(
CEF_REQUIRE_RT_RETURN(false); content::RenderView* view) {
CEF_REQUIRE_RT_RETURN(nullptr);
GuestViewMap::const_iterator it = guest_views_.find(view); GuestViewMap::const_iterator it = guest_views_.find(view);
return it != guest_views_.end(); if (it != guest_views_.end())
return it->second.get();
return nullptr;
} }
void CefContentRendererClient::OnGuestViewDestroyed(CefGuestView* guest_view) { void CefContentRendererClient::OnGuestViewDestroyed(CefGuestView* guest_view) {
@ -481,20 +489,29 @@ void CefContentRendererClient::RenderFrameCreated(
new SpellCheckProvider(render_frame, spellcheck_.get(), this); new SpellCheckProvider(render_frame, spellcheck_.get(), this);
} }
auto browser = base::Optional<bool> is_windowless;
MaybeCreateBrowser(render_frame->GetRenderView(), render_frame);
auto browser = MaybeCreateBrowser(render_frame->GetRenderView(), render_frame,
&is_windowless);
if (browser) { if (browser) {
// Attach the frame to the observer for message routing purposes. // Attach the frame to the observer for message routing purposes.
render_frame_observer->AttachFrame( render_frame_observer->AttachFrame(
browser->GetWebFrameImpl(render_frame->GetWebFrame()).get()); browser->GetWebFrameImpl(render_frame->GetWebFrame()).get());
} }
if (is_windowless.has_value()) {
new printing::PrintRenderFrameHelper(
render_frame,
base::WrapUnique(
new extensions::CefPrintRenderFrameHelperDelegate(*is_windowless)));
}
} }
void CefContentRendererClient::RenderViewCreated( void CefContentRendererClient::RenderViewCreated(
content::RenderView* render_view) { content::RenderView* render_view) {
new CefPrerendererClient(render_view); new CefPrerendererClient(render_view);
MaybeCreateBrowser(render_view, render_view->GetMainRenderFrame()); MaybeCreateBrowser(render_view, render_view->GetMainRenderFrame(), nullptr);
} }
bool CefContentRendererClient::IsPluginHandledExternally( bool CefContentRendererClient::IsPluginHandledExternally(
@ -712,18 +729,28 @@ void CefContentRendererClient::WillDestroyCurrentMessageLoop() {
CefRefPtr<CefBrowserImpl> CefContentRendererClient::MaybeCreateBrowser( CefRefPtr<CefBrowserImpl> CefContentRendererClient::MaybeCreateBrowser(
content::RenderView* render_view, content::RenderView* render_view,
content::RenderFrame* render_frame) { content::RenderFrame* render_frame,
base::Optional<bool>* is_windowless) {
if (!render_view || !render_frame) if (!render_view || !render_frame)
return nullptr; return nullptr;
// Don't create another browser or guest view object if one already exists for // Don't create another browser or guest view object if one already exists for
// the view. // the view.
auto browser = GetBrowserForView(render_view); auto browser = GetBrowserForView(render_view);
if (browser) if (browser) {
if (is_windowless) {
*is_windowless = browser->is_windowless();
}
return browser; return browser;
}
if (HasGuestViewForView(render_view)) auto guest_view = GetGuestViewForView(render_view);
if (guest_view) {
if (is_windowless) {
*is_windowless = guest_view->is_windowless();
}
return nullptr; return nullptr;
}
const int render_frame_routing_id = render_frame->GetRoutingID(); const int render_frame_routing_id = render_frame->GetRoutingID();
@ -733,10 +760,9 @@ CefRefPtr<CefBrowserImpl> CefContentRendererClient::MaybeCreateBrowser(
content::RenderThread::Get()->Send(new CefProcessHostMsg_GetNewBrowserInfo( content::RenderThread::Get()->Send(new CefProcessHostMsg_GetNewBrowserInfo(
render_frame_routing_id, &params)); render_frame_routing_id, &params));
new printing::PrintRenderFrameHelper( if (is_windowless) {
render_frame, *is_windowless = params.is_windowless;
base::WrapUnique(new extensions::CefPrintRenderFrameHelperDelegate( }
params.is_windowless)));
if (params.browser_id == 0) { if (params.browser_id == 0) {
// The popup may have been canceled during creation. // The popup may have been canceled during creation.
@ -746,7 +772,8 @@ CefRefPtr<CefBrowserImpl> CefContentRendererClient::MaybeCreateBrowser(
if (params.is_guest_view) { if (params.is_guest_view) {
// Don't create a CefBrowser for guest views. // Don't create a CefBrowser for guest views.
guest_views_.insert(std::make_pair( guest_views_.insert(std::make_pair(
render_view, std::make_unique<CefGuestView>(render_view))); render_view,
std::make_unique<CefGuestView>(render_view, params.is_windowless)));
return nullptr; return nullptr;
} }

View File

@ -17,6 +17,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/message_loop/message_loop_current.h" #include "base/message_loop/message_loop_current.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "chrome/common/plugin.mojom.h" #include "chrome/common/plugin.mojom.h"
#include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/content_renderer_client.h"
@ -69,8 +70,8 @@ class CefContentRendererClient
// Called from CefBrowserImpl::OnDestruct(). // Called from CefBrowserImpl::OnDestruct().
void OnBrowserDestroyed(CefBrowserImpl* browser); void OnBrowserDestroyed(CefBrowserImpl* browser);
// Returns true if a guest view associated with the specified RenderView. // Returns the guest view associated with the specified RenderView if any.
bool HasGuestViewForView(content::RenderView* view); CefGuestView* GetGuestViewForView(content::RenderView* view);
// Called from CefGuestView::OnDestruct(). // Called from CefGuestView::OnDestruct().
void OnGuestViewDestroyed(CefGuestView* guest_view); void OnGuestViewDestroyed(CefGuestView* guest_view);
@ -154,7 +155,8 @@ class CefContentRendererClient
// nullptr for guest views. // nullptr for guest views.
CefRefPtr<CefBrowserImpl> MaybeCreateBrowser( CefRefPtr<CefBrowserImpl> MaybeCreateBrowser(
content::RenderView* render_view, content::RenderView* render_view,
content::RenderFrame* render_frame); content::RenderFrame* render_frame,
base::Optional<bool>* is_windowless);
// Perform cleanup work for single-process mode. // Perform cleanup work for single-process mode.
void RunSingleProcessCleanupOnUIThread(); void RunSingleProcessCleanupOnUIThread();