• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/printing/print_view_manager.h"
6 
7 #include <map>
8 
9 #include "base/bind.h"
10 #include "base/lazy_instance.h"
11 #include "base/metrics/histogram.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/printing/print_job_manager.h"
14 #include "chrome/browser/printing/print_preview_dialog_controller.h"
15 #include "chrome/browser/printing/print_view_manager_observer.h"
16 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
17 #include "chrome/common/print_messages.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_contents.h"
20 #include "printing/print_destination_interface.h"
21 
22 using content::BrowserThread;
23 
24 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager);
25 
26 namespace {
27 
28 // Keeps track of pending scripted print preview closures.
29 // No locking, only access on the UI thread.
30 typedef std::map<content::RenderProcessHost*, base::Closure>
31     ScriptedPrintPreviewClosureMap;
32 static base::LazyInstance<ScriptedPrintPreviewClosureMap>
33     g_scripted_print_preview_closure_map = LAZY_INSTANCE_INITIALIZER;
34 
35 }  // namespace
36 
37 namespace printing {
38 
PrintViewManager(content::WebContents * web_contents)39 PrintViewManager::PrintViewManager(content::WebContents* web_contents)
40     : PrintViewManagerBase(web_contents),
41       observer_(NULL),
42       print_preview_state_(NOT_PREVIEWING),
43       scripted_print_preview_rph_(NULL) {
44 }
45 
~PrintViewManager()46 PrintViewManager::~PrintViewManager() {
47   DCHECK_EQ(NOT_PREVIEWING, print_preview_state_);
48 }
49 
PrintForSystemDialogNow()50 bool PrintViewManager::PrintForSystemDialogNow() {
51   return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id()));
52 }
53 
AdvancedPrintNow()54 bool PrintViewManager::AdvancedPrintNow() {
55   PrintPreviewDialogController* dialog_controller =
56       PrintPreviewDialogController::GetInstance();
57   if (!dialog_controller)
58     return false;
59   content::WebContents* print_preview_dialog =
60       dialog_controller->GetPrintPreviewForContents(web_contents());
61   if (print_preview_dialog) {
62     if (!print_preview_dialog->GetWebUI())
63       return false;
64     PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
65         print_preview_dialog->GetWebUI()->GetController());
66     print_preview_ui->OnShowSystemDialog();
67     return true;
68   } else {
69     return PrintNow();
70   }
71 }
72 
PrintToDestination()73 bool PrintViewManager::PrintToDestination() {
74   // TODO(mad): Remove this once we can send user metrics from the metro driver.
75   // crbug.com/142330
76   UMA_HISTOGRAM_ENUMERATION("Metro.Print", 0, 2);
77   // TODO(mad): Use a passed in destination interface instead.
78   g_browser_process->print_job_manager()->queue()->SetDestination(
79       printing::CreatePrintDestination());
80   return PrintNowInternal(new PrintMsg_PrintPages(routing_id()));
81 }
82 
PrintPreviewNow(bool selection_only)83 bool PrintViewManager::PrintPreviewNow(bool selection_only) {
84   // Users can send print commands all they want and it is beyond
85   // PrintViewManager's control. Just ignore the extra commands.
86   // See http://crbug.com/136842 for example.
87   if (print_preview_state_ != NOT_PREVIEWING)
88     return false;
89 
90   if (!PrintNowInternal(new PrintMsg_InitiatePrintPreview(routing_id(),
91                                                           selection_only))) {
92     return false;
93   }
94 
95   print_preview_state_ = USER_INITIATED_PREVIEW;
96   return true;
97 }
98 
PrintPreviewForWebNode()99 void PrintViewManager::PrintPreviewForWebNode() {
100   if (print_preview_state_ != NOT_PREVIEWING)
101     return;
102   print_preview_state_ = USER_INITIATED_PREVIEW;
103 }
104 
PrintPreviewDone()105 void PrintViewManager::PrintPreviewDone() {
106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107   DCHECK_NE(NOT_PREVIEWING, print_preview_state_);
108 
109   if (print_preview_state_ == SCRIPTED_PREVIEW) {
110     ScriptedPrintPreviewClosureMap& map =
111         g_scripted_print_preview_closure_map.Get();
112     ScriptedPrintPreviewClosureMap::iterator it =
113         map.find(scripted_print_preview_rph_);
114     CHECK(it != map.end());
115     it->second.Run();
116     map.erase(scripted_print_preview_rph_);
117     scripted_print_preview_rph_ = NULL;
118   }
119   print_preview_state_ = NOT_PREVIEWING;
120 }
121 
set_observer(PrintViewManagerObserver * observer)122 void PrintViewManager::set_observer(PrintViewManagerObserver* observer) {
123   DCHECK(!observer || !observer_);
124   observer_ = observer;
125 }
126 
RenderProcessGone(base::TerminationStatus status)127 void PrintViewManager::RenderProcessGone(base::TerminationStatus status) {
128   print_preview_state_ = NOT_PREVIEWING;
129   PrintViewManagerBase::RenderProcessGone(status);
130 }
131 
OnDidShowPrintDialog()132 void PrintViewManager::OnDidShowPrintDialog() {
133   if (observer_)
134     observer_->OnPrintDialogShown();
135 }
136 
OnSetupScriptedPrintPreview(IPC::Message * reply_msg)137 void PrintViewManager::OnSetupScriptedPrintPreview(IPC::Message* reply_msg) {
138   BrowserThread::CurrentlyOn(BrowserThread::UI);
139   ScriptedPrintPreviewClosureMap& map =
140       g_scripted_print_preview_closure_map.Get();
141   content::RenderProcessHost* rph = web_contents()->GetRenderProcessHost();
142 
143   // This should always be 0 once we get modal window.print().
144   if (map.count(rph) != 0) {
145     // Renderer already handling window.print() in another View.
146     Send(reply_msg);
147     return;
148   }
149   if (print_preview_state_ != NOT_PREVIEWING) {
150     // If a user initiated print dialog is already open, ignore the scripted
151     // print message.
152     DCHECK_EQ(USER_INITIATED_PREVIEW, print_preview_state_);
153     Send(reply_msg);
154     return;
155   }
156 
157   PrintPreviewDialogController* dialog_controller =
158       PrintPreviewDialogController::GetInstance();
159   if (!dialog_controller) {
160     Send(reply_msg);
161     return;
162   }
163 
164   print_preview_state_ = SCRIPTED_PREVIEW;
165   base::Closure callback =
166       base::Bind(&PrintViewManager::OnScriptedPrintPreviewReply,
167                  base::Unretained(this),
168                  reply_msg);
169   map[rph] = callback;
170   scripted_print_preview_rph_ = rph;
171 }
172 
OnShowScriptedPrintPreview(bool source_is_modifiable)173 void PrintViewManager::OnShowScriptedPrintPreview(bool source_is_modifiable) {
174   PrintPreviewDialogController* dialog_controller =
175       PrintPreviewDialogController::GetInstance();
176   if (!dialog_controller) {
177     PrintPreviewDone();
178     return;
179   }
180   dialog_controller->PrintPreview(web_contents());
181   PrintHostMsg_RequestPrintPreview_Params params;
182   params.is_modifiable = source_is_modifiable;
183   PrintPreviewUI::SetInitialParams(
184       dialog_controller->GetPrintPreviewForContents(web_contents()), params);
185 }
186 
OnScriptedPrintPreviewReply(IPC::Message * reply_msg)187 void PrintViewManager::OnScriptedPrintPreviewReply(IPC::Message* reply_msg) {
188   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
189   Send(reply_msg);
190 }
191 
OnMessageReceived(const IPC::Message & message)192 bool PrintViewManager::OnMessageReceived(const IPC::Message& message) {
193   bool handled = true;
194   IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message)
195     IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog)
196     IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_SetupScriptedPrintPreview,
197                                     OnSetupScriptedPrintPreview)
198     IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview,
199                         OnShowScriptedPrintPreview)
200     IPC_MESSAGE_UNHANDLED(handled = false)
201   IPC_END_MESSAGE_MAP()
202 
203   return handled ? true : PrintViewManagerBase::OnMessageReceived(message);
204 }
205 
206 }  // namespace printing
207