From d309fd5a27d58512fa3890f0437be7b5a53fe5e4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 06:55:40 -0800 Subject: [PATCH] Update printing code --- atom.gyp | 3 +- atom/browser/atom_browser_client.cc | 2 +- atom/renderer/atom_renderer_client.cc | 2 +- atom/renderer/atom_renderer_client.h | 2 +- .../chrome/browser/printing/print_job.cc | 69 ++-- .../chrome/browser/printing/print_job.h | 21 +- .../browser/printing/print_job_manager.cc | 33 +- .../browser/printing/print_job_manager.h | 10 +- .../browser/printing/print_job_worker.cc | 210 +++++++----- .../browser/printing/print_job_worker.h | 60 ++-- .../printing/print_job_worker_owner.cc | 27 ++ .../browser/printing/print_job_worker_owner.h | 24 +- .../printing/print_view_manager_base.cc | 82 ++--- .../printing/print_view_manager_base.h | 9 +- .../chrome/browser/printing/printer_query.cc | 47 +-- .../chrome/browser/printing/printer_query.h | 16 +- .../printing/printing_message_filter.cc | 306 +++++++++++++----- .../printing/printing_message_filter.h | 63 ++-- .../printing/print_web_view_helper.cc | 78 ++--- .../renderer/printing/print_web_view_helper.h | 55 ++-- .../printing/print_web_view_helper_linux.cc | 13 +- .../printing/print_web_view_helper_mac.mm | 16 +- vendor/brightray | 2 +- 23 files changed, 665 insertions(+), 485 deletions(-) create mode 100644 chromium_src/chrome/browser/printing/print_job_worker_owner.cc diff --git a/atom.gyp b/atom.gyp index e3c9eeab71cd..3c368b1b9e51 100644 --- a/atom.gyp +++ b/atom.gyp @@ -283,6 +283,7 @@ 'chromium_src/chrome/browser/printing/print_job_manager.h', 'chromium_src/chrome/browser/printing/print_job_worker.cc', 'chromium_src/chrome/browser/printing/print_job_worker.h', + 'chromium_src/chrome/browser/printing/print_job_worker_owner.cc', 'chromium_src/chrome/browser/printing/print_job_worker_owner.h', 'chromium_src/chrome/browser/printing/print_view_manager_base.cc', 'chromium_src/chrome/browser/printing/print_view_manager_base.h', @@ -293,8 +294,6 @@ 'chromium_src/chrome/browser/printing/printer_query.h', 'chromium_src/chrome/browser/printing/printing_message_filter.cc', 'chromium_src/chrome/browser/printing/printing_message_filter.h', - 'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.cc', - 'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.h', 'chromium_src/chrome/browser/speech/tts_controller.h', 'chromium_src/chrome/browser/speech/tts_controller_impl.cc', 'chromium_src/chrome/browser/speech/tts_controller_impl.h', diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index c39acc06ca2e..7b908676b14b 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -56,7 +56,7 @@ AtomBrowserClient::~AtomBrowserClient() { void AtomBrowserClient::RenderProcessWillLaunch( content::RenderProcessHost* host) { int id = host->GetID(); - host->AddFilter(new PrintingMessageFilter(host->GetID())); + host->AddFilter(new printing::PrintingMessageFilter(host->GetID())); host->AddFilter(new TtsMessageFilter(id, host->GetBrowserContext())); } diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 91d83bf1f4b1..7a108d72c5e1 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -161,7 +161,7 @@ void AtomRendererClient::DidCreateScriptContext(blink::WebFrame* frame, } void AtomRendererClient::WillReleaseScriptContext( - blink::WebFrame* frame, + blink::WebLocalFrame* frame, v8::Handle context, int world_id) { node::Environment* env = node::Environment::GetCurrent(context); diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index cb461b2bcaa0..ed2c1e1ad7e1 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -27,7 +27,7 @@ class AtomRendererClient : public content::ContentRendererClient, virtual ~AtomRendererClient(); // Forwarded by RenderFrameObserver. - void WillReleaseScriptContext(blink::WebFrame* frame, + void WillReleaseScriptContext(blink::WebLocalFrame* frame, v8::Handle context, int world_id); diff --git a/chromium_src/chrome/browser/printing/print_job.cc b/chromium_src/chrome/browser/printing/print_job.cc index 4a58440685b9..25cf0ad79033 100644 --- a/chromium_src/chrome/browser/printing/print_job.cc +++ b/chromium_src/chrome/browser/printing/print_job.cc @@ -32,29 +32,25 @@ void HoldRefCallback(const scoped_refptr& owner, namespace printing { PrintJob::PrintJob() - : ui_message_loop_(base::MessageLoop::current()), - source_(NULL), + : source_(NULL), worker_(), settings_(), is_job_pending_(false), is_canceling_(false), quit_factory_(this) { - DCHECK(ui_message_loop_); // This is normally a UI message loop, but in unit tests, the message loop is // of the 'default' type. DCHECK(base::MessageLoopForUI::IsCurrent() || - ui_message_loop_->type() == base::MessageLoop::TYPE_DEFAULT); - ui_message_loop_->AddDestructionObserver(this); + base::MessageLoop::current()->type() == + base::MessageLoop::TYPE_DEFAULT); } PrintJob::~PrintJob() { - ui_message_loop_->RemoveDestructionObserver(this); // The job should be finished (or at least canceled) when it is destroyed. DCHECK(!is_job_pending_); DCHECK(!is_canceling_); - if (worker_.get()) - DCHECK(worker_->message_loop() == NULL); - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(!worker_ || !worker_->IsRunning()); + DCHECK(RunsTasksOnCurrentThread()); } void PrintJob::Initialize(PrintJobWorkerOwner* job, @@ -85,7 +81,7 @@ void PrintJob::Initialize(PrintJobWorkerOwner* job, void PrintJob::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); switch (type) { case chrome::NOTIFICATION_PRINT_JOB_EVENT: { OnNotifyPrintJobEvent(*content::Details(details).ptr()); @@ -107,10 +103,6 @@ PrintJobWorker* PrintJob::DetachWorker(PrintJobWorkerOwner* new_owner) { return NULL; } -base::MessageLoop* PrintJob::message_loop() { - return ui_message_loop_; -} - const PrintSettings& PrintJob::settings() const { return settings_; } @@ -122,23 +114,20 @@ int PrintJob::cookie() const { return document_->cookie(); } -void PrintJob::WillDestroyCurrentMessageLoop() { - NOTREACHED(); -} - void PrintJob::StartPrinting() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); - DCHECK(worker_->message_loop()); + DCHECK(RunsTasksOnCurrentThread()); + DCHECK(worker_->IsRunning()); DCHECK(!is_job_pending_); - if (!worker_->message_loop() || is_job_pending_) + if (!worker_->IsRunning() || is_job_pending_) return; // Real work is done in PrintJobWorker::StartPrinting(). - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(this), - base::Bind(&PrintJobWorker::StartPrinting, - base::Unretained(worker_.get()), document_))); + worker_->PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(this), + base::Bind(&PrintJobWorker::StartPrinting, + base::Unretained(worker_.get()), + document_))); // Set the flag right now. is_job_pending_ = true; @@ -152,7 +141,7 @@ void PrintJob::StartPrinting() { } void PrintJob::Stop() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); if (quit_factory_.HasWeakPtrs()) { // In case we're running a nested message loop to wait for a job to finish, @@ -164,7 +153,7 @@ void PrintJob::Stop() { // Be sure to live long enough. scoped_refptr handle(this); - if (worker_->message_loop()) { + if (worker_->IsRunning()) { ControlledWorkerShutdown(); } else { // Flush the cached document. @@ -180,10 +169,8 @@ void PrintJob::Cancel() { // Be sure to live long enough. scoped_refptr handle(this); - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); - base::MessageLoop* worker_loop = - worker_.get() ? worker_->message_loop() : NULL; - if (worker_loop) { + DCHECK(RunsTasksOnCurrentThread()); + if (worker_ && worker_->IsRunning()) { // Call this right now so it renders the context invalid. Do not use // InvokeLater since it would take too much time. worker_->Cancel(); @@ -237,14 +224,15 @@ void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) { settings_ = document_->settings(); } - if (worker_.get() && worker_->message_loop()) { + if (worker_) { DCHECK(!is_job_pending_); // Sync the document with the worker. - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(this), - base::Bind(&PrintJobWorker::OnDocumentChanged, - base::Unretained(worker_.get()), document_))); + worker_->PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(this), + base::Bind(&PrintJobWorker::OnDocumentChanged, + base::Unretained(worker_.get()), + document_))); } } @@ -264,7 +252,6 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) { } case JobEventDetails::NEW_DOC: case JobEventDetails::NEW_PAGE: - case JobEventDetails::PAGE_DONE: case JobEventDetails::JOB_DONE: case JobEventDetails::ALL_PAGES_REQUESTED: { // Don't care. @@ -276,6 +263,8 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) { FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this)); break; } + case JobEventDetails::PAGE_DONE: + break; default: { NOTREACHED(); break; @@ -300,7 +289,7 @@ void PrintJob::OnDocumentDone() { } void PrintJob::ControlledWorkerShutdown() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); // The deadlock this code works around is specific to window messaging on // Windows, so we aren't likely to need it on any other platforms. diff --git a/chromium_src/chrome/browser/printing/print_job.h b/chromium_src/chrome/browser/printing/print_job.h index 2ff827a8edc8..1b816085c6a4 100644 --- a/chromium_src/chrome/browser/printing/print_job.h +++ b/chromium_src/chrome/browser/printing/print_job.h @@ -15,15 +15,19 @@ class Thread; +namespace base { +class RefCountedMemory; +} + namespace printing { -// See definition below. class JobEventDetails; - +class MetafilePlayer; +class PdfToEmfConverter; +class PrintJobWorker; class PrintedDocument; class PrintedPage; class PrintedPagesSource; -class PrintJobWorker; class PrinterQuery; // Manages the print work for a specific document. Talks to the printer through @@ -33,8 +37,7 @@ class PrinterQuery; // reference to the job to be sure it is kept alive. All the code in this class // runs in the UI thread. class PrintJob : public PrintJobWorkerOwner, - public content::NotificationObserver, - public base::MessageLoop::DestructionObserver { + public content::NotificationObserver { public: // Create a empty PrintJob. When initializing with this constructor, // post-constructor initialization must be done with Initialize(). @@ -54,13 +57,9 @@ class PrintJob : public PrintJobWorkerOwner, virtual void GetSettingsDone(const PrintSettings& new_settings, PrintingContext::Result result) OVERRIDE; virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE; - virtual base::MessageLoop* message_loop() OVERRIDE; virtual const PrintSettings& settings() const OVERRIDE; virtual int cookie() const OVERRIDE; - // DestructionObserver implementation. - virtual void WillDestroyCurrentMessageLoop() OVERRIDE; - // Starts the actual printing. Signals the worker that it should begin to // spool as soon as data is available. void StartPrinting(); @@ -116,10 +115,6 @@ class PrintJob : public PrintJobWorkerOwner, content::NotificationRegistrar registrar_; - // Main message loop reference. Used to send notifications in the right - // thread. - base::MessageLoop* const ui_message_loop_; - // Source that generates the PrintedPage's (i.e. a WebContents). It will be // set back to NULL if the source is deleted before this object. PrintedPagesSource* source_; diff --git a/chromium_src/chrome/browser/printing/print_job_manager.cc b/chromium_src/chrome/browser/printing/print_job_manager.cc index 9dc0c85404c1..ec08a9892335 100644 --- a/chromium_src/chrome/browser/printing/print_job_manager.cc +++ b/chromium_src/chrome/browser/printing/print_job_manager.cc @@ -22,11 +22,6 @@ PrintQueriesQueue::~PrintQueriesQueue() { queued_queries_.clear(); } -void PrintQueriesQueue::SetDestination(PrintDestinationInterface* destination) { - base::AutoLock lock(lock_); - destination_ = destination; -} - void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) { base::AutoLock lock(lock_); DCHECK(job); @@ -49,17 +44,27 @@ scoped_refptr PrintQueriesQueue::PopPrinterQuery( return NULL; } -scoped_refptr PrintQueriesQueue::CreatePrinterQuery() { - scoped_refptr job = new printing::PrinterQuery; - base::AutoLock lock(lock_); - job->SetWorkerDestination(destination_); +scoped_refptr PrintQueriesQueue::CreatePrinterQuery( + int render_process_id, + int render_view_id) { + scoped_refptr job = + new printing::PrinterQuery(render_process_id, render_view_id); return job; } void PrintQueriesQueue::Shutdown() { - base::AutoLock lock(lock_); - queued_queries_.clear(); - destination_ = NULL; + PrinterQueries queries_to_stop; + { + base::AutoLock lock(lock_); + queued_queries_.swap(queries_to_stop); + } + // Stop all pending queries, requests to generate print preview do not have + // corresponding PrintJob, so any pending preview requests are not covered + // by PrintJobManager::StopJobs and should be stopped explicitly. + for (PrinterQueries::iterator itr = queries_to_stop.begin(); + itr != queries_to_stop.end(); ++itr) { + (*itr)->PostTask(FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr)); + } } PrintJobManager::PrintJobManager() : is_shutdown_(false) { @@ -72,7 +77,7 @@ PrintJobManager::~PrintJobManager() { scoped_refptr PrintJobManager::queue() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - if (!queue_) + if (!queue_.get()) queue_ = new PrintQueriesQueue(); return queue_; } @@ -83,7 +88,7 @@ void PrintJobManager::Shutdown() { is_shutdown_ = true; registrar_.RemoveAll(); StopJobs(true); - if (queue_) + if (queue_.get()) queue_->Shutdown(); queue_ = NULL; } diff --git a/chromium_src/chrome/browser/printing/print_job_manager.h b/chromium_src/chrome/browser/printing/print_job_manager.h index 9d03d9a340f2..ef61541a2ee5 100644 --- a/chromium_src/chrome/browser/printing/print_job_manager.h +++ b/chromium_src/chrome/browser/printing/print_job_manager.h @@ -10,11 +10,11 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/non_thread_safe.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "printing/print_destination_interface.h" namespace printing { @@ -26,9 +26,6 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { public: PrintQueriesQueue(); - // Sets the print destination to be set on the next print job. - void SetDestination(PrintDestinationInterface* destination); - // Queues a semi-initialized worker thread. Can be called from any thread. // Current use case is queuing from the I/O thread. // TODO(maruel): Have them vanish after a timeout (~5 minutes?) @@ -39,7 +36,8 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { scoped_refptr PopPrinterQuery(int document_cookie); // Creates new query. - scoped_refptr CreatePrinterQuery(); + scoped_refptr CreatePrinterQuery(int render_process_id, + int render_view_id); void Shutdown(); @@ -54,8 +52,6 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { PrinterQueries queued_queries_; - scoped_refptr destination_; - DISALLOW_COPY_AND_ASSIGN(PrintQueriesQueue); }; diff --git a/chromium_src/chrome/browser/printing/print_job_worker.cc b/chromium_src/chrome/browser/printing/print_job_worker.cc index a14c87c794e4..c4794f815416 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker.cc +++ b/chromium_src/chrome/browser/printing/print_job_worker.cc @@ -13,10 +13,10 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/printing/print_job.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" -#include "grit/generated_resources.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" #include "printing/print_job_constants.h" #include "printing/printed_document.h" #include "printing/printed_page.h" @@ -25,6 +25,8 @@ using content::BrowserThread; +namespace printing { + namespace { // Helper function to ensure |owner| is valid until at least |callback| returns. @@ -33,9 +35,41 @@ void HoldRefCallback(const scoped_refptr& owner, callback.Run(); } -} // namespace +class PrintingContextDelegate : public PrintingContext::Delegate { + public: + PrintingContextDelegate(int render_process_id, int render_view_id); + virtual ~PrintingContextDelegate(); -namespace printing { + virtual gfx::NativeView GetParentView() OVERRIDE; + virtual std::string GetAppLocale() OVERRIDE; + + private: + int render_process_id_; + int render_view_id_; +}; + +PrintingContextDelegate::PrintingContextDelegate(int render_process_id, + int render_view_id) + : render_process_id_(render_process_id), + render_view_id_(render_view_id) { +} + +PrintingContextDelegate::~PrintingContextDelegate() { +} + +gfx::NativeView PrintingContextDelegate::GetParentView() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::RenderViewHost* view = + content::RenderViewHost::FromID(render_process_id_, render_view_id_); + if (!view) + return NULL; + content::WebContents* wc = content::WebContents::FromRenderViewHost(view); + return wc ? wc->GetNativeView() : NULL; +} + +std::string PrintingContextDelegate::GetAppLocale() { + return g_browser_process->GetApplicationLocale(); +} void NotificationCallback(PrintJobWorkerOwner* print_job, JobEventDetails::Type detail_type, @@ -49,22 +83,25 @@ void NotificationCallback(PrintJobWorkerOwner* print_job, content::Details(details)); } -PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner) - : Thread("Printing_Worker"), - owner_(owner), - weak_factory_(this) { - // The object is created in the IO thread. - DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); +} // namespace - printing_context_.reset(PrintingContext::Create( - g_browser_process->GetApplicationLocale())); +PrintJobWorker::PrintJobWorker(int render_process_id, + int render_view_id, + PrintJobWorkerOwner* owner) + : owner_(owner), thread_("Printing_Worker"), weak_factory_(this) { + // The object is created in the IO thread. + DCHECK(owner_->RunsTasksOnCurrentThread()); + + printing_context_delegate_.reset( + new PrintingContextDelegate(render_process_id, render_view_id)); + printing_context_ = PrintingContext::Create(printing_context_delegate_.get()); } PrintJobWorker::~PrintJobWorker() { // The object is normally deleted in the UI thread, but when the user // cancels printing or in the case of print preview, the worker is destroyed // on the I/O thread. - DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); + DCHECK(owner_->RunsTasksOnCurrentThread()); Stop(); } @@ -73,18 +110,12 @@ void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) { owner_ = new_owner; } -void PrintJobWorker::SetPrintDestination( - PrintDestinationInterface* destination) { - destination_ = destination; -} - void PrintJobWorker::GetSettings( bool ask_user_for_settings, - scoped_ptr web_contents_observer, int document_page_count, bool has_selection, MarginType margin_type) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); // Recursive task processing is needed for the dialog in case it needs to be @@ -97,13 +128,12 @@ void PrintJobWorker::GetSettings( // When we delegate to a destination, we don't ask the user for settings. // TODO(mad): Ask the destination for settings. - if (ask_user_for_settings && destination_.get() == NULL) { + if (ask_user_for_settings) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), base::Bind(&PrintJobWorker::GetSettingsWithUI, base::Unretained(this), - base::Passed(&web_contents_observer), document_page_count, has_selection))); } else { @@ -116,8 +146,8 @@ void PrintJobWorker::GetSettings( } void PrintJobWorker::SetSettings( - const base::DictionaryValue* const new_settings) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + scoped_ptr new_settings) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); BrowserThread::PostTask( BrowserThread::UI, @@ -126,11 +156,12 @@ void PrintJobWorker::SetSettings( make_scoped_refptr(owner_), base::Bind(&PrintJobWorker::UpdatePrintSettings, base::Unretained(this), - base::Owned(new_settings)))); + base::Passed(&new_settings)))); } void PrintJobWorker::UpdatePrintSettings( - const base::DictionaryValue* const new_settings) { + scoped_ptr new_settings) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); PrintingContext::Result result = printing_context_->UpdatePrintSettings(*new_settings); GetSettingsDone(result); @@ -147,36 +178,31 @@ void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) { // We can't use OnFailure() here since owner_ may not support notifications. // PrintJob will create the new PrintedDocument. - owner_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorkerOwner::GetSettingsDone, - make_scoped_refptr(owner_), printing_context_->settings(), - result)); + owner_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorkerOwner::GetSettingsDone, + make_scoped_refptr(owner_), + printing_context_->settings(), + result)); } void PrintJobWorker::GetSettingsWithUI( - scoped_ptr web_contents_observer, int document_page_count, bool has_selection) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - - gfx::NativeView parent_view = web_contents_observer->GetParentView(); - if (!parent_view) { - GetSettingsWithUIDone(printing::PrintingContext::FAILED); - return; - } printing_context_->AskUserForSettings( - parent_view, document_page_count, has_selection, + document_page_count, + has_selection, base::Bind(&PrintJobWorker::GetSettingsWithUIDone, base::Unretained(this))); } void PrintJobWorker::GetSettingsWithUIDone(PrintingContext::Result result) { - message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), - base::Bind(&PrintJobWorker::GetSettingsDone, - base::Unretained(this), result))); + PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(owner_), + base::Bind(&PrintJobWorker::GetSettingsDone, + base::Unretained(this), + result))); } void PrintJobWorker::UseDefaultSettings() { @@ -185,9 +211,9 @@ void PrintJobWorker::UseDefaultSettings() { } void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); - DCHECK_EQ(document_, new_document); + DCHECK_EQ(document_.get(), new_document); DCHECK(document_.get()); if (!document_.get() || page_number_ != PageNumber::npos() || @@ -216,7 +242,7 @@ void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { } void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); if (page_number_ != PageNumber::npos()) @@ -230,7 +256,7 @@ void PrintJobWorker::OnNewPage() { return; // message_loop() could return NULL when the print job is cancelled. - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); if (page_number_ == PageNumber::npos()) { // Find first page to print. @@ -243,15 +269,13 @@ void PrintJobWorker::OnNewPage() { } // We have enough information to initialize page_number_. page_number_.Init(document_->settings(), page_count); - if (destination_.get() != NULL) - destination_->SetPageCount(page_count); } DCHECK_NE(page_number_, PageNumber::npos()); while (true) { // Is the page available? scoped_refptr page = document_->GetPage(page_number_.ToInt()); - if (!page) { + if (!page.get()) { // We need to wait for the page to be available. base::MessageLoop::current()->PostDelayedTask( FROM_HERE, @@ -277,8 +301,33 @@ void PrintJobWorker::Cancel() { // context we run. } +bool PrintJobWorker::IsRunning() const { + return thread_.IsRunning(); +} + +bool PrintJobWorker::PostTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + if (task_runner_.get()) + return task_runner_->PostTask(from_here, task); + return false; +} + +void PrintJobWorker::StopSoon() { + thread_.StopSoon(); +} + +void PrintJobWorker::Stop() { + thread_.Stop(); +} + +bool PrintJobWorker::Start() { + bool result = thread_.Start(); + task_runner_ = thread_.task_runner(); + return result; +} + void PrintJobWorker::OnDocumentDone() { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); DCHECK(document_.get()); @@ -287,24 +336,28 @@ void PrintJobWorker::OnDocumentDone() { return; } - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::DOC_DONE, document_, - scoped_refptr())); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::DOC_DONE, + document_, + scoped_refptr())); // Makes sure the variables are reinitialized. document_ = NULL; } void PrintJobWorker::SpoolPage(PrintedPage* page) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_NE(page_number_, PageNumber::npos()); // Signal everyone that the page is about to be printed. - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::NEW_PAGE, document_, - make_scoped_refptr(page))); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::NEW_PAGE, + document_, + make_scoped_refptr(page))); // Preprocess. if (printing_context_->NewPage() != PrintingContext::OK) { @@ -312,18 +365,6 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) { return; } - if (destination_.get() != NULL) { - std::vector metabytes(page->metafile()->GetDataSize()); - bool success = page->metafile()->GetData( - reinterpret_cast(&metabytes[0]), metabytes.size()); - DCHECK(success) << "Failed to get metafile data."; - destination_->SetPageContent( - page->page_number(), - reinterpret_cast(&metabytes[0]), - metabytes.size()); - return; - } - // Actual printing. #if defined(OS_WIN) || defined(OS_MACOSX) document_->RenderPrintedPage(*page, printing_context_->context()); @@ -338,23 +379,26 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) { } // Signal everyone that the page is printed. - owner_->message_loop()->PostTask( - FROM_HERE, - base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::PAGE_DONE, document_, - make_scoped_refptr(page))); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::PAGE_DONE, + document_, + make_scoped_refptr(page))); } void PrintJobWorker::OnFailure() { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); // We may loose our last reference by broadcasting the FAILED event. scoped_refptr handle(owner_); - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::FAILED, document_, - scoped_refptr())); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::FAILED, + document_, + scoped_refptr())); Cancel(); // Makes sure the variables are reinitialized. diff --git a/chromium_src/chrome/browser/printing/print_job_worker.h b/chromium_src/chrome/browser/printing/print_job_worker.h index 2ce01f081acb..a8378bb2353d 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker.h +++ b/chromium_src/chrome/browser/printing/print_job_worker.h @@ -9,12 +9,10 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" +#include "content/public/browser/browser_thread.h" #include "printing/page_number.h" -#include "printing/print_destination_interface.h" -#include "printing/printing_context.h" #include "printing/print_job_constants.h" - -class PrintingUIWebContentsObserver; +#include "printing/printing_context.h" namespace base { class DictionaryValue; @@ -22,39 +20,35 @@ class DictionaryValue; namespace printing { -class PrintedDocument; -class PrintedPage; class PrintJob; class PrintJobWorkerOwner; +class PrintedDocument; +class PrintedPage; // Worker thread code. It manages the PrintingContext, which can be blocking // and/or run a message loop. This is the object that generates most // NOTIFY_PRINT_JOB_EVENT notifications, but they are generated through a // NotificationTask task to be executed from the right thread, the UI thread. // PrintJob always outlives its worker instance. -class PrintJobWorker : public base::Thread { +class PrintJobWorker { public: - explicit PrintJobWorker(PrintJobWorkerOwner* owner); + PrintJobWorker(int render_process_id, + int render_view_id, + PrintJobWorkerOwner* owner); virtual ~PrintJobWorker(); void SetNewOwner(PrintJobWorkerOwner* new_owner); - // Set a destination for print. - // This supercedes the document's rendering destination. - void SetPrintDestination(PrintDestinationInterface* destination); - // Initializes the print settings. If |ask_user_for_settings| is true, a // Print... dialog box will be shown to ask the user his preference. void GetSettings( bool ask_user_for_settings, - scoped_ptr web_contents_observer, int document_page_count, bool has_selection, MarginType margin_type); - // Set the new print settings. This function takes ownership of - // |new_settings|. - void SetSettings(const base::DictionaryValue* const new_settings); + // Set the new print settings. + void SetSettings(scoped_ptr new_settings); // Starts the printing loop. Every pages are printed as soon as the data is // available. Makes sure the new_document is the right one. @@ -71,6 +65,22 @@ class PrintJobWorker : public base::Thread { // This is the only function that can be called in a thread. void Cancel(); + // Returns true if the thread has been started, and not yet stopped. + bool IsRunning() const; + + // Posts the given task to be run. + bool PostTask(const tracked_objects::Location& from_here, + const base::Closure& task); + + // Signals the thread to exit in the near future. + void StopSoon(); + + // Signals the thread to exit and returns once the thread has exited. + void Stop(); + + // Starts the thread. + bool Start(); + protected: // Retrieves the context for testing only. PrintingContext* printing_context() { return printing_context_.get(); } @@ -97,7 +107,6 @@ class PrintJobWorker : public base::Thread { // Required on Mac and Linux. Windows can display UI from non-main threads, // but sticks with this for consistency. void GetSettingsWithUI( - scoped_ptr web_contents_observer, int document_page_count, bool has_selection); @@ -106,9 +115,8 @@ class PrintJobWorker : public base::Thread { // back into the IO thread for GetSettingsDone(). void GetSettingsWithUIDone(PrintingContext::Result result); - // Called on the UI thread to update the print settings. This function takes - // the ownership of |new_settings|. - void UpdatePrintSettings(const base::DictionaryValue* const new_settings); + // Called on the UI thread to update the print settings. + void UpdatePrintSettings(scoped_ptr new_settings); // Reports settings back to owner_. void GetSettingsDone(PrintingContext::Result result); @@ -118,15 +126,15 @@ class PrintJobWorker : public base::Thread { // systems. void UseDefaultSettings(); + // Printing context delegate. + scoped_ptr printing_context_delegate_; + // Information about the printer setting. scoped_ptr printing_context_; // The printed document. Only has read-only access. scoped_refptr document_; - // The print destination, may be NULL. - scoped_refptr destination_; - // The print job owning this worker thread. It is guaranteed to outlive this // object. PrintJobWorkerOwner* owner_; @@ -134,6 +142,12 @@ class PrintJobWorker : public base::Thread { // Current page number to print. PageNumber page_number_; + // Thread to run worker tasks. + base::Thread thread_; + + // Tread-safe pointer to task runner of the |thread_|. + scoped_refptr task_runner_; + // Used to generate a WeakPtr for callbacks. base::WeakPtrFactory weak_factory_; diff --git a/chromium_src/chrome/browser/printing/print_job_worker_owner.cc b/chromium_src/chrome/browser/printing/print_job_worker_owner.cc new file mode 100644 index 000000000000..843ab4616d18 --- /dev/null +++ b/chromium_src/chrome/browser/printing/print_job_worker_owner.cc @@ -0,0 +1,27 @@ +// Copyright 2014 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_job_worker_owner.h" + +#include "base/message_loop/message_loop.h" + +namespace printing { + +PrintJobWorkerOwner::PrintJobWorkerOwner() + : task_runner_(base::MessageLoop::current()->task_runner()) { +} + +PrintJobWorkerOwner::~PrintJobWorkerOwner() { +} + +bool PrintJobWorkerOwner::RunsTasksOnCurrentThread() const { + return task_runner_->RunsTasksOnCurrentThread(); +} + +bool PrintJobWorkerOwner::PostTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + return task_runner_->PostTask(from_here, task); +} + +} // namespace printing diff --git a/chromium_src/chrome/browser/printing/print_job_worker_owner.h b/chromium_src/chrome/browser/printing/print_job_worker_owner.h index 8f9f58509f1f..00a561a39bb6 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker_owner.h +++ b/chromium_src/chrome/browser/printing/print_job_worker_owner.h @@ -10,8 +10,12 @@ namespace base { class MessageLoop; +class SequencedTaskRunner; } +namespace tracked_objects { +class Location; +} namespace printing { @@ -21,6 +25,8 @@ class PrintSettings; class PrintJobWorkerOwner : public base::RefCountedThreadSafe { public: + PrintJobWorkerOwner(); + // Finishes the initialization began by PrintJobWorker::GetSettings(). // Creates a new PrintedDocument if necessary. Solely meant to be called by // PrintJobWorker. @@ -30,19 +36,29 @@ class PrintJobWorkerOwner // Detach the PrintJobWorker associated to this object. virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) = 0; - // Retrieves the message loop that is expected to process GetSettingsDone. - virtual base::MessageLoop* message_loop() = 0; - // Access the current settings. virtual const PrintSettings& settings() const = 0; // Cookie uniquely identifying the PrintedDocument and/or loaded settings. virtual int cookie() const = 0; + // Returns true if the current thread is a thread on which a task + // may be run, and false if no task will be run on the current + // thread. + bool RunsTasksOnCurrentThread() const; + + // Posts the given task to be run. + bool PostTask(const tracked_objects::Location& from_here, + const base::Closure& task); + protected: friend class base::RefCountedThreadSafe; - virtual ~PrintJobWorkerOwner() {} + virtual ~PrintJobWorkerOwner(); + + // Task runner reference. Used to send notifications in the right + // thread. + scoped_refptr task_runner_; }; } // namespace printing diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.cc b/chromium_src/chrome/browser/printing/print_view_manager_base.cc index db77791ba7ef..e2cfedd4a2c2 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.cc +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.cc @@ -24,11 +24,14 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" -#include "grit/generated_resources.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "printing/printed_document.h" #include "ui/base/l10n/l10n_util.h" +#if defined(ENABLE_FULL_PRINTING) +#include "chrome/browser/printing/print_error_dialog.h" +#endif + using base::TimeDelta; using content::BrowserThread; @@ -36,11 +39,6 @@ namespace printing { namespace { -#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) -// Limits memory usage by raster to 64 MiB. -const int kMaxRasterSizeInPixels = 16*1024*1024; -#endif - } // namespace PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) @@ -50,11 +48,10 @@ PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) inside_inner_message_loop_(false), cookie_(0), queue_(g_browser_process->print_job_manager()->queue()) { - DCHECK(queue_); -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) + DCHECK(queue_.get()); +#if !defined(OS_MACOSX) expecting_first_page_ = true; -#endif +#endif // OS_MACOSX printing_enabled_ = true; } @@ -63,10 +60,12 @@ PrintViewManagerBase::~PrintViewManagerBase() { DisconnectFromCurrentPrintJob(); } +#if !defined(DISABLE_BASIC_PRINTING) bool PrintViewManagerBase::PrintNow(bool silent, bool print_background) { return PrintNowInternal(new PrintMsg_PrintPages( routing_id(), silent, print_background)); } +#endif // !DISABLE_BASIC_PRINTING void PrintViewManagerBase::NavigationStopped() { // Cancel the current job, wait for the worker to finish. @@ -117,13 +116,12 @@ void PrintViewManagerBase::OnDidPrintPage( return; } -#if (defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)) || \ - defined(OS_MACOSX) +#if defined(OS_MACOSX) const bool metafile_must_be_valid = true; -#elif defined(OS_POSIX) || defined(WIN_PDF_METAFILE_FOR_PRINTING) +#else const bool metafile_must_be_valid = expecting_first_page_; expecting_first_page_ = false; -#endif +#endif // OS_MACOSX base::SharedMemory shared_buf(params.metafile_data_handle, true); if (metafile_must_be_valid) { @@ -134,7 +132,7 @@ void PrintViewManagerBase::OnDidPrintPage( } } - scoped_ptr metafile(new NativeMetafile); + scoped_ptr metafile(new PdfMetafileSkia); if (metafile_must_be_valid) { if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { NOTREACHED() << "Invalid metafile header"; @@ -143,32 +141,10 @@ void PrintViewManagerBase::OnDidPrintPage( } } -#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) - bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize); - int raster_size = - std::min(params.page_size.GetArea(), kMaxRasterSizeInPixels); - if (big_emf) { - scoped_ptr 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 // OS_WIN && !WIN_PDF_METAFILE_FOR_PRINTING - -#if !defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_WIN) // Update the rendered document. It will send notifications to the listener. document->SetPage(params.page_number, - metafile.release(), -#if defined(OS_WIN) - params.actual_shrink, -#endif // OS_WIN + metafile.PassAs(), params.page_size, params.content_area); @@ -180,19 +156,8 @@ void PrintViewManagerBase::OnDidPrintPage( params.data_size); document->DebugDumpData(bytes, FILE_PATH_LITERAL(".pdf")); - - if (!pdf_to_emf_converter_) - pdf_to_emf_converter_ = PdfToEmfConverter::CreateDefault(); - - const int kPrinterDpi = print_job_->settings().dpi(); - pdf_to_emf_converter_->Start( - bytes, - printing::PdfRenderSettings(params.content_area, kPrinterDpi, true), - base::Bind(&PrintViewManagerBase::OnPdfToEmfConverted, - base::Unretained(this), - params)); } -#endif // !WIN_PDF_METAFILE_FOR_PRINTING +#endif // !OS_WIN } void PrintViewManagerBase::OnPrintingFailed(int cookie) { @@ -386,10 +351,9 @@ void PrintViewManagerBase::DisconnectFromCurrentPrintJob() { // DO NOT wait for the job to finish. ReleasePrintJob(); } -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_MACOSX) expecting_first_page_ = true; -#endif +#endif // OS_MACOSX } void PrintViewManagerBase::PrintingDone(bool success) { @@ -481,12 +445,12 @@ bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) { // The job was initiated by a script. Time to get the corresponding worker // thread. scoped_refptr queued_query = queue_->PopPrinterQuery(cookie); - if (!queued_query) { + if (!queued_query.get()) { NOTREACHED(); return false; } - if (!CreateNewPrintJob(queued_query)) { + if (!CreateNewPrintJob(queued_query.get())) { // Don't kill anything. return false; } @@ -512,8 +476,6 @@ void PrintViewManagerBase::ReleasePrinterQuery() { int cookie = cookie_; cookie_ = 0; - queue_->SetDestination(NULL); - printing::PrintJobManager* print_job_manager = g_browser_process->print_job_manager(); @@ -523,7 +485,7 @@ void PrintViewManagerBase::ReleasePrinterQuery() { scoped_refptr printer_query; printer_query = queue_->PopPrinterQuery(cookie); - if (!printer_query) + if (!printer_query.get()) return; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.h b/chromium_src/chrome/browser/printing/print_view_manager_base.h index 61b0fd440086..f9232fdfe87f 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.h +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.h @@ -23,7 +23,7 @@ class RenderViewHost; namespace printing { class JobEventDetails; -class PdfToEmfConverter; +class MetafilePlayer; class PrintJob; class PrintJobWorkerOwner; class PrintQueriesQueue; @@ -35,10 +35,12 @@ class PrintViewManagerBase : public content::NotificationObserver, public: virtual ~PrintViewManagerBase(); +#if !defined(DISABLE_BASIC_PRINTING) // Prints the current document immediately. Since the rendering is // asynchronous, the actual printing will not be completed on the return of // this function. Returns false if printing is impossible at the moment. virtual bool PrintNow(bool silent, bool print_background); +#endif // !DISABLE_BASIC_PRINTING // PrintedPagesSource implementation. virtual base::string16 RenderSourceName() OVERRIDE; @@ -140,11 +142,10 @@ class PrintViewManagerBase : public content::NotificationObserver, // print settings are being loaded. bool inside_inner_message_loop_; -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_MACOSX) // Set to true when OnDidPrintPage() should be expecting the first page. bool expecting_first_page_; -#endif +#endif // OS_MACOSX // The document cookie of the current PrinterQuery. int cookie_; diff --git a/chromium_src/chrome/browser/printing/printer_query.cc b/chromium_src/chrome/browser/printing/printer_query.cc index 6770e575c69d..6cd11ff067ef 100644 --- a/chromium_src/chrome/browser/printing/printer_query.cc +++ b/chromium_src/chrome/browser/printing/printer_query.cc @@ -10,13 +10,11 @@ #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "chrome/browser/printing/print_job_worker.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" namespace printing { -PrinterQuery::PrinterQuery() - : io_message_loop_(base::MessageLoop::current()), - worker_(new PrintJobWorker(this)), +PrinterQuery::PrinterQuery(int render_process_id, int render_view_id) + : worker_(new PrintJobWorker(render_process_id, render_view_id, this)), is_print_dialog_box_shown_(false), cookie_(PrintSettings::NewCookie()), last_status_(PrintingContext::FAILED) { @@ -57,10 +55,6 @@ PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) { return worker_.release(); } -base::MessageLoop* PrinterQuery::message_loop() { - return io_message_loop_; -} - const PrintSettings& PrinterQuery::settings() const { return settings_; } @@ -71,43 +65,34 @@ int PrinterQuery::cookie() const { void PrinterQuery::GetSettings( GetSettingsAskParam ask_user_for_settings, - scoped_ptr web_contents_observer, int expected_page_count, bool has_selection, MarginType margin_type, const base::Closure& callback) { - DCHECK_EQ(io_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); DCHECK(!is_print_dialog_box_shown_); StartWorker(callback); // Real work is done in PrintJobWorker::GetSettings(). is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER; - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorker::GetSettings, - base::Unretained(worker_.get()), - is_print_dialog_box_shown_, - base::Passed(&web_contents_observer), - expected_page_count, - has_selection, - margin_type)); + worker_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorker::GetSettings, + base::Unretained(worker_.get()), + is_print_dialog_box_shown_, + expected_page_count, + has_selection, + margin_type)); } -void PrinterQuery::SetSettings(const base::DictionaryValue& new_settings, +void PrinterQuery::SetSettings(scoped_ptr new_settings, const base::Closure& callback) { StartWorker(callback); - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorker::SetSettings, - base::Unretained(worker_.get()), - new_settings.DeepCopy())); -} - -void PrinterQuery::SetWorkerDestination( - PrintDestinationInterface* destination) { - worker_->SetPrintDestination(destination); + worker_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorker::SetSettings, + base::Unretained(worker_.get()), + base::Passed(&new_settings))); } void PrinterQuery::StartWorker(const base::Closure& callback) { @@ -115,7 +100,7 @@ void PrinterQuery::StartWorker(const base::Closure& callback) { DCHECK(worker_.get()); // Lazily create the worker thread. There is one worker thread per print job. - if (!worker_->message_loop()) + if (!worker_->IsRunning()) worker_->Start(); callback_ = callback; diff --git a/chromium_src/chrome/browser/printing/printer_query.h b/chromium_src/chrome/browser/printing/printer_query.h index aab49143242a..22af08d7af2f 100644 --- a/chromium_src/chrome/browser/printing/printer_query.h +++ b/chromium_src/chrome/browser/printing/printer_query.h @@ -11,11 +11,8 @@ #include "chrome/browser/printing/print_job_worker_owner.h" #include "printing/print_job_constants.h" -class PrintingUIWebContentsObserver; - namespace base { class DictionaryValue; -class MessageLoop; } namespace printing { @@ -32,13 +29,12 @@ class PrinterQuery : public PrintJobWorkerOwner { ASK_USER, }; - PrinterQuery(); + PrinterQuery(int render_process_id, int render_view_id); // PrintJobWorkerOwner implementation. virtual void GetSettingsDone(const PrintSettings& new_settings, PrintingContext::Result result) OVERRIDE; virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE; - virtual base::MessageLoop* message_loop() OVERRIDE; virtual const PrintSettings& settings() const OVERRIDE; virtual int cookie() const OVERRIDE; @@ -48,19 +44,15 @@ class PrinterQuery : public PrintJobWorkerOwner { // |ask_for_user_settings| is DEFAULTS. void GetSettings( GetSettingsAskParam ask_user_for_settings, - scoped_ptr web_contents_observer, int expected_page_count, bool has_selection, MarginType margin_type, const base::Closure& callback); // Updates the current settings with |new_settings| dictionary values. - void SetSettings(const base::DictionaryValue& new_settings, + void SetSettings(scoped_ptr new_settings, const base::Closure& callback); - // Set a destination for the worker. - void SetWorkerDestination(PrintDestinationInterface* destination); - // Stops the worker thread since the client is done with this object. void StopWorker(); @@ -78,10 +70,6 @@ class PrinterQuery : public PrintJobWorkerOwner { // Lazy create the worker thread. There is one worker thread per print job. void StartWorker(const base::Closure& callback); - // Main message loop reference. Used to send notifications in the right - // thread. - base::MessageLoop* const io_message_loop_; - // All the UI is done in a worker thread because many Win32 print functions // are blocking and enters a message loop without your consent. There is one // worker thread per print job. diff --git a/chromium_src/chrome/browser/printing/printing_message_filter.cc b/chromium_src/chrome/browser/printing/printing_message_filter.cc index d10843fe3c7e..15ca50fba53f 100644 --- a/chromium_src/chrome/browser/printing/printing_message_filter.cc +++ b/chromium_src/chrome/browser/printing/printing_message_filter.cc @@ -8,21 +8,56 @@ #include "base/bind.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/printing/print_job_manager.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" +#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_io_data.h" #include "chrome/common/print_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/child_process_host.h" + +#if defined(ENABLE_FULL_PRINTING) +#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" +#endif + +#if defined(OS_CHROMEOS) +#include + +#include + +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "chrome/browser/printing/print_dialog_cloud.h" +#endif + +#if defined(OS_ANDROID) +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/printing/print_view_manager_basic.h" +#include "printing/printing_context_android.h" +#endif using content::BrowserThread; +namespace printing { + namespace { -void RenderParamsFromPrintSettings(const printing::PrintSettings& settings, +#if defined(OS_CHROMEOS) +typedef std::map SequenceToPathMap; + +struct PrintingSequencePathMap { + SequenceToPathMap map; + int sequence; +}; + +// No locking, only access on the FILE thread. +static base::LazyInstance + g_printing_file_descriptor_map = LAZY_INSTANCE_INITIALIZER; +#endif + +void RenderParamsFromPrintSettings(const PrintSettings& settings, PrintMsg_Print_Params* params) { params->page_size = settings.page_setup_device_units().physical_size(); params->content_size.SetSize( @@ -57,21 +92,45 @@ PrintingMessageFilter::PrintingMessageFilter(int render_process_id) : BrowserMessageFilter(PrintMsgStart), render_process_id_(render_process_id), queue_(g_browser_process->print_job_manager()->queue()) { - DCHECK(queue_); + DCHECK(queue_.get()); } PrintingMessageFilter::~PrintingMessageFilter() { } +void PrintingMessageFilter::OverrideThreadForMessage( + const IPC::Message& message, BrowserThread::ID* thread) { +#if defined(OS_CHROMEOS) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::FILE; + } +#elif defined(OS_ANDROID) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::UI; + } +#endif +} + bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message) #if defined(OS_WIN) IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection) +#endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) #endif IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, OnGetDefaultPrintSettings) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) +#if defined(ENABLE_FULL_PRINTING) + IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel) +#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -88,6 +147,102 @@ void PrintingMessageFilter::OnDuplicateSection( } #endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +void PrintingMessageFilter::OnAllocateTempFileForPrinting( + int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number) { +#if defined(OS_CHROMEOS) + // TODO(thestig): Use |render_view_id| for Chrome OS. + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + temp_file_fd->fd = *sequence_number = -1; + temp_file_fd->auto_close = false; + + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + *sequence_number = g_printing_file_descriptor_map.Get().sequence++; + + base::FilePath path; + if (base::CreateTemporaryFile(&path)) { + int fd = open(path.value().c_str(), O_WRONLY); + if (fd >= 0) { + SequenceToPathMap::iterator it = map->find(*sequence_number); + if (it != map->end()) { + NOTREACHED() << "Sequence number already in use. seq=" << + *sequence_number; + } else { + (*map)[*sequence_number] = path; + temp_file_fd->fd = fd; + temp_file_fd->auto_close = true; + } + } + } +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + // The file descriptor is originally created in & passed from the Android + // side, and it will handle the closing. + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + temp_file_fd->fd = file_descriptor.fd; + temp_file_fd->auto_close = false; +#endif +} + +void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_view_id, + int sequence_number) { +#if defined(OS_CHROMEOS) + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + SequenceToPathMap::iterator it = map->find(sequence_number); + if (it == map->end()) { + NOTREACHED() << "Got a sequence that we didn't pass to the " + "renderer: " << sequence_number; + return; + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::CreatePrintDialogForFile, + this, render_view_id, it->second)); + + // Erase the entry in the map. + map->erase(it); +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + PrintingContextAndroid::PdfWritingDone(file_descriptor.fd, true); + // Invalidate the file descriptor so it doesn't accidentally get reused. + print_view_manager->set_file_descriptor(base::FileDescriptor(-1, false)); +#endif +} +#endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) + +#if defined(OS_CHROMEOS) +void PrintingMessageFilter::CreatePrintDialogForFile( + int render_view_id, + const base::FilePath& path) { + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + print_dialog_cloud::CreatePrintDialogForFile( + wc->GetBrowserContext(), + wc->GetTopLevelNativeWindow(), + path, + wc->GetTitle(), + base::string16(), + std::string("application/pdf")); +} +#endif // defined(OS_CHROMEOS) + content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView( int render_view_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -96,80 +251,41 @@ content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView( return view ? content::WebContents::FromRenderViewHost(view) : NULL; } -struct PrintingMessageFilter::GetPrintSettingsForRenderViewParams { - printing::PrinterQuery::GetSettingsAskParam ask_user_for_settings; - int expected_page_count; - bool has_selection; - printing::MarginType margin_type; -}; - -void PrintingMessageFilter::GetPrintSettingsForRenderView( - int render_view_id, - GetPrintSettingsForRenderViewParams params, - const base::Closure& callback, - scoped_refptr printer_query) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - content::WebContents* wc = GetWebContentsForRenderView(render_view_id); - if (wc) { - scoped_ptr wc_observer( - new PrintingUIWebContentsObserver(wc)); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&printing::PrinterQuery::GetSettings, printer_query, - params.ask_user_for_settings, base::Passed(&wc_observer), - params.expected_page_count, params.has_selection, - params.margin_type, callback)); - } else { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PrintingMessageFilter::OnGetPrintSettingsFailed, this, - callback, printer_query)); - } -} - -void PrintingMessageFilter::OnGetPrintSettingsFailed( - const base::Closure& callback, - scoped_refptr printer_query) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - printer_query->GetSettingsDone(printing::PrintSettings(), - printing::PrintingContext::FAILED); - callback.Run(); -} - void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - scoped_refptr printer_query; - if (false) { + scoped_refptr printer_query; +#if 0 + if (!profile_io_data_->printing_enabled()->GetValue()) { // Reply with NULL query. OnGetDefaultPrintSettingsReply(printer_query, reply_msg); return; } +#endif printer_query = queue_->PopPrinterQuery(0); - if (!printer_query) - printer_query = queue_->CreatePrinterQuery(); + if (!printer_query.get()) { + printer_query = + queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); + } // Loads default settings. This is asynchronous, only the IPC message sender // will hang until the settings are retrieved. - GetPrintSettingsForRenderViewParams params; - params.ask_user_for_settings = printing::PrinterQuery::DEFAULTS; - params.expected_page_count = 0; - params.has_selection = false; - params.margin_type = printing::DEFAULT_MARGINS; - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, - reply_msg->routing_id(), params, - base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, - this, printer_query, reply_msg), - printer_query)); + printer_query->GetSettings( + PrinterQuery::DEFAULTS, + 0, + false, + DEFAULT_MARGINS, + base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, + this, + printer_query, + reply_msg)); } void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( - scoped_refptr printer_query, + scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_Print_Params params; if (!printer_query.get() || - printer_query->last_status() != printing::PrintingContext::OK) { + printer_query->last_status() != PrintingContext::OK) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); @@ -191,43 +307,69 @@ void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( void PrintingMessageFilter::OnScriptedPrint( const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg) { - scoped_refptr printer_query = + scoped_refptr printer_query = queue_->PopPrinterQuery(params.cookie); - if (!printer_query) - printer_query = queue_->CreatePrinterQuery(); - GetPrintSettingsForRenderViewParams settings_params; - settings_params.ask_user_for_settings = printing::PrinterQuery::ASK_USER; - settings_params.expected_page_count = params.expected_pages_count; - settings_params.has_selection = params.has_selection; - settings_params.margin_type = params.margin_type; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, - reply_msg->routing_id(), settings_params, - base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this, - printer_query, reply_msg), - printer_query)); + if (!printer_query.get()) { + printer_query = + queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); + } + printer_query->GetSettings( + PrinterQuery::ASK_USER, + params.expected_pages_count, + params.has_selection, + params.margin_type, + base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, + this, + printer_query, + reply_msg)); } void PrintingMessageFilter::OnScriptedPrintReply( - scoped_refptr printer_query, + scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_PrintPages_Params params; - if (printer_query->last_status() != printing::PrintingContext::OK || +#if defined(OS_ANDROID) + // We need to save the routing ID here because Send method below deletes the + // |reply_msg| before we can get the routing ID for the Android code. + int routing_id = reply_msg->routing_id(); +#endif + if (printer_query->last_status() != PrintingContext::OK || !printer_query->settings().dpi()) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); params.params.document_cookie = printer_query->cookie(); - params.pages = - printing::PageRange::GetPages(printer_query->settings().ranges()); + params.pages = PageRange::GetPages(printer_query->settings().ranges()); } PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); Send(reply_msg); if (params.params.dpi && params.params.document_cookie) { +#if defined(OS_ANDROID) + int file_descriptor; + const base::string16& device_name = printer_query->settings().device_name(); + if (base::StringToInt(device_name, &file_descriptor)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::UpdateFileDescriptor, this, + routing_id, file_descriptor)); + } +#endif queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); } } + +#if defined(OS_ANDROID) +void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + print_view_manager->set_file_descriptor(base::FileDescriptor(fd, false)); +} +#endif + +} // namespace printing diff --git a/chromium_src/chrome/browser/printing/printing_message_filter.h b/chromium_src/chrome/browser/printing/printing_message_filter.h index 8a9d9c2d1ec0..5f437864c176 100644 --- a/chromium_src/chrome/browser/printing/printing_message_filter.h +++ b/chromium_src/chrome/browser/printing/printing_message_filter.h @@ -15,6 +15,8 @@ #endif struct PrintHostMsg_ScriptedPrint_Params; +class Profile; +class ProfileIOData; namespace base { class DictionaryValue; @@ -26,18 +28,21 @@ class WebContents; } namespace printing { -class PrinterQuery; + class PrintJobManager; class PrintQueriesQueue; -} +class PrinterQuery; // This class filters out incoming printing related IPC messages for the // renderer process on the IPC thread. class PrintingMessageFilter : public content::BrowserMessageFilter { public: - explicit PrintingMessageFilter(int render_process_id); + PrintingMessageFilter(int render_process_id); // content::BrowserMessageFilter methods. + virtual void OverrideThreadForMessage( + const IPC::Message& message, + content::BrowserThread::ID* thread) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: @@ -49,6 +54,25 @@ class PrintingMessageFilter : public content::BrowserMessageFilter { base::SharedMemoryHandle* browser_handle); #endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + // Used to ask the browser allocate a temporary file for the renderer + // to fill in resulting PDF in renderer. + void OnAllocateTempFileForPrinting(int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number); + void OnTempFileForPrintingWritten(int render_view_id, int sequence_number); +#endif + +#if defined(OS_CHROMEOS) + void CreatePrintDialogForFile(int render_view_id, const base::FilePath& path); +#endif + +#if defined(OS_ANDROID) + // Updates the file descriptor for the PrintViewManagerBasic of a given + // render_view_id. + void UpdateFileDescriptor(int render_view_id, int fd); +#endif + // Given a render_view_id get the corresponding WebContents. // Must be called on the UI thread. content::WebContents* GetWebContentsForRenderView(int render_view_id); @@ -59,38 +83,33 @@ class PrintingMessageFilter : public content::BrowserMessageFilter { // to base::Bind. struct GetPrintSettingsForRenderViewParams; - // Retrieve print settings. Uses |render_view_id| to get a parent - // for any UI created if needed. - void GetPrintSettingsForRenderView( - int render_view_id, - GetPrintSettingsForRenderViewParams params, - const base::Closure& callback, - scoped_refptr printer_query); - - void OnGetPrintSettingsFailed( - const base::Closure& callback, - scoped_refptr printer_query); - // Get the default print setting. void OnGetDefaultPrintSettings(IPC::Message* reply_msg); - void OnGetDefaultPrintSettingsReply( - scoped_refptr printer_query, - IPC::Message* reply_msg); + void OnGetDefaultPrintSettingsReply(scoped_refptr printer_query, + IPC::Message* reply_msg); // The renderer host have to show to the user the print dialog and returns // the selected print settings. The task is handled by the print worker // thread and the UI thread. The reply occurs on the IO thread. void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg); - void OnScriptedPrintReply( - scoped_refptr printer_query, - IPC::Message* reply_msg); + void OnScriptedPrintReply(scoped_refptr printer_query, + IPC::Message* reply_msg); + +#if defined(ENABLE_FULL_PRINTING) + // Check to see if print preview has been cancelled. + void OnCheckForCancel(int32 preview_ui_id, + int preview_request_id, + bool* cancel); +#endif const int render_process_id_; - scoped_refptr queue_; + scoped_refptr queue_; DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter); }; +} // namespace printing + #endif // CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_ diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc index df9e287cdcbb..4e25da86296b 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc @@ -22,8 +22,7 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "net/base/escape.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "printing/units.h" #include "skia/ext/vector_platform_device_skia.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -65,7 +64,8 @@ bool PrintMsg_Print_Params_IsValid(const PrintMsg_Print_Params& params) { return !params.content_size.IsEmpty() && !params.page_size.IsEmpty() && !params.printable_area.IsEmpty() && params.document_cookie && params.desired_dpi && params.max_shrink && params.min_shrink && - params.dpi && (params.margin_top >= 0) && (params.margin_left >= 0); + params.dpi && (params.margin_top >= 0) && (params.margin_left >= 0) && + params.dpi > kMinDpi && params.document_cookie != 0; } PrintMsg_Print_Params GetCssPrintParams( @@ -409,8 +409,6 @@ class PrepareFrameAndViewForPrint : public blink::WebViewClient, return expected_pages_count_; } - gfx::Size GetPrintCanvasSize() const; - void FinishPrinting(); bool IsLoadingSelection() { @@ -590,12 +588,6 @@ void PrepareFrameAndViewForPrint::CallOnReady() { return on_ready_.Run(); // Can delete |this|. } -gfx::Size PrepareFrameAndViewForPrint::GetPrintCanvasSize() const { - DCHECK(is_printing_started_); - return gfx::Size(web_print_params_.printContentArea.width, - web_print_params_.printContentArea.height); -} - void PrepareFrameAndViewForPrint::RestoreSize() { if (frame()) { blink::WebView* web_view = frame_.GetFrame()->view(); @@ -606,7 +598,7 @@ void PrepareFrameAndViewForPrint::RestoreSize() { } void PrepareFrameAndViewForPrint::FinishPrinting() { - blink::WebFrame* frame = frame_.GetFrame(); + blink::WebLocalFrame* frame = frame_.GetFrame(); if (frame) { blink::WebView* web_view = frame->view(); if (is_printing_started_) { @@ -630,10 +622,15 @@ void PrepareFrameAndViewForPrint::FinishPrinting() { PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view) : content::RenderViewObserver(render_view), content::RenderViewObserverTracker(render_view), + reset_prep_frame_view_(false), is_print_ready_metafile_sent_(false), ignore_css_margins_(false), + is_scripted_printing_blocked_(false), notify_browser_of_print_failure_(true), + print_for_preview_(false), print_node_in_progress_(false), + is_loading_(false), + is_scripted_preview_delayed_(false), weak_ptr_factory_(this) { } @@ -673,11 +670,13 @@ bool PrintWebViewHelper::GetPrintFrame(blink::WebLocalFrame** frame) { return true; } +#if !defined(DISABLE_BASIC_PRINTING) void PrintWebViewHelper::OnPrintPages(bool silent, bool print_background) { blink::WebLocalFrame* frame; if (GetPrintFrame(&frame)) Print(frame, blink::WebNode(), silent, print_background); } +#endif // !DISABLE_BASIC_PRINTING void PrintWebViewHelper::GetPageSizeAndContentAreaFromPageLayout( const PageSizeMargins& page_layout_in_points, @@ -726,9 +725,6 @@ void PrintWebViewHelper::PrintNode(const blink::WebNode& node) { } print_node_in_progress_ = true; - - // Make a copy of the node, in case RenderView::OnContextMenuClosed resets - // its |context_menu_node_|. blink::WebNode duplicate_node(node); Print(duplicate_node.document().frame(), duplicate_node); @@ -783,7 +779,7 @@ void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { break; case FAIL_PRINT: - if (notify_browser_of_print_failure_ && print_pages_params_.get()) { + if (notify_browser_of_print_failure_ && print_pages_params_) { int cookie = print_pages_params_->params.document_cookie; Send(new PrintHostMsg_PrintingFailed(routing_id(), cookie)); } @@ -821,8 +817,7 @@ void PrintWebViewHelper::PrintPages() { page_count)); #endif // !defined(OS_CHROMEOS) - if (!PrintPagesNative(prep_frame_view_->frame(), page_count, - prep_frame_view_->GetPrintCanvasSize())) { + if (!PrintPagesNative(prep_frame_view_->frame(), page_count)) { LOG(ERROR) << "Printing failed."; return DidFinishPrinting(FAIL_PRINT); } @@ -832,10 +827,9 @@ void PrintWebViewHelper::FinishFramePrinting() { prep_frame_view_.reset(); } -#if defined(OS_MACOSX) || defined(OS_WIN) +#if defined(OS_MACOSX) bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size) { + int page_count) { const PrintMsg_PrintPages_Params& params = *print_pages_params_; const PrintMsg_Print_Params& print_params = params.params; @@ -844,20 +838,20 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, if (params.pages.empty()) { for (int i = 0; i < page_count; ++i) { page_params.page_number = i; - PrintPageInternal(page_params, canvas_size, frame); + PrintPageInternal(page_params, frame); } } else { for (size_t i = 0; i < params.pages.size(); ++i) { if (params.pages[i] >= page_count) break; page_params.page_number = params.pages[i]; - PrintPageInternal(page_params, canvas_size, frame); + PrintPageInternal(page_params, frame); } } return true; } -#endif // OS_MACOSX || OS_WIN +#endif // OS_MACOSX // static - Not anonymous so that platform implementations can use it. void PrintWebViewHelper::ComputePageLayoutInPointsForCss( @@ -886,13 +880,6 @@ bool PrintWebViewHelper::InitPrintSettings(bool fit_to_paper_size) { if (!PrintMsg_Print_Params_IsValid(settings.params)) result = false; - if (result && - (settings.params.dpi < kMinDpi || settings.params.document_cookie == 0)) { - // Invalid print page settings. - NOTREACHED(); - result = false; - } - // Reset to default values. ignore_css_margins_ = false; settings.pages.clear(); @@ -904,7 +891,7 @@ bool PrintWebViewHelper::InitPrintSettings(bool fit_to_paper_size) { blink::WebPrintScalingOptionFitToPrintableArea; } - print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); + SetPrintPagesParams(settings); return result; } @@ -923,8 +910,6 @@ bool PrintWebViewHelper::CalculateNumberOfPages(blink::WebLocalFrame* frame, PrepareFrameAndViewForPrint prepare(params, frame, node, ignore_css_margins_); prepare.StartPrinting(); - Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), - params.document_cookie)); *number_of_pages = prepare.GetExpectedPageCount(); return true; } @@ -953,9 +938,8 @@ bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebFrame* frame, new PrintHostMsg_ScriptedPrint(routing_id(), params, &print_settings); msg->EnableMessagePumping(); Send(msg); - print_pages_params_.reset(new PrintMsg_PrintPages_Params(print_settings)); - - print_pages_params_->params.print_scaling_option = scaling_option; + print_settings.params.print_scaling_option = scaling_option; + SetPrintPagesParams(print_settings); return (print_settings.params.dpi && print_settings.params.document_cookie); } @@ -965,9 +949,8 @@ bool PrintWebViewHelper::RenderPagesForPrint(blink::WebLocalFrame* frame, return false; const PrintMsg_PrintPages_Params& params = *print_pages_params_; const PrintMsg_Print_Params& print_params = params.params; - prep_frame_view_.reset( - new PrepareFrameAndViewForPrint(print_params, frame, node, - ignore_css_margins_)); + prep_frame_view_.reset(new PrepareFrameAndViewForPrint( + print_params, frame, node, ignore_css_margins_)); DCHECK(!print_pages_params_->params.selection_only || print_pages_params_->pages.empty()); prep_frame_view_->CopySelectionIfNeeded( @@ -979,24 +962,27 @@ bool PrintWebViewHelper::RenderPagesForPrint(blink::WebLocalFrame* frame, #if defined(OS_POSIX) bool PrintWebViewHelper::CopyMetafileDataToSharedMem( - Metafile* metafile, + PdfMetafileSkia* metafile, base::SharedMemoryHandle* shared_mem_handle) { uint32 buf_size = metafile->GetDataSize(); scoped_ptr shared_buf( content::RenderThread::Get()->HostAllocateSharedMemoryBuffer( buf_size).release()); - if (shared_buf.get()) { + if (shared_buf) { if (shared_buf->Map(buf_size)) { metafile->GetData(shared_buf->memory(), buf_size); - shared_buf->GiveToProcess(base::GetCurrentProcessHandle(), - shared_mem_handle); - return true; + return shared_buf->GiveToProcess(base::GetCurrentProcessHandle(), + shared_mem_handle); } } - NOTREACHED(); return false; } #endif // defined(OS_POSIX) +void PrintWebViewHelper::SetPrintPagesParams( + const PrintMsg_PrintPages_Params& settings) { + print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); +} + } // namespace printing diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper.h b/chromium_src/chrome/renderer/printing/print_web_view_helper.h index 9ae64be20b70..17b8cb05b628 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper.h +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper.h @@ -7,13 +7,15 @@ #include +#include "base/callback.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "content/public/renderer/render_view_observer.h" #include "content/public/renderer/render_view_observer_tracker.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "third_party/WebKit/public/platform/WebCanvas.h" #include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebPrintParams.h" @@ -22,6 +24,7 @@ struct PrintMsg_Print_Params; struct PrintMsg_PrintPage_Params; struct PrintMsg_PrintPages_Params; +struct PrintHostMsg_SetOptionsFromDocument_Params; namespace base { class DictionaryValue; @@ -81,8 +84,10 @@ class PrintWebViewHelper bool user_initiated) OVERRIDE; // Message handlers --------------------------------------------------------- +#if !defined(DISABLE_BASIC_PRINTING) void OnPrintPages(bool silent, bool print_background); void OnPrintingDone(bool success); +#endif // !DISABLE_BASIC_PRINTING // Get |page_size| and |content_area| information from // |page_layout_in_points|. @@ -125,20 +130,22 @@ class PrintWebViewHelper void OnFramePreparedForPrintPages(); void PrintPages(); - bool PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size); + bool PrintPagesNative(blink::WebFrame* frame, int page_count); void FinishFramePrinting(); // Prints the page listed in |params|. #if defined(OS_LINUX) || defined(OS_ANDROID) void PrintPageInternal(const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, blink::WebFrame* frame, - Metafile* metafile); + PdfMetafileSkia* metafile); +#elif defined(OS_WIN) + void PrintPageInternal(const PrintMsg_PrintPage_Params& params, + blink::WebFrame* frame, + PdfMetafileSkia* metafile, + gfx::Size* page_size_in_dpi, + gfx::Rect* content_area_in_dpi); #else void PrintPageInternal(const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, blink::WebFrame* frame); #endif @@ -147,24 +154,15 @@ class PrintWebViewHelper const blink::WebNode& node); // Platform specific helper function for rendering page(s) to |metafile|. -#if defined(OS_WIN) +#if defined(OS_MACOSX) void RenderPage(const PrintMsg_Print_Params& params, int page_number, blink::WebFrame* frame, bool is_preview, - Metafile* metafile, - double* scale_factor, - gfx::Size* page_size_in_dpi, - gfx::Rect* content_area_in_dpi); -#elif defined(OS_MACOSX) - void RenderPage(const PrintMsg_Print_Params& params, - int page_number, - blink::WebFrame* frame, - bool is_preview, - Metafile* metafile, + PdfMetafileSkia* metafile, gfx::Size* page_size, gfx::Rect* content_rect); -#endif // defined(OS_WIN) +#endif // defined(OS_MACOSX) // Renders page contents from |frame| to |content_area| of |canvas|. // |page_number| is zero-based. @@ -179,7 +177,7 @@ class PrintWebViewHelper // Helper methods ----------------------------------------------------------- - bool CopyMetafileDataToSharedMem(Metafile* metafile, + bool CopyMetafileDataToSharedMem(PdfMetafileSkia* metafile, base::SharedMemoryHandle* shared_mem_handle); // Helper method to get page layout in points and fit to page if needed. @@ -195,18 +193,35 @@ class PrintWebViewHelper // Script Initiated Printing ------------------------------------------------ + void SetPrintPagesParams(const PrintMsg_PrintPages_Params& settings); + // WebView used only to print the selection. scoped_ptr prep_frame_view_; + bool reset_prep_frame_view_; scoped_ptr print_pages_params_; bool is_print_ready_metafile_sent_; bool ignore_css_margins_; + // Used for scripted initiated printing blocking. + bool is_scripted_printing_blocked_; + // Let the browser process know of a printing failure. Only set to false when // the failure came from the browser in the first place. bool notify_browser_of_print_failure_; + // True, when printing from print preview. + bool print_for_preview_; + bool print_node_in_progress_; + bool is_loading_; + bool is_scripted_preview_delayed_; + + // Used to fix a race condition where the source is a PDF and print preview + // hangs because RequestPrintPreview is called before DidStopLoading() is + // called. This is a store for the RequestPrintPreview() call and its + // parameters so that it can be invoked after DidStopLoading. + base::Closure on_stop_loading_closure_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc index bf5dfd7039c7..c42467d45ccb 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc @@ -8,10 +8,9 @@ #include "base/memory/scoped_ptr.h" #include "chrome/common/print_messages.h" #include "content/public/renderer/render_thread.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" #include "printing/metafile_skia_wrapper.h" #include "printing/page_size_margins.h" +#include "printing/pdf_metafile_skia.h" #include "skia/ext/platform_device.h" #include "skia/ext/vector_canvas.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -27,9 +26,8 @@ namespace printing { using blink::WebFrame; bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size) { - NativeMetafile metafile; + int page_count) { + PdfMetafileSkia metafile; if (!metafile.Init()) return false; @@ -56,7 +54,7 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, page_params.params = params.params; for (size_t i = 0; i < printed_pages.size(); ++i) { page_params.page_number = printed_pages[i]; - PrintPageInternal(page_params, canvas_size, frame, &metafile); + PrintPageInternal(page_params, frame, &metafile); } // blink::printEnd() for PDF should be called before metafile is closed. @@ -119,9 +117,8 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, void PrintWebViewHelper::PrintPageInternal( const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, WebFrame* frame, - Metafile* metafile) { + PdfMetafileSkia* metafile) { PageSizeMargins page_layout_in_points; double scale_factor = 1.0f; ComputePageLayoutInPointsForCss(frame, params.page_number, params.params, diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm b/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm index ddd91c88c524..9565269a0bcb 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm @@ -10,8 +10,6 @@ #include "base/mac/scoped_nsautorelease_pool.h" #include "base/metrics/histogram.h" #include "chrome/common/print_messages.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" #include "printing/metafile_skia_wrapper.h" #include "printing/page_size_margins.h" #include "skia/ext/platform_device.h" @@ -25,9 +23,8 @@ using blink::WebFrame; void PrintWebViewHelper::PrintPageInternal( const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, WebFrame* frame) { - NativeMetafile metafile; + PdfMetafileSkia metafile; if (!metafile.Init()) return; @@ -54,10 +51,13 @@ void PrintWebViewHelper::PrintPageInternal( Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); } -void PrintWebViewHelper::RenderPage( - const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, - bool is_preview, Metafile* metafile, gfx::Size* page_size, - gfx::Rect* content_rect) { +void PrintWebViewHelper::RenderPage(const PrintMsg_Print_Params& params, + int page_number, + WebFrame* frame, + bool is_preview, + PdfMetafileSkia* metafile, + gfx::Size* page_size, + gfx::Rect* content_rect) { double scale_factor = 1.0f; double webkit_shrink_factor = frame->getPrintPageShrink(page_number); PageSizeMargins page_layout_in_points; diff --git a/vendor/brightray b/vendor/brightray index 4f04cc8121dd..f7f439bdd31c 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 4f04cc8121dd05ed61a8c94edfa66201e12f0abb +Subproject commit f7f439bdd31c901c802108ec903a3bfc0448c3d1