1 // Copyright (c) 2012 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.
5 #include "chrome/browser/printing/print_view_manager.h"
10 #include "base/lazy_instance.h"
11 #include "base/metrics/histogram.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
14 #include "chrome/browser/printing/print_job_manager.h"
15 #include "chrome/browser/printing/print_preview_dialog_controller.h"
16 #include "chrome/browser/printing/print_view_manager_observer.h"
17 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
18 #include "chrome/common/chrome_content_client.h"
19 #include "components/printing/common/print_messages.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/plugin_service.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/webplugininfo.h"
27 using content::BrowserThread
;
29 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager
);
33 // Keeps track of pending scripted print preview closures.
34 // No locking, only access on the UI thread.
35 typedef std::map
<content::RenderProcessHost
*, base::Closure
>
36 ScriptedPrintPreviewClosureMap
;
37 static base::LazyInstance
<ScriptedPrintPreviewClosureMap
>
38 g_scripted_print_preview_closure_map
= LAZY_INSTANCE_INITIALIZER
;
40 void EnableInternalPDFPluginForContents(int render_process_id
,
41 int render_frame_id
) {
42 // Always enable the internal PDF plugin for the print preview page.
43 base::FilePath pdf_plugin_path
= base::FilePath::FromUTF8Unsafe(
44 ChromeContentClient::kPDFPluginPath
);
46 content::WebPluginInfo pdf_plugin
;
47 if (!content::PluginService::GetInstance()->GetPluginInfoByPath(
48 pdf_plugin_path
, &pdf_plugin
)) {
52 ChromePluginServiceFilter::GetInstance()->OverridePluginForFrame(
53 render_process_id
, render_frame_id
, GURL(), pdf_plugin
);
60 PrintViewManager::PrintViewManager(content::WebContents
* web_contents
)
61 : PrintViewManagerBase(web_contents
),
63 print_preview_state_(NOT_PREVIEWING
),
64 scripted_print_preview_rph_(NULL
) {
65 if (PrintPreviewDialogController::IsPrintPreviewDialog(web_contents
)) {
66 EnableInternalPDFPluginForContents(
67 web_contents
->GetRenderProcessHost()->GetID(),
68 web_contents
->GetMainFrame()->GetRoutingID());
72 PrintViewManager::~PrintViewManager() {
73 DCHECK_EQ(NOT_PREVIEWING
, print_preview_state_
);
76 #if defined(ENABLE_BASIC_PRINTING)
77 bool PrintViewManager::PrintForSystemDialogNow() {
78 return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id()));
81 bool PrintViewManager::BasicPrint() {
82 PrintPreviewDialogController
* dialog_controller
=
83 PrintPreviewDialogController::GetInstance();
84 if (!dialog_controller
)
86 content::WebContents
* print_preview_dialog
=
87 dialog_controller
->GetPrintPreviewForContents(web_contents());
88 if (print_preview_dialog
) {
89 if (!print_preview_dialog
->GetWebUI())
91 PrintPreviewUI
* print_preview_ui
= static_cast<PrintPreviewUI
*>(
92 print_preview_dialog
->GetWebUI()->GetController());
93 print_preview_ui
->OnShowSystemDialog();
99 #endif // ENABLE_BASIC_PRINTING
101 bool PrintViewManager::PrintPreviewNow(bool selection_only
) {
102 // Users can send print commands all they want and it is beyond
103 // PrintViewManager's control. Just ignore the extra commands.
104 // See http://crbug.com/136842 for example.
105 if (print_preview_state_
!= NOT_PREVIEWING
)
108 if (!PrintNowInternal(new PrintMsg_InitiatePrintPreview(routing_id(),
113 print_preview_state_
= USER_INITIATED_PREVIEW
;
117 void PrintViewManager::PrintPreviewForWebNode() {
118 if (print_preview_state_
!= NOT_PREVIEWING
)
120 print_preview_state_
= USER_INITIATED_PREVIEW
;
123 void PrintViewManager::PrintPreviewDone() {
124 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
125 DCHECK_NE(NOT_PREVIEWING
, print_preview_state_
);
127 if (print_preview_state_
== SCRIPTED_PREVIEW
) {
128 ScriptedPrintPreviewClosureMap
& map
=
129 g_scripted_print_preview_closure_map
.Get();
130 ScriptedPrintPreviewClosureMap::iterator it
=
131 map
.find(scripted_print_preview_rph_
);
132 CHECK(it
!= map
.end());
134 map
.erase(scripted_print_preview_rph_
);
135 scripted_print_preview_rph_
= NULL
;
137 print_preview_state_
= NOT_PREVIEWING
;
140 void PrintViewManager::set_observer(PrintViewManagerObserver
* observer
) {
141 DCHECK(!observer
|| !observer_
);
142 observer_
= observer
;
145 void PrintViewManager::RenderFrameCreated(
146 content::RenderFrameHost
* render_frame_host
) {
147 if (PrintPreviewDialogController::IsPrintPreviewDialog(web_contents())) {
148 EnableInternalPDFPluginForContents(render_frame_host
->GetProcess()->GetID(),
149 render_frame_host
->GetRoutingID());
153 void PrintViewManager::RenderProcessGone(base::TerminationStatus status
) {
154 print_preview_state_
= NOT_PREVIEWING
;
155 PrintViewManagerBase::RenderProcessGone(status
);
158 void PrintViewManager::OnDidShowPrintDialog() {
160 observer_
->OnPrintDialogShown();
163 void PrintViewManager::OnSetupScriptedPrintPreview(IPC::Message
* reply_msg
) {
164 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
165 ScriptedPrintPreviewClosureMap
& map
=
166 g_scripted_print_preview_closure_map
.Get();
167 content::RenderProcessHost
* rph
= web_contents()->GetRenderProcessHost();
169 // This should always be 0 once we get modal window.print().
170 if (map
.count(rph
) != 0) {
171 // Renderer already handling window.print() in another View.
175 if (print_preview_state_
!= NOT_PREVIEWING
) {
176 // If a user initiated print dialog is already open, ignore the scripted
178 DCHECK_EQ(USER_INITIATED_PREVIEW
, print_preview_state_
);
183 PrintPreviewDialogController
* dialog_controller
=
184 PrintPreviewDialogController::GetInstance();
185 if (!dialog_controller
) {
190 print_preview_state_
= SCRIPTED_PREVIEW
;
191 base::Closure callback
=
192 base::Bind(&PrintViewManager::OnScriptedPrintPreviewReply
,
193 base::Unretained(this),
196 scripted_print_preview_rph_
= rph
;
199 void PrintViewManager::OnShowScriptedPrintPreview(bool source_is_modifiable
) {
200 PrintPreviewDialogController
* dialog_controller
=
201 PrintPreviewDialogController::GetInstance();
202 if (!dialog_controller
) {
206 dialog_controller
->PrintPreview(web_contents());
207 PrintHostMsg_RequestPrintPreview_Params params
;
208 params
.is_modifiable
= source_is_modifiable
;
209 PrintPreviewUI::SetInitialParams(
210 dialog_controller
->GetPrintPreviewForContents(web_contents()), params
);
213 void PrintViewManager::OnScriptedPrintPreviewReply(IPC::Message
* reply_msg
) {
214 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
218 bool PrintViewManager::OnMessageReceived(const IPC::Message
& message
) {
220 IPC_BEGIN_MESSAGE_MAP(PrintViewManager
, message
)
221 IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog
, OnDidShowPrintDialog
)
222 IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_SetupScriptedPrintPreview
,
223 OnSetupScriptedPrintPreview
)
224 IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview
,
225 OnShowScriptedPrintPreview
)
226 IPC_MESSAGE_UNHANDLED(handled
= false)
227 IPC_END_MESSAGE_MAP()
229 return handled
? true : PrintViewManagerBase::OnMessageReceived(message
);
232 } // namespace printing