1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/printing/browser/print_manager.h"
6
7 #include "base/bind.h"
8 #include "build/build_config.h"
9 #include "components/printing/common/print_messages.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
12
13 namespace printing {
14
15 struct PrintManager::FrameDispatchHelper {
16 PrintManager* manager;
17 content::RenderFrameHost* render_frame_host;
18
Sendprinting::PrintManager::FrameDispatchHelper19 bool Send(IPC::Message* msg) { return render_frame_host->Send(msg); }
20
OnGetDefaultPrintSettingsprinting::PrintManager::FrameDispatchHelper21 void OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
22 manager->OnGetDefaultPrintSettings(render_frame_host, reply_msg);
23 }
24
OnScriptedPrintprinting::PrintManager::FrameDispatchHelper25 void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& scripted_params,
26 IPC::Message* reply_msg) {
27 manager->OnScriptedPrint(render_frame_host, scripted_params, reply_msg);
28 }
29
OnDidPrintDocumentprinting::PrintManager::FrameDispatchHelper30 void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params,
31 IPC::Message* reply_msg) {
32 // If DidPrintDocument message was received then need to transition from
33 // a variable allocated on stack (which has efficient memory management
34 // when dealing with any other incoming message) to a persistent variable
35 // on the heap that can be referenced by the asynchronous processing which
36 // occurs beyond the scope of PrintViewManagerBase::OnMessageReceived().
37 manager->OnDidPrintDocument(
38 render_frame_host, params,
39 std::make_unique<DelayedFrameDispatchHelper>(
40 manager->web_contents(), render_frame_host, reply_msg));
41 }
42 };
43
DelayedFrameDispatchHelper(content::WebContents * contents,content::RenderFrameHost * render_frame_host,IPC::Message * reply_msg)44 PrintManager::DelayedFrameDispatchHelper::DelayedFrameDispatchHelper(
45 content::WebContents* contents,
46 content::RenderFrameHost* render_frame_host,
47 IPC::Message* reply_msg)
48 : content::WebContentsObserver(contents),
49 render_frame_host_(render_frame_host),
50 reply_msg_(reply_msg) {}
51
~DelayedFrameDispatchHelper()52 PrintManager::DelayedFrameDispatchHelper::~DelayedFrameDispatchHelper() {
53 if (reply_msg_) {
54 PrintHostMsg_DidPrintDocument::WriteReplyParams(reply_msg_, false);
55 render_frame_host_->Send(reply_msg_);
56 }
57 }
58
SendCompleted()59 void PrintManager::DelayedFrameDispatchHelper::SendCompleted() {
60 if (!reply_msg_)
61 return;
62
63 PrintHostMsg_DidPrintDocument::WriteReplyParams(reply_msg_, true);
64 render_frame_host_->Send(reply_msg_);
65
66 // This wraps up the one allowed reply for the message.
67 reply_msg_ = nullptr;
68 }
69
RenderFrameDeleted(content::RenderFrameHost * render_frame_host)70 void PrintManager::DelayedFrameDispatchHelper::RenderFrameDeleted(
71 content::RenderFrameHost* render_frame_host) {
72 if (render_frame_host == render_frame_host_)
73 reply_msg_ = nullptr;
74 }
75
PrintManager(content::WebContents * contents)76 PrintManager::PrintManager(content::WebContents* contents)
77 : content::WebContentsObserver(contents) {}
78
79 PrintManager::~PrintManager() = default;
80
OnMessageReceived(const IPC::Message & message,content::RenderFrameHost * render_frame_host)81 bool PrintManager::OnMessageReceived(
82 const IPC::Message& message,
83 content::RenderFrameHost* render_frame_host) {
84 FrameDispatchHelper helper = {this, render_frame_host};
85 bool handled = true;
86 IPC_BEGIN_MESSAGE_MAP(PrintManager, message)
87 IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount,
88 OnDidGetPrintedPagesCount)
89 IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie,
90 OnDidGetDocumentCookie)
91 IPC_MESSAGE_FORWARD_DELAY_REPLY(
92 PrintHostMsg_GetDefaultPrintSettings, &helper,
93 FrameDispatchHelper::OnGetDefaultPrintSettings)
94 IPC_MESSAGE_FORWARD_DELAY_REPLY(PrintHostMsg_ScriptedPrint, &helper,
95 FrameDispatchHelper::OnScriptedPrint)
96 IPC_MESSAGE_FORWARD_DELAY_REPLY(PrintHostMsg_DidPrintDocument, &helper,
97 FrameDispatchHelper::OnDidPrintDocument);
98
99 IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
100 IPC_MESSAGE_UNHANDLED(handled = false)
101 IPC_END_MESSAGE_MAP()
102 return handled;
103 }
104
RenderFrameDeleted(content::RenderFrameHost * render_frame_host)105 void PrintManager::RenderFrameDeleted(
106 content::RenderFrameHost* render_frame_host) {
107 print_render_frames_.erase(render_frame_host);
108 }
109
OnDidGetPrintedPagesCount(int cookie,int number_pages)110 void PrintManager::OnDidGetPrintedPagesCount(int cookie,
111 int number_pages) {
112 DCHECK_GT(cookie, 0);
113 DCHECK_GT(number_pages, 0);
114 number_pages_ = number_pages;
115 }
116
OnDidGetDocumentCookie(int cookie)117 void PrintManager::OnDidGetDocumentCookie(int cookie) {
118 cookie_ = cookie;
119 }
120
OnPrintingFailed(int cookie)121 void PrintManager::OnPrintingFailed(int cookie) {
122 if (cookie != cookie_) {
123 NOTREACHED();
124 return;
125 }
126 #if defined(OS_ANDROID)
127 PdfWritingDone(0);
128 #endif
129 }
130
131 const mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>&
GetPrintRenderFrame(content::RenderFrameHost * rfh)132 PrintManager::GetPrintRenderFrame(content::RenderFrameHost* rfh) {
133 auto it = print_render_frames_.find(rfh);
134 if (it == print_render_frames_.end()) {
135 mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> remote;
136 rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote);
137 it = print_render_frames_.insert(std::make_pair(rfh, std::move(remote))).first;
138 } else if (it->second.is_bound() && !it->second.is_connected()) {
139 // When print preview is closed, the remote is disconnected from the
140 // receiver. Reset and bind the remote before using it again.
141 it->second.reset();
142 rfh->GetRemoteAssociatedInterfaces()->GetInterface(&it->second);
143 }
144
145 return it->second;
146 }
147
PrintingRenderFrameDeleted()148 void PrintManager::PrintingRenderFrameDeleted() {
149 #if defined(OS_ANDROID)
150 PdfWritingDone(0);
151 #endif
152 }
153
154 } // namespace printing
155