Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1739)

Unified Diff: chrome/browser/printing/print_view_manager.cc

Issue 22577010: Printing: Add a basic printing mode without print preview and cloud print. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/printing/print_view_manager.h ('k') | chrome/browser/printing/print_view_manager_base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..2b720370dbd7807d95b42e8dfa267296032ee28f 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -7,43 +7,19 @@
#include <map>
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/lazy_instance.h"
-#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"
-#include "grit/generated_resources.h"
-#include "printing/metafile.h"
-#include "printing/metafile_impl.h"
#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 +32,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 +56,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 +118,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 +133,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 +181,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
« no previous file with comments | « chrome/browser/printing/print_view_manager.h ('k') | chrome/browser/printing/print_view_manager_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698