| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/printing/print_view_manager.h" |
| |
| #include <map> |
| |
| #include "base/bind.h" |
| #include "base/lazy_instance.h" |
| #include "base/metrics/histogram.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/printing/print_job_manager.h" |
| #include "chrome/browser/printing/print_preview_dialog_controller.h" |
| #include "chrome/browser/printing/print_view_manager_observer.h" |
| #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" |
| #include "chrome/common/print_messages.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/web_contents.h" |
| #include "printing/print_destination_interface.h" |
| |
| using content::BrowserThread; |
| |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager); |
| |
| namespace { |
| |
| // Keeps track of pending scripted print preview closures. |
| // No locking, only access on the UI thread. |
| typedef std::map<content::RenderProcessHost*, base::Closure> |
| ScriptedPrintPreviewClosureMap; |
| static base::LazyInstance<ScriptedPrintPreviewClosureMap> |
| g_scripted_print_preview_closure_map = LAZY_INSTANCE_INITIALIZER; |
| |
| } // namespace |
| |
| namespace printing { |
| |
| PrintViewManager::PrintViewManager(content::WebContents* web_contents) |
| : PrintViewManagerBase(web_contents), |
| observer_(NULL), |
| print_preview_state_(NOT_PREVIEWING), |
| scripted_print_preview_rph_(NULL) { |
| } |
| |
| PrintViewManager::~PrintViewManager() { |
| DCHECK_EQ(NOT_PREVIEWING, print_preview_state_); |
| } |
| |
| bool PrintViewManager::PrintForSystemDialogNow() { |
| return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id())); |
| } |
| |
| bool PrintViewManager::AdvancedPrintNow() { |
| PrintPreviewDialogController* dialog_controller = |
| PrintPreviewDialogController::GetInstance(); |
| if (!dialog_controller) |
| return false; |
| content::WebContents* print_preview_dialog = |
| dialog_controller->GetPrintPreviewForContents(web_contents()); |
| if (print_preview_dialog) { |
| if (!print_preview_dialog->GetWebUI()) |
| return false; |
| PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>( |
| print_preview_dialog->GetWebUI()->GetController()); |
| print_preview_ui->OnShowSystemDialog(); |
| return true; |
| } else { |
| return PrintNow(); |
| } |
| } |
| |
| bool PrintViewManager::PrintToDestination() { |
| // TODO(mad): Remove this once we can send user metrics from the metro driver. |
| // crbug.com/142330 |
| UMA_HISTOGRAM_ENUMERATION("Metro.Print", 0, 2); |
| // TODO(mad): Use a passed in destination interface instead. |
| g_browser_process->print_job_manager()->queue()->SetDestination( |
| printing::CreatePrintDestination()); |
| return PrintNowInternal(new PrintMsg_PrintPages(routing_id())); |
| } |
| |
| bool PrintViewManager::PrintPreviewNow(bool selection_only) { |
| // Users can send print commands all they want and it is beyond |
| // PrintViewManager's control. Just ignore the extra commands. |
| // See http://crbug.com/136842 for example. |
| if (print_preview_state_ != NOT_PREVIEWING) |
| return false; |
| |
| if (!PrintNowInternal(new PrintMsg_InitiatePrintPreview(routing_id(), |
| selection_only))) { |
| return false; |
| } |
| |
| print_preview_state_ = USER_INITIATED_PREVIEW; |
| return true; |
| } |
| |
| void PrintViewManager::PrintPreviewForWebNode() { |
| if (print_preview_state_ != NOT_PREVIEWING) |
| return; |
| print_preview_state_ = USER_INITIATED_PREVIEW; |
| } |
| |
| void PrintViewManager::PrintPreviewDone() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| DCHECK_NE(NOT_PREVIEWING, print_preview_state_); |
| |
| if (print_preview_state_ == SCRIPTED_PREVIEW) { |
| ScriptedPrintPreviewClosureMap& map = |
| g_scripted_print_preview_closure_map.Get(); |
| ScriptedPrintPreviewClosureMap::iterator it = |
| map.find(scripted_print_preview_rph_); |
| CHECK(it != map.end()); |
| it->second.Run(); |
| map.erase(scripted_print_preview_rph_); |
| scripted_print_preview_rph_ = NULL; |
| } |
| print_preview_state_ = NOT_PREVIEWING; |
| } |
| |
| void PrintViewManager::set_observer(PrintViewManagerObserver* observer) { |
| DCHECK(!observer || !observer_); |
| observer_ = observer; |
| } |
| |
| void PrintViewManager::RenderProcessGone(base::TerminationStatus status) { |
| print_preview_state_ = NOT_PREVIEWING; |
| PrintViewManagerBase::RenderProcessGone(status); |
| } |
| |
| void PrintViewManager::OnDidShowPrintDialog() { |
| if (observer_) |
| observer_->OnPrintDialogShown(); |
| } |
| |
| void PrintViewManager::OnSetupScriptedPrintPreview(IPC::Message* reply_msg) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| ScriptedPrintPreviewClosureMap& map = |
| g_scripted_print_preview_closure_map.Get(); |
| content::RenderProcessHost* rph = web_contents()->GetRenderProcessHost(); |
| |
| // This should always be 0 once we get modal window.print(). |
| if (map.count(rph) != 0) { |
| // Renderer already handling window.print() in another View. |
| Send(reply_msg); |
| return; |
| } |
| if (print_preview_state_ != NOT_PREVIEWING) { |
| // If a user initiated print dialog is already open, ignore the scripted |
| // print message. |
| DCHECK_EQ(USER_INITIATED_PREVIEW, print_preview_state_); |
| Send(reply_msg); |
| return; |
| } |
| |
| PrintPreviewDialogController* dialog_controller = |
| PrintPreviewDialogController::GetInstance(); |
| if (!dialog_controller) { |
| Send(reply_msg); |
| return; |
| } |
| |
| print_preview_state_ = SCRIPTED_PREVIEW; |
| base::Closure callback = |
| base::Bind(&PrintViewManager::OnScriptedPrintPreviewReply, |
| base::Unretained(this), |
| reply_msg); |
| map[rph] = callback; |
| scripted_print_preview_rph_ = rph; |
| } |
| |
| void PrintViewManager::OnShowScriptedPrintPreview(bool source_is_modifiable) { |
| PrintPreviewDialogController* dialog_controller = |
| PrintPreviewDialogController::GetInstance(); |
| if (!dialog_controller) { |
| PrintPreviewDone(); |
| return; |
| } |
| dialog_controller->PrintPreview(web_contents()); |
| PrintHostMsg_RequestPrintPreview_Params params; |
| params.is_modifiable = source_is_modifiable; |
| PrintPreviewUI::SetInitialParams( |
| dialog_controller->GetPrintPreviewForContents(web_contents()), params); |
| } |
| |
| void PrintViewManager::OnScriptedPrintPreviewReply(IPC::Message* reply_msg) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| Send(reply_msg); |
| } |
| |
| bool PrintViewManager::OnMessageReceived(const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message) |
| IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_SetupScriptedPrintPreview, |
| OnSetupScriptedPrintPreview) |
| IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview, |
| OnShowScriptedPrintPreview) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| |
| return handled ? true : PrintViewManagerBase::OnMessageReceived(message); |
| } |
| |
| } // namespace printing |