Chromium Code Reviews| Index: chrome/browser/printing/print_view_manager.cc |
| diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc |
| index 7ed48ac70b5461d8f474153c7c331aa479036a47..d0b5c109ab38cc83d9d23272b311870685b82dab 100644 |
| --- a/chrome/browser/printing/print_view_manager.cc |
| +++ b/chrome/browser/printing/print_view_manager.cc |
| @@ -12,25 +12,17 @@ |
| #include "base/memory/scoped_ptr.h" |
| #include "base/metrics/histogram.h" |
| #include "base/prefs/pref_service.h" |
| -#include "base/strings/utf_string_conversions.h" |
| -#include "base/timer/timer.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| -#include "chrome/browser/printing/print_error_dialog.h" |
| #include "chrome/browser/printing/print_job.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/printing/printer_query.h" |
| -#include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/print_messages.h" |
| #include "content/public/browser/browser_thread.h" |
| -#include "content/public/browser/notification_details.h" |
| -#include "content/public/browser/notification_service.h" |
| -#include "content/public/browser/notification_source.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_view.h" |
| @@ -39,11 +31,8 @@ |
| #include "printing/metafile_impl.h" |
|
cimamoglu1
2013/08/11 18:22:51
Do we need this in this class? (also for metafile.
Lei Zhang
2013/08/12 06:06:15
Done.
|
| #include "printing/print_destination_interface.h" |
| #include "printing/printed_document.h" |
| -#include "ui/base/l10n/l10n_util.h" |
| -using base::TimeDelta; |
| using content::BrowserThread; |
| -using content::WebContents; |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager); |
| @@ -56,45 +45,19 @@ typedef std::map<content::RenderProcessHost*, base::Closure> |
| static base::LazyInstance<ScriptedPrintPreviewClosureMap> |
| g_scripted_print_preview_closure_map = LAZY_INSTANCE_INITIALIZER; |
| -// Limits memory usage by raster to 64 MiB. |
| -const int kMaxRasterSizeInPixels = 16*1024*1024; |
| - |
| } // namespace |
| namespace printing { |
| PrintViewManager::PrintViewManager(content::WebContents* web_contents) |
| - : content::WebContentsObserver(web_contents), |
| - number_pages_(0), |
| - printing_succeeded_(false), |
| - inside_inner_message_loop_(false), |
| + : PrintViewManagerBase(web_contents), |
| observer_(NULL), |
| - cookie_(0), |
| print_preview_state_(NOT_PREVIEWING), |
| - scripted_print_preview_rph_(NULL), |
| - tab_content_blocked_(false) { |
| -#if defined(OS_POSIX) && !defined(OS_MACOSX) |
| - expecting_first_page_ = true; |
| -#endif |
| - registrar_.Add(this, chrome::NOTIFICATION_CONTENT_BLOCKED_STATE_CHANGED, |
| - content::Source<content::WebContents>(web_contents)); |
| - Profile* profile = |
| - Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| - printing_enabled_.Init( |
| - prefs::kPrintingEnabled, |
| - profile->GetPrefs(), |
| - base::Bind(&PrintViewManager::UpdateScriptedPrintingBlocked, |
| - base::Unretained(this))); |
| + scripted_print_preview_rph_(NULL) { |
| } |
| PrintViewManager::~PrintViewManager() { |
| DCHECK_EQ(NOT_PREVIEWING, print_preview_state_); |
| - ReleasePrinterQuery(); |
| - DisconnectFromCurrentPrintJob(); |
| -} |
| - |
| -bool PrintViewManager::PrintNow() { |
| - return PrintNowInternal(new PrintMsg_PrintPages(routing_id())); |
| } |
| bool PrintViewManager::PrintForSystemDialogNow() { |
| @@ -106,7 +69,7 @@ bool PrintViewManager::AdvancedPrintNow() { |
| PrintPreviewDialogController::GetInstance(); |
| if (!dialog_controller) |
| return false; |
| - WebContents* print_preview_dialog = |
| + content::WebContents* print_preview_dialog = |
| dialog_controller->GetPrintPreviewForContents(web_contents()); |
| if (print_preview_dialog) { |
| if (!print_preview_dialog->GetWebUI()) |
| @@ -168,54 +131,14 @@ void PrintViewManager::PrintPreviewDone() { |
| print_preview_state_ = NOT_PREVIEWING; |
| } |
| -void PrintViewManager::UpdateScriptedPrintingBlocked() { |
| - Send(new PrintMsg_SetScriptedPrintingBlocked( |
| - routing_id(), |
| - !printing_enabled_.GetValue() || tab_content_blocked_)); |
| -} |
| - |
| void PrintViewManager::set_observer(PrintViewManagerObserver* observer) { |
| DCHECK(!observer || !observer_); |
| observer_ = observer; |
| } |
| -void PrintViewManager::StopNavigation() { |
| - // Cancel the current job, wait for the worker to finish. |
| - TerminatePrintJob(true); |
| -} |
| - |
| void PrintViewManager::RenderProcessGone(base::TerminationStatus status) { |
| print_preview_state_ = NOT_PREVIEWING; |
| - ReleasePrinterQuery(); |
| - |
| - if (!print_job_.get()) |
| - return; |
| - |
| - scoped_refptr<PrintedDocument> document(print_job_->document()); |
| - if (document.get()) { |
| - // If IsComplete() returns false, the document isn't completely rendered. |
| - // Since our renderer is gone, there's nothing to do, cancel it. Otherwise, |
| - // the print job may finish without problem. |
| - TerminatePrintJob(!document->IsComplete()); |
| - } |
| -} |
| - |
| -string16 PrintViewManager::RenderSourceName() { |
| - string16 name(web_contents()->GetTitle()); |
| - if (name.empty()) |
| - name = l10n_util::GetStringUTF16(IDS_DEFAULT_PRINT_DOCUMENT_TITLE); |
| - return name; |
| -} |
| - |
| -void PrintViewManager::OnDidGetPrintedPagesCount(int cookie, int number_pages) { |
| - DCHECK_GT(cookie, 0); |
| - DCHECK_GT(number_pages, 0); |
| - number_pages_ = number_pages; |
| - OpportunisticallyCreatePrintJob(cookie); |
| -} |
| - |
| -void PrintViewManager::OnDidGetDocumentCookie(int cookie) { |
| - cookie_ = cookie; |
| + PrintViewManagerBase::RenderProcessGone(status); |
| } |
| void PrintViewManager::OnDidShowPrintDialog() { |
| @@ -223,90 +146,6 @@ void PrintViewManager::OnDidShowPrintDialog() { |
| observer_->OnPrintDialogShown(); |
| } |
| -void PrintViewManager::OnDidPrintPage( |
| - const PrintHostMsg_DidPrintPage_Params& params) { |
| - if (!OpportunisticallyCreatePrintJob(params.document_cookie)) |
| - return; |
| - |
| - PrintedDocument* document = print_job_->document(); |
| - if (!document || params.document_cookie != document->cookie()) { |
| - // Out of sync. It may happen since we are completely asynchronous. Old |
| - // spurious messages can be received if one of the processes is overloaded. |
| - return; |
| - } |
| - |
| -#if defined(OS_WIN) || defined(OS_MACOSX) |
| - const bool metafile_must_be_valid = true; |
| -#elif defined(OS_POSIX) |
| - const bool metafile_must_be_valid = expecting_first_page_; |
| - expecting_first_page_ = false; |
| -#endif |
| - |
| - base::SharedMemory shared_buf(params.metafile_data_handle, true); |
| - if (metafile_must_be_valid) { |
| - if (!shared_buf.Map(params.data_size)) { |
| - NOTREACHED() << "couldn't map"; |
| - web_contents()->Stop(); |
| - return; |
| - } |
| - } |
| - |
| - scoped_ptr<NativeMetafile> metafile(new NativeMetafile); |
| - if (metafile_must_be_valid) { |
| - if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { |
| - NOTREACHED() << "Invalid metafile header"; |
| - web_contents()->Stop(); |
| - return; |
| - } |
| - } |
| - |
| -#if defined(OS_WIN) |
| - bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize); |
| - const CommandLine* cmdline = CommandLine::ForCurrentProcess(); |
| - int raster_size = std::min(params.page_size.GetArea(), |
| - kMaxRasterSizeInPixels); |
| - if (big_emf || (cmdline && cmdline->HasSwitch(switches::kPrintRaster))) { |
| - scoped_ptr<NativeMetafile> raster_metafile( |
| - metafile->RasterizeMetafile(raster_size)); |
| - if (raster_metafile.get()) { |
| - metafile.swap(raster_metafile); |
| - } else if (big_emf) { |
| - // Don't fall back to emf here. |
| - NOTREACHED() << "size:" << params.data_size; |
| - TerminatePrintJob(true); |
| - web_contents()->Stop(); |
| - return; |
| - } |
| - } |
| -#endif |
| - |
| - // Update the rendered document. It will send notifications to the listener. |
| - document->SetPage(params.page_number, |
| - metafile.release(), |
| - params.actual_shrink, |
| - params.page_size, |
| - params.content_area); |
| - |
| - ShouldQuitFromInnerMessageLoop(); |
| -} |
| - |
| -void PrintViewManager::OnPrintingFailed(int cookie) { |
| - if (cookie != cookie_) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - |
| - chrome::ShowPrintErrorDialog( |
| - web_contents()->GetView()->GetTopLevelNativeWindow()); |
| - |
| - ReleasePrinterQuery(); |
| - |
| - content::NotificationService::current()->Notify( |
| - chrome::NOTIFICATION_PRINT_JOB_RELEASED, |
| - content::Source<content::WebContents>(web_contents()), |
| - content::NotificationService::NoDetails()); |
| -} |
| - |
| void PrintViewManager::OnScriptedPrintPreview(bool source_is_modifiable, |
| IPC::Message* reply_msg) { |
| BrowserThread::CurrentlyOn(BrowserThread::UI); |
| @@ -355,331 +194,16 @@ void PrintViewManager::OnScriptedPrintPreviewReply(IPC::Message* reply_msg) { |
| Send(reply_msg); |
| } |
| -void PrintViewManager::DidStartLoading( |
| - content::RenderViewHost* render_view_host) { |
| - UpdateScriptedPrintingBlocked(); |
| -} |
| - |
| bool PrintViewManager::OnMessageReceived(const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message) |
| - IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount, |
| - OnDidGetPrintedPagesCount) |
| - IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie, |
| - OnDidGetDocumentCookie) |
| IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) |
| - IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) |
| - IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrintPreview, |
| OnScriptedPrintPreview) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| - return handled; |
| -} |
| - |
| -void PrintViewManager::Observe(int type, |
| - const content::NotificationSource& source, |
| - const content::NotificationDetails& details) { |
| - switch (type) { |
| - case chrome::NOTIFICATION_PRINT_JOB_EVENT: { |
| - OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr()); |
| - break; |
| - } |
| - case chrome::NOTIFICATION_CONTENT_BLOCKED_STATE_CHANGED: { |
| - tab_content_blocked_ = *content::Details<const bool>(details).ptr(); |
| - UpdateScriptedPrintingBlocked(); |
| - break; |
| - } |
| - default: { |
| - NOTREACHED(); |
| - break; |
| - } |
| - } |
| -} |
| -void PrintViewManager::OnNotifyPrintJobEvent( |
| - const JobEventDetails& event_details) { |
| - switch (event_details.type()) { |
| - case JobEventDetails::FAILED: { |
| - TerminatePrintJob(true); |
| - |
| - content::NotificationService::current()->Notify( |
| - chrome::NOTIFICATION_PRINT_JOB_RELEASED, |
| - content::Source<content::WebContents>(web_contents()), |
| - content::NotificationService::NoDetails()); |
| - break; |
| - } |
| - case JobEventDetails::USER_INIT_DONE: |
| - case JobEventDetails::DEFAULT_INIT_DONE: |
| - case JobEventDetails::USER_INIT_CANCELED: { |
| - NOTREACHED(); |
| - break; |
| - } |
| - case JobEventDetails::ALL_PAGES_REQUESTED: { |
| - ShouldQuitFromInnerMessageLoop(); |
| - break; |
| - } |
| - case JobEventDetails::NEW_DOC: |
| - case JobEventDetails::NEW_PAGE: |
| - case JobEventDetails::PAGE_DONE: |
| - case JobEventDetails::DOC_DONE: { |
| - // Don't care about the actual printing process. |
| - break; |
| - } |
| - case JobEventDetails::JOB_DONE: { |
| - // Printing is done, we don't need it anymore. |
| - // print_job_->is_job_pending() may still be true, depending on the order |
| - // of object registration. |
| - printing_succeeded_ = true; |
| - ReleasePrintJob(); |
| - |
| - content::NotificationService::current()->Notify( |
| - chrome::NOTIFICATION_PRINT_JOB_RELEASED, |
| - content::Source<content::WebContents>(web_contents()), |
| - content::NotificationService::NoDetails()); |
| - break; |
| - } |
| - default: { |
| - NOTREACHED(); |
| - break; |
| - } |
| - } |
| -} |
| - |
| -bool PrintViewManager::RenderAllMissingPagesNow() { |
| - if (!print_job_.get() || !print_job_->is_job_pending()) |
| - return false; |
| - |
| - // We can't print if there is no renderer. |
| - if (!web_contents() || |
| - !web_contents()->GetRenderViewHost() || |
| - !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { |
| - return false; |
| - } |
| - |
| - // Is the document already complete? |
| - if (print_job_->document() && print_job_->document()->IsComplete()) { |
| - printing_succeeded_ = true; |
| - return true; |
| - } |
| - |
| - // WebContents is either dying or a second consecutive request to print |
| - // happened before the first had time to finish. We need to render all the |
| - // pages in an hurry if a print_job_ is still pending. No need to wait for it |
| - // to actually spool the pages, only to have the renderer generate them. Run |
| - // a message loop until we get our signal that the print job is satisfied. |
| - // PrintJob will send a ALL_PAGES_REQUESTED after having received all the |
| - // pages it needs. MessageLoop::current()->Quit() will be called as soon as |
| - // print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED |
| - // or in DidPrintPage(). The check is done in |
| - // ShouldQuitFromInnerMessageLoop(). |
| - // BLOCKS until all the pages are received. (Need to enable recursive task) |
| - if (!RunInnerMessageLoop()) { |
| - // This function is always called from DisconnectFromCurrentPrintJob() so we |
| - // know that the job will be stopped/canceled in any case. |
| - return false; |
| - } |
| - return true; |
| -} |
| - |
| -void PrintViewManager::ShouldQuitFromInnerMessageLoop() { |
| - // Look at the reason. |
| - DCHECK(print_job_->document()); |
| - if (print_job_->document() && |
| - print_job_->document()->IsComplete() && |
| - inside_inner_message_loop_) { |
| - // We are in a message loop created by RenderAllMissingPagesNow. Quit from |
| - // it. |
| - base::MessageLoop::current()->Quit(); |
| - inside_inner_message_loop_ = false; |
| - } |
| -} |
| - |
| -bool PrintViewManager::CreateNewPrintJob(PrintJobWorkerOwner* job) { |
| - DCHECK(!inside_inner_message_loop_); |
| - |
| - // Disconnect the current print_job_. |
| - DisconnectFromCurrentPrintJob(); |
| - |
| - // We can't print if there is no renderer. |
| - if (!web_contents()->GetRenderViewHost() || |
| - !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { |
| - return false; |
| - } |
| - |
| - // Ask the renderer to generate the print preview, create the print preview |
| - // view and switch to it, initialize the printer and show the print dialog. |
| - DCHECK(!print_job_.get()); |
| - DCHECK(job); |
| - if (!job) |
| - return false; |
| - |
| - print_job_ = new PrintJob(); |
| - print_job_->Initialize(job, this, number_pages_); |
| - registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| - content::Source<PrintJob>(print_job_.get())); |
| - printing_succeeded_ = false; |
| - return true; |
| -} |
| - |
| -void PrintViewManager::DisconnectFromCurrentPrintJob() { |
| - // Make sure all the necessary rendered page are done. Don't bother with the |
| - // return value. |
| - bool result = RenderAllMissingPagesNow(); |
| - |
| - // Verify that assertion. |
| - if (print_job_.get() && |
| - print_job_->document() && |
| - !print_job_->document()->IsComplete()) { |
| - DCHECK(!result); |
| - // That failed. |
| - TerminatePrintJob(true); |
| - } else { |
| - // DO NOT wait for the job to finish. |
| - ReleasePrintJob(); |
| - } |
| -#if defined(OS_POSIX) && !defined(OS_MACOSX) |
| - expecting_first_page_ = true; |
| -#endif |
| -} |
| - |
| -void PrintViewManager::PrintingDone(bool success) { |
| - if (!print_job_.get()) |
| - return; |
| - Send(new PrintMsg_PrintingDone(routing_id(), success)); |
| -} |
| - |
| -void PrintViewManager::TerminatePrintJob(bool cancel) { |
| - if (!print_job_.get()) |
| - return; |
| - |
| - if (cancel) { |
| - // We don't need the metafile data anymore because the printing is canceled. |
| - print_job_->Cancel(); |
| - inside_inner_message_loop_ = false; |
| - } else { |
| - DCHECK(!inside_inner_message_loop_); |
| - DCHECK(!print_job_->document() || print_job_->document()->IsComplete()); |
| - |
| - // WebContents is either dying or navigating elsewhere. We need to render |
| - // all the pages in an hurry if a print job is still pending. This does the |
| - // trick since it runs a blocking message loop: |
| - print_job_->Stop(); |
| - } |
| - ReleasePrintJob(); |
| -} |
| - |
| -void PrintViewManager::ReleasePrintJob() { |
| - if (!print_job_.get()) |
| - return; |
| - |
| - PrintingDone(printing_succeeded_); |
| - |
| - registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| - content::Source<PrintJob>(print_job_.get())); |
| - print_job_->DisconnectSource(); |
| - // Don't close the worker thread. |
| - print_job_ = NULL; |
| -} |
| - |
| -bool PrintViewManager::RunInnerMessageLoop() { |
| - // This value may actually be too low: |
| - // |
| - // - If we're looping because of printer settings initialization, the premise |
| - // here is that some poor users have their print server away on a VPN over a |
| - // slow connection. In this situation, the simple fact of opening the printer |
| - // can be dead slow. On the other side, we don't want to die infinitely for a |
| - // real network error. Give the printer 60 seconds to comply. |
| - // |
| - // - If we're looping because of renderer page generation, the renderer could |
| - // be CPU bound, the page overly complex/large or the system just |
| - // memory-bound. |
| - static const int kPrinterSettingsTimeout = 60000; |
| - base::OneShotTimer<base::MessageLoop> quit_timer; |
| - quit_timer.Start(FROM_HERE, |
| - TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), |
| - base::MessageLoop::current(), &base::MessageLoop::Quit); |
| - |
| - inside_inner_message_loop_ = true; |
| - |
| - // Need to enable recursive task. |
| - { |
| - base::MessageLoop::ScopedNestableTaskAllower allow( |
| - base::MessageLoop::current()); |
| - base::MessageLoop::current()->Run(); |
| - } |
| - |
| - bool success = true; |
| - if (inside_inner_message_loop_) { |
| - // Ok we timed out. That's sad. |
| - inside_inner_message_loop_ = false; |
| - success = false; |
| - } |
| - |
| - return success; |
| -} |
| - |
| -bool PrintViewManager::OpportunisticallyCreatePrintJob(int cookie) { |
| - if (print_job_.get()) |
| - return true; |
| - |
| - if (!cookie) { |
| - // Out of sync. It may happens since we are completely asynchronous. Old |
| - // spurious message can happen if one of the processes is overloaded. |
| - return false; |
| - } |
| - |
| - // The job was initiated by a script. Time to get the corresponding worker |
| - // thread. |
| - scoped_refptr<PrinterQuery> queued_query; |
| - g_browser_process->print_job_manager()->PopPrinterQuery(cookie, |
| - &queued_query); |
| - DCHECK(queued_query.get()); |
| - if (!queued_query.get()) |
| - return false; |
| - |
| - if (!CreateNewPrintJob(queued_query.get())) { |
| - // Don't kill anything. |
| - return false; |
| - } |
| - |
| - // Settings are already loaded. Go ahead. This will set |
| - // print_job_->is_job_pending() to true. |
| - print_job_->StartPrinting(); |
| - return true; |
| -} |
| - |
| -bool PrintViewManager::PrintNowInternal(IPC::Message* message) { |
| - // Don't print / print preview interstitials. |
| - if (web_contents()->ShowingInterstitialPage()) { |
| - delete message; |
| - return false; |
| - } |
| - return Send(message); |
| -} |
| - |
| -void PrintViewManager::ReleasePrinterQuery() { |
| - if (!cookie_) |
| - return; |
| - |
| - int cookie = cookie_; |
| - cookie_ = 0; |
| - g_browser_process->print_job_manager()->SetPrintDestination(NULL); |
| - |
| - |
| - printing::PrintJobManager* print_job_manager = |
| - g_browser_process->print_job_manager(); |
| - // May be NULL in tests. |
| - if (!print_job_manager) |
| - return; |
| - |
| - scoped_refptr<printing::PrinterQuery> printer_query; |
| - print_job_manager->PopPrinterQuery(cookie, &printer_query); |
| - if (!printer_query.get()) |
| - return; |
| - BrowserThread::PostTask( |
| - BrowserThread::IO, FROM_HERE, |
| - base::Bind(&PrinterQuery::StopWorker, printer_query.get())); |
| + return handled ? true : PrintViewManagerBase::OnMessageReceived(message); |
| } |
| } // namespace printing |