Update printing code to latest

This commit is contained in:
Cheng Zhao 2017-01-31 17:38:05 +09:00 committed by Kevin Sawicki
parent 75627ba6ad
commit ab783413a2
16 changed files with 374 additions and 463 deletions

View file

@ -4,14 +4,20 @@
#include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job.h"
#include <memory>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h" #include "base/threading/worker_pool.h"
#include "base/timer/timer.h" #include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job_worker.h" #include "chrome/browser/printing/print_job_worker.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
@ -24,25 +30,22 @@
#include "printing/pdf_render_settings.h" #include "printing/pdf_render_settings.h"
#endif #endif
using base::TimeDelta; using base::TimeDelta;
namespace printing {
namespace { namespace {
// Helper function to ensure |owner| is valid until at least |callback| returns. // Helper function to ensure |owner| is valid until at least |callback| returns.
void HoldRefCallback(const scoped_refptr<printing::PrintJobWorkerOwner>& owner, void HoldRefCallback(const scoped_refptr<PrintJobWorkerOwner>& owner,
const base::Closure& callback) { const base::Closure& callback) {
callback.Run(); callback.Run();
} }
} // namespace } // namespace
namespace printing {
PrintJob::PrintJob() PrintJob::PrintJob()
: source_(NULL), : source_(nullptr),
worker_(),
settings_(),
is_job_pending_(false), is_job_pending_(false),
is_canceling_(false), is_canceling_(false),
quit_factory_(this) { quit_factory_(this) {
@ -65,12 +68,12 @@ void PrintJob::Initialize(PrintJobWorkerOwner* job,
PrintedPagesSource* source, PrintedPagesSource* source,
int page_count) { int page_count) {
DCHECK(!source_); DCHECK(!source_);
DCHECK(!worker_.get()); DCHECK(!worker_);
DCHECK(!is_job_pending_); DCHECK(!is_job_pending_);
DCHECK(!is_canceling_); DCHECK(!is_canceling_);
DCHECK(!document_.get()); DCHECK(!document_.get());
source_ = source; source_ = source;
worker_.reset(job->DetachWorker(this)); worker_ = job->DetachWorker(this);
settings_ = job->settings(); settings_ = job->settings();
PrintedDocument* new_doc = PrintedDocument* new_doc =
@ -90,15 +93,9 @@ void PrintJob::Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) { const content::NotificationDetails& details) {
DCHECK(RunsTasksOnCurrentThread()); DCHECK(RunsTasksOnCurrentThread());
switch (type) { DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr()); OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
break;
}
default: {
break;
}
}
} }
void PrintJob::GetSettingsDone(const PrintSettings& new_settings, void PrintJob::GetSettingsDone(const PrintSettings& new_settings,
@ -106,9 +103,10 @@ void PrintJob::GetSettingsDone(const PrintSettings& new_settings,
NOTREACHED(); NOTREACHED();
} }
PrintJobWorker* PrintJob::DetachWorker(PrintJobWorkerOwner* new_owner) { std::unique_ptr<PrintJobWorker> PrintJob::DetachWorker(
PrintJobWorkerOwner* new_owner) {
NOTREACHED(); NOTREACHED();
return NULL; return nullptr;
} }
const PrintSettings& PrintJob::settings() const { const PrintSettings& PrintJob::settings() const {
@ -116,23 +114,22 @@ const PrintSettings& PrintJob::settings() const {
} }
int PrintJob::cookie() const { int PrintJob::cookie() const {
// Always use an invalid cookie in this case.
if (!document_.get()) if (!document_.get())
// Always use an invalid cookie in this case.
return 0; return 0;
return document_->cookie(); return document_->cookie();
} }
void PrintJob::StartPrinting() { void PrintJob::StartPrinting() {
DCHECK(RunsTasksOnCurrentThread()); DCHECK(RunsTasksOnCurrentThread());
DCHECK(worker_->IsRunning()); if (!worker_->IsRunning() || is_job_pending_) {
DCHECK(!is_job_pending_); NOTREACHED();
if (!worker_->IsRunning() || is_job_pending_)
return; return;
}
// Real work is done in PrintJobWorker::StartPrinting(). // Real work is done in PrintJobWorker::StartPrinting().
worker_->PostTask(FROM_HERE, worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback, base::Bind(&HoldRefCallback, make_scoped_refptr(this),
make_scoped_refptr(this),
base::Bind(&PrintJobWorker::StartPrinting, base::Bind(&PrintJobWorker::StartPrinting,
base::Unretained(worker_.get()), base::Unretained(worker_.get()),
base::RetainedRef(document_)))); base::RetainedRef(document_))));
@ -141,7 +138,7 @@ void PrintJob::StartPrinting() {
// Tell everyone! // Tell everyone!
scoped_refptr<JobEventDetails> details( scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), NULL)); new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), nullptr));
content::NotificationService::current()->Notify( content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(this), content::Source<PrintJob>(this),
@ -165,7 +162,8 @@ void PrintJob::Stop() {
ControlledWorkerShutdown(); ControlledWorkerShutdown();
} else { } else {
// Flush the cached document. // Flush the cached document.
UpdatePrintedDocument(NULL); is_job_pending_ = false;
UpdatePrintedDocument(nullptr);
} }
} }
@ -185,7 +183,7 @@ void PrintJob::Cancel() {
} }
// Make sure a Cancel() is broadcast. // Make sure a Cancel() is broadcast.
scoped_refptr<JobEventDetails> details( scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::FAILED, NULL, NULL)); new JobEventDetails(JobEventDetails::FAILED, nullptr, nullptr));
content::NotificationService::current()->Notify( content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(this), content::Source<PrintJob>(this),
@ -210,7 +208,7 @@ bool PrintJob::FlushJob(base::TimeDelta timeout) {
} }
void PrintJob::DisconnectSource() { void PrintJob::DisconnectSource() {
source_ = NULL; source_ = nullptr;
if (document_.get()) if (document_.get())
document_->DisconnectSource(); document_->DisconnectSource();
} }
@ -237,8 +235,10 @@ class PrintJob::PdfToEmfState {
void Start(const scoped_refptr<base::RefCountedMemory>& data, void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings, const PdfRenderSettings& conversion_settings,
bool print_text_with_gdi,
const PdfToEmfConverter::StartCallback& start_callback) { const PdfToEmfConverter::StartCallback& start_callback) {
converter_->Start(data, conversion_settings, start_callback); converter_->Start(data, conversion_settings, print_text_with_gdi,
start_callback);
} }
void GetMorePages( void GetMorePages(
@ -273,48 +273,51 @@ class PrintJob::PdfToEmfState {
std::unique_ptr<PdfToEmfConverter> converter_; std::unique_ptr<PdfToEmfConverter> converter_;
}; };
void PrintJob::AppendPrintedPage(int page_number) {
pdf_page_mapping_.push_back(page_number);
}
void PrintJob::StartPdfToEmfConversion( void PrintJob::StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes, const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size, const gfx::Size& page_size,
const gfx::Rect& content_area) { const gfx::Rect& content_area,
DCHECK(!ptd_to_emf_state_.get()); bool print_text_with_gdi) {
ptd_to_emf_state_.reset(new PdfToEmfState(page_size, content_area)); DCHECK(!pdf_to_emf_state_);
pdf_to_emf_state_ = base::MakeUnique<PdfToEmfState>(page_size, content_area);
const int kPrinterDpi = settings().dpi(); const int kPrinterDpi = settings().dpi();
ptd_to_emf_state_->Start( pdf_to_emf_state_->Start(
bytes, bytes, PdfRenderSettings(content_area, kPrinterDpi, true),
printing::PdfRenderSettings(content_area, kPrinterDpi, true), print_text_with_gdi, base::Bind(&PrintJob::OnPdfToEmfStarted, this));
base::Bind(&PrintJob::OnPdfToEmfStarted, this));
} }
void PrintJob::OnPdfToEmfStarted(int page_count) { void PrintJob::OnPdfToEmfStarted(int page_count) {
if (page_count <= 0) { if (page_count <= 0) {
ptd_to_emf_state_.reset(); pdf_to_emf_state_.reset();
Cancel(); Cancel();
return; return;
} }
ptd_to_emf_state_->set_page_count(page_count); pdf_to_emf_state_->set_page_count(page_count);
ptd_to_emf_state_->GetMorePages( pdf_to_emf_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this)); base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
} }
void PrintJob::OnPdfToEmfPageConverted(int page_number, void PrintJob::OnPdfToEmfPageConverted(int page_number,
float scale_factor, float scale_factor,
std::unique_ptr<MetafilePlayer> emf) { std::unique_ptr<MetafilePlayer> emf) {
DCHECK(ptd_to_emf_state_); DCHECK(pdf_to_emf_state_);
if (!document_.get() || !emf) { if (!document_.get() || !emf || page_number < 0 ||
ptd_to_emf_state_.reset(); static_cast<size_t>(page_number) >= pdf_page_mapping_.size()) {
pdf_to_emf_state_.reset();
Cancel(); Cancel();
return; return;
} }
// Update the rendered document. It will send notifications to the listener. // Update the rendered document. It will send notifications to the listener.
document_->SetPage(page_number, document_->SetPage(pdf_page_mapping_[page_number], std::move(emf),
std::move(emf), scale_factor, pdf_to_emf_state_->page_size(),
scale_factor, pdf_to_emf_state_->content_area());
ptd_to_emf_state_->page_size(),
ptd_to_emf_state_->content_area());
ptd_to_emf_state_->GetMorePages( pdf_to_emf_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this)); base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
} }
@ -326,16 +329,14 @@ void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
document_ = new_document; document_ = new_document;
if (document_.get()) { if (document_.get())
settings_ = document_->settings(); settings_ = document_->settings();
}
if (worker_) { if (worker_) {
DCHECK(!is_job_pending_); DCHECK(!is_job_pending_);
// Sync the document with the worker. // Sync the document with the worker.
worker_->PostTask(FROM_HERE, worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback, base::Bind(&HoldRefCallback, make_scoped_refptr(this),
make_scoped_refptr(this),
base::Bind(&PrintJobWorker::OnDocumentChanged, base::Bind(&PrintJobWorker::OnDocumentChanged,
base::Unretained(worker_.get()), base::Unretained(worker_.get()),
base::RetainedRef(document_)))); base::RetainedRef(document_))));
@ -371,9 +372,9 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
} }
case JobEventDetails::PAGE_DONE: case JobEventDetails::PAGE_DONE:
#if defined(OS_WIN) #if defined(OS_WIN)
ptd_to_emf_state_->OnPageProcessed( pdf_to_emf_state_->OnPageProcessed(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this)); base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
#endif // OS_WIN #endif // defined(OS_WIN)
break; break;
default: { default: {
NOTREACHED(); NOTREACHED();
@ -391,7 +392,7 @@ void PrintJob::OnDocumentDone() {
Stop(); Stop();
scoped_refptr<JobEventDetails> details( scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::JOB_DONE, document_.get(), NULL)); new JobEventDetails(JobEventDetails::JOB_DONE, document_.get(), nullptr));
content::NotificationService::current()->Notify( content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(this), content::Source<PrintJob>(this),
@ -419,8 +420,7 @@ void PrintJob::ControlledWorkerShutdown() {
// to wait on the thread to quit before continuing. // to wait on the thread to quit before continuing.
if (worker_->IsRunning()) { if (worker_->IsRunning()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, FROM_HERE, base::Bind(&PrintJob::ControlledWorkerShutdown, this),
base::Bind(&PrintJob::ControlledWorkerShutdown, this),
base::TimeDelta::FromMilliseconds(100)); base::TimeDelta::FromMilliseconds(100));
return; return;
} }
@ -437,7 +437,7 @@ void PrintJob::ControlledWorkerShutdown() {
is_job_pending_ = false; is_job_pending_ = false;
registrar_.RemoveAll(); registrar_.RemoveAll();
UpdatePrintedDocument(NULL); UpdatePrintedDocument(nullptr);
} }
void PrintJob::HoldUntilStopIsCalled() { void PrintJob::HoldUntilStopIsCalled() {

View file

@ -6,15 +6,15 @@
#define CHROME_BROWSER_PRINTING_PRINT_JOB_H_ #define CHROME_BROWSER_PRINTING_PRINT_JOB_H_
#include <memory> #include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h" #include "build/build_config.h"
#include "chrome/browser/printing/print_job_worker_owner.h" #include "chrome/browser/printing/print_job_worker_owner.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
class Thread;
namespace base { namespace base {
class RefCountedMemory; class RefCountedMemory;
} }
@ -49,16 +49,17 @@ class PrintJob : public PrintJobWorkerOwner,
int page_count); int page_count);
// content::NotificationObserver implementation. // content::NotificationObserver implementation.
virtual void Observe(int type, void Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// PrintJobWorkerOwner implementation. // PrintJobWorkerOwner implementation.
virtual void GetSettingsDone(const PrintSettings& new_settings, void GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) override; PrintingContext::Result result) override;
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) override; std::unique_ptr<PrintJobWorker> DetachWorker(
virtual const PrintSettings& settings() const override; PrintJobWorkerOwner* new_owner) override;
virtual int cookie() const override; const PrintSettings& settings() const override;
int cookie() const override;
// Starts the actual printing. Signals the worker that it should begin to // Starts the actual printing. Signals the worker that it should begin to
// spool as soon as data is available. // spool as soon as data is available.
@ -91,23 +92,21 @@ class PrintJob : public PrintJobWorkerOwner,
PrintedDocument* document() const; PrintedDocument* document() const;
#if defined(OS_WIN) #if defined(OS_WIN)
// Let the PrintJob know the 0-based |page_number| of a given printed page.
void AppendPrintedPage(int page_number);
void StartPdfToEmfConversion( void StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes, const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size, const gfx::Size& page_size,
const gfx::Rect& content_area); const gfx::Rect& content_area,
bool print_text_with_gdi);
void OnPdfToEmfStarted(int page_count); #endif // defined(OS_WIN)
void OnPdfToEmfPageConverted(int page_number,
float scale_factor,
std::unique_ptr<MetafilePlayer> emf);
#endif // OS_WIN
protected: protected:
virtual ~PrintJob(); ~PrintJob() override;
private: private:
// Updates document_ to a new instance. // Updates |document_| to a new instance.
void UpdatePrintedDocument(PrintedDocument* new_document); void UpdatePrintedDocument(PrintedDocument* new_document);
// Processes a NOTIFY_PRINT_JOB_EVENT notification. // Processes a NOTIFY_PRINT_JOB_EVENT notification.
@ -126,6 +125,13 @@ class PrintJob : public PrintJobWorkerOwner,
void HoldUntilStopIsCalled(); void HoldUntilStopIsCalled();
#if defined(OS_WIN)
void OnPdfToEmfStarted(int page_count);
void OnPdfToEmfPageConverted(int page_number,
float scale_factor,
std::unique_ptr<MetafilePlayer> emf);
#endif // defined(OS_WIN)
content::NotificationRegistrar registrar_; content::NotificationRegistrar registrar_;
// Source that generates the PrintedPage's (i.e. a WebContents). It will be // Source that generates the PrintedPage's (i.e. a WebContents). It will be
@ -152,8 +158,9 @@ class PrintJob : public PrintJobWorkerOwner,
#if defined(OS_WIN) #if defined(OS_WIN)
class PdfToEmfState; class PdfToEmfState;
std::unique_ptr<PdfToEmfState> ptd_to_emf_state_; std::unique_ptr<PdfToEmfState> pdf_to_emf_state_;
#endif // OS_WIN std::vector<int> pdf_page_mapping_;
#endif // defined(OS_WIN)
// Used at shutdown so that we can quit a nested message loop. // Used at shutdown so that we can quit a nested message loop.
base::WeakPtrFactory<PrintJob> quit_factory_; base::WeakPtrFactory<PrintJob> quit_factory_;

View file

@ -35,7 +35,7 @@ scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
for (PrinterQueries::iterator itr = queued_queries_.begin(); for (PrinterQueries::iterator itr = queued_queries_.begin();
itr != queued_queries_.end(); ++itr) { itr != queued_queries_.end(); ++itr) {
if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) { if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
scoped_refptr<printing::PrinterQuery> current_query(*itr); scoped_refptr<PrinterQuery> current_query(*itr);
queued_queries_.erase(itr); queued_queries_.erase(itr);
DCHECK(current_query->is_valid()); DCHECK(current_query->is_valid());
return current_query; return current_query;
@ -46,10 +46,9 @@ scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery( scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery(
int render_process_id, int render_process_id,
int render_view_id) { int render_frame_id) {
scoped_refptr<PrinterQuery> job = return make_scoped_refptr(
new printing::PrinterQuery(render_process_id, render_view_id); new PrinterQuery(render_process_id, render_frame_id));
return job;
} }
void PrintQueriesQueue::Shutdown() { void PrintQueriesQueue::Shutdown() {
@ -76,14 +75,14 @@ PrintJobManager::~PrintJobManager() {
} }
scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() { scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!queue_.get()) if (!queue_.get())
queue_ = new PrintQueriesQueue(); queue_ = new PrintQueriesQueue();
return queue_; return queue_;
} }
void PrintJobManager::Shutdown() { void PrintJobManager::Shutdown() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(!is_shutdown_); DCHECK(!is_shutdown_);
is_shutdown_ = true; is_shutdown_ = true;
registrar_.RemoveAll(); registrar_.RemoveAll();
@ -94,7 +93,7 @@ void PrintJobManager::Shutdown() {
} }
void PrintJobManager::StopJobs(bool wait_for_finish) { void PrintJobManager::StopJobs(bool wait_for_finish) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Copy the array since it can be modified in transit. // Copy the array since it can be modified in transit.
PrintJobs to_stop; PrintJobs to_stop;
to_stop.swap(current_jobs_); to_stop.swap(current_jobs_);
@ -111,18 +110,11 @@ void PrintJobManager::StopJobs(bool wait_for_finish) {
void PrintJobManager::Observe(int type, void PrintJobManager::Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) { const content::NotificationDetails& details) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
switch (type) { DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
OnPrintJobEvent(content::Source<PrintJob>(source).ptr(), OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
*content::Details<JobEventDetails>(details).ptr()); *content::Details<JobEventDetails>(details).ptr());
break;
}
default: {
NOTREACHED();
break;
}
}
} }
void PrintJobManager::OnPrintJobEvent( void PrintJobManager::OnPrintJobEvent(

View file

@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
@ -37,7 +38,7 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe<PrintQueriesQueue> {
// Creates new query. // Creates new query.
scoped_refptr<PrinterQuery> CreatePrinterQuery(int render_process_id, scoped_refptr<PrinterQuery> CreatePrinterQuery(int render_process_id,
int render_view_id); int render_frame_id);
void Shutdown(); void Shutdown();
@ -58,15 +59,15 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe<PrintQueriesQueue> {
class PrintJobManager : public content::NotificationObserver { class PrintJobManager : public content::NotificationObserver {
public: public:
PrintJobManager(); PrintJobManager();
virtual ~PrintJobManager(); ~PrintJobManager() override;
// On browser quit, we should wait to have the print job finished. // On browser quit, we should wait to have the print job finished.
void Shutdown(); void Shutdown();
// content::NotificationObserver // content::NotificationObserver
virtual void Observe(int type, void Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// Returns queries queue. Never returns NULL. Must be called on Browser UI // Returns queries queue. Never returns NULL. Must be called on Browser UI
// Thread. Reference could be stored and used from any thread. // Thread. Reference could be stored and used from any thread.

View file

@ -4,19 +4,25 @@
#include "chrome/browser/printing/print_job_worker.h" #include "chrome/browser/printing/print_job_worker.h"
#include <memory>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/values.h" #include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "printing/print_job_constants.h" #include "printing/print_job_constants.h"
#include "printing/printed_document.h" #include "printing/printed_document.h"
@ -31,41 +37,45 @@ namespace printing {
namespace { namespace {
// Helper function to ensure |owner| is valid until at least |callback| returns. // Helper function to ensure |owner| is valid until at least |callback| returns.
void HoldRefCallback(const scoped_refptr<printing::PrintJobWorkerOwner>& owner, void HoldRefCallback(const scoped_refptr<PrintJobWorkerOwner>& owner,
const base::Closure& callback) { const base::Closure& callback) {
callback.Run(); callback.Run();
} }
class PrintingContextDelegate : public PrintingContext::Delegate { class PrintingContextDelegate : public PrintingContext::Delegate {
public: public:
PrintingContextDelegate(int render_process_id, int render_view_id); PrintingContextDelegate(int render_process_id, int render_frame_id);
virtual ~PrintingContextDelegate(); ~PrintingContextDelegate() override;
virtual gfx::NativeView GetParentView() override; gfx::NativeView GetParentView() override;
virtual std::string GetAppLocale() override; std::string GetAppLocale() override;
// Not exposed to PrintingContext::Delegate because of dependency issues.
content::WebContents* GetWebContents();
private: private:
int render_process_id_; const int render_process_id_;
int render_view_id_; const int render_frame_id_;
}; };
PrintingContextDelegate::PrintingContextDelegate(int render_process_id, PrintingContextDelegate::PrintingContextDelegate(int render_process_id,
int render_view_id) int render_frame_id)
: render_process_id_(render_process_id), : render_process_id_(render_process_id),
render_view_id_(render_view_id) { render_frame_id_(render_frame_id) {}
}
PrintingContextDelegate::~PrintingContextDelegate() { PrintingContextDelegate::~PrintingContextDelegate() {
} }
gfx::NativeView PrintingContextDelegate::GetParentView() { gfx::NativeView PrintingContextDelegate::GetParentView() {
content::WebContents* wc = GetWebContents();
return wc ? wc->GetNativeView() : nullptr;
}
content::WebContents* PrintingContextDelegate::GetWebContents() {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::RenderViewHost* view = auto* rfh =
content::RenderViewHost::FromID(render_process_id_, render_view_id_); content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!view) return rfh ? content::WebContents::FromRenderFrameHost(rfh) : nullptr;
return NULL;
content::WebContents* wc = content::WebContents::FromRenderViewHost(view);
return wc ? wc->GetNativeView() : NULL;
} }
std::string PrintingContextDelegate::GetAppLocale() { std::string PrintingContextDelegate::GetAppLocale() {
@ -84,17 +94,24 @@ void NotificationCallback(PrintJobWorkerOwner* print_job,
content::Details<JobEventDetails>(details)); content::Details<JobEventDetails>(details));
} }
void PostOnOwnerThread(const scoped_refptr<PrintJobWorkerOwner>& owner,
const PrintingContext::PrintSettingsCallback& callback,
PrintingContext::Result result) {
owner->PostTask(FROM_HERE, base::Bind(&HoldRefCallback, owner,
base::Bind(callback, result)));
}
} // namespace } // namespace
PrintJobWorker::PrintJobWorker(int render_process_id, PrintJobWorker::PrintJobWorker(int render_process_id,
int render_view_id, int render_frame_id,
PrintJobWorkerOwner* owner) PrintJobWorkerOwner* owner)
: owner_(owner), thread_("Printing_Worker"), weak_factory_(this) { : owner_(owner), thread_("Printing_Worker"), weak_factory_(this) {
// The object is created in the IO thread. // The object is created in the IO thread.
DCHECK(owner_->RunsTasksOnCurrentThread()); DCHECK(owner_->RunsTasksOnCurrentThread());
printing_context_delegate_.reset( printing_context_delegate_ = base::MakeUnique<PrintingContextDelegate>(
new PrintingContextDelegate(render_process_id, render_view_id)); render_process_id, render_frame_id);
printing_context_ = PrintingContext::Create(printing_context_delegate_.get()); printing_context_ = PrintingContext::Create(printing_context_delegate_.get());
} }
@ -111,11 +128,12 @@ void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) {
owner_ = new_owner; owner_ = new_owner;
} }
void PrintJobWorker::GetSettings( void PrintJobWorker::GetSettings(bool ask_user_for_settings,
bool ask_user_for_settings, int document_page_count,
int document_page_count, bool has_selection,
bool has_selection, MarginType margin_type,
MarginType margin_type) { bool is_scripted,
bool is_modifiable) {
DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK_EQ(page_number_, PageNumber::npos()); DCHECK_EQ(page_number_, PageNumber::npos());
@ -126,6 +144,7 @@ void PrintJobWorker::GetSettings(
// should happen on the same thread. See http://crbug.com/73466 // should happen on the same thread. See http://crbug.com/73466
// MessageLoop::current()->SetNestableTasksAllowed(true); // MessageLoop::current()->SetNestableTasksAllowed(true);
printing_context_->set_margin_type(margin_type); printing_context_->set_margin_type(margin_type);
printing_context_->set_is_modifiable(is_modifiable);
// When we delegate to a destination, we don't ask the user for settings. // When we delegate to a destination, we don't ask the user for settings.
// TODO(mad): Ask the destination for settings. // TODO(mad): Ask the destination for settings.
@ -136,7 +155,8 @@ void PrintJobWorker::GetSettings(
base::Bind(&PrintJobWorker::GetSettingsWithUI, base::Bind(&PrintJobWorker::GetSettingsWithUI,
base::Unretained(this), base::Unretained(this),
document_page_count, document_page_count,
has_selection))); has_selection,
is_scripted)));
} else { } else {
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, BrowserThread::UI, FROM_HERE,
@ -188,23 +208,16 @@ void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) {
void PrintJobWorker::GetSettingsWithUI( void PrintJobWorker::GetSettingsWithUI(
int document_page_count, int document_page_count,
bool has_selection) { bool has_selection,
bool is_scripted) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
printing_context_->AskUserForSettings(
document_page_count,
has_selection,
false,
base::Bind(&PrintJobWorker::GetSettingsWithUIDone,
base::Unretained(this)));
}
void PrintJobWorker::GetSettingsWithUIDone(PrintingContext::Result result) { // weak_factory_ creates pointers valid only on owner_ thread.
PostTask(FROM_HERE, printing_context_->AskUserForSettings(
base::Bind(&HoldRefCallback, document_page_count, has_selection, is_scripted,
make_scoped_refptr(owner_), base::Bind(&PostOnOwnerThread, make_scoped_refptr(owner_),
base::Bind(&PrintJobWorker::GetSettingsDone, base::Bind(&PrintJobWorker::GetSettingsDone,
base::Unretained(this), weak_factory_.GetWeakPtr())));
result)));
} }
void PrintJobWorker::UseDefaultSettings() { void PrintJobWorker::UseDefaultSettings() {
@ -225,8 +238,6 @@ void PrintJobWorker::StartPrinting(PrintedDocument* new_document) {
base::string16 document_name = base::string16 document_name =
printing::SimplifyDocumentTitle(document_->name()); printing::SimplifyDocumentTitle(document_->name());
if (document_name.empty()) {
}
PrintingContext::Result result = PrintingContext::Result result =
printing_context_->NewDocument(document_name); printing_context_->NewDocument(document_name);
if (result != PrintingContext::OK) { if (result != PrintingContext::OK) {
@ -352,10 +363,11 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) {
DCHECK_NE(page_number_, PageNumber::npos()); DCHECK_NE(page_number_, PageNumber::npos());
// Signal everyone that the page is about to be printed. // Signal everyone that the page is about to be printed.
owner_->PostTask(FROM_HERE, owner_->PostTask(
base::Bind(&NotificationCallback, base::RetainedRef(owner_), FROM_HERE,
JobEventDetails::NEW_PAGE, base::RetainedRef(document_), base::Bind(&NotificationCallback, base::RetainedRef(owner_),
base::RetainedRef(page))); JobEventDetails::NEW_PAGE, base::RetainedRef(document_),
base::RetainedRef(page)));
// Preprocess. // Preprocess.
if (printing_context_->NewPage() != PrintingContext::OK) { if (printing_context_->NewPage() != PrintingContext::OK) {
@ -390,11 +402,10 @@ void PrintJobWorker::OnFailure() {
// We may loose our last reference by broadcasting the FAILED event. // We may loose our last reference by broadcasting the FAILED event.
scoped_refptr<PrintJobWorkerOwner> handle(owner_); scoped_refptr<PrintJobWorkerOwner> handle(owner_);
owner_->PostTask( owner_->PostTask(FROM_HERE,
FROM_HERE, base::Bind(&NotificationCallback, base::RetainedRef(owner_),
base::Bind(&NotificationCallback, base::RetainedRef(owner_), JobEventDetails::FAILED,
JobEventDetails::FAILED, base::RetainedRef(document_), nullptr));
base::RetainedRef(document_), nullptr));
Cancel(); Cancel();
// Makes sure the variables are reinitialized. // Makes sure the variables are reinitialized.

View file

@ -7,9 +7,11 @@
#include <memory> #include <memory>
#include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "chrome/browser/printing/printer_query.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "printing/page_number.h" #include "printing/page_number.h"
#include "printing/print_job_constants.h" #include "printing/print_job_constants.h"
@ -34,19 +36,22 @@ class PrintedPage;
class PrintJobWorker { class PrintJobWorker {
public: public:
PrintJobWorker(int render_process_id, PrintJobWorker(int render_process_id,
int render_view_id, int render_frame_id,
PrintJobWorkerOwner* owner); PrintJobWorkerOwner* owner);
virtual ~PrintJobWorker(); virtual ~PrintJobWorker();
void SetNewOwner(PrintJobWorkerOwner* new_owner); void SetNewOwner(PrintJobWorkerOwner* new_owner);
// Initializes the print settings. If |ask_user_for_settings| is true, a // Initializes the print settings. If |ask_user_for_settings| is true, a
// Print... dialog box will be shown to ask the user his preference. // Print... dialog box will be shown to ask the user their preference.
void GetSettings( // |is_scripted| should be true for calls coming straight from window.print().
bool ask_user_for_settings, // |is_modifiable| implies HTML and not other formats like PDF.
int document_page_count, void GetSettings(bool ask_user_for_settings,
bool has_selection, int document_page_count,
MarginType margin_type); bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable);
// Set the new print settings. // Set the new print settings.
void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings); void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings);
@ -109,12 +114,8 @@ class PrintJobWorker {
// but sticks with this for consistency. // but sticks with this for consistency.
void GetSettingsWithUI( void GetSettingsWithUI(
int document_page_count, int document_page_count,
bool has_selection); bool has_selection,
bool is_scripted);
// The callback used by PrintingContext::GetSettingsWithUI() to notify this
// object that the print settings are set. This is needed in order to bounce
// back into the IO thread for GetSettingsDone().
void GetSettingsWithUIDone(PrintingContext::Result result);
// Called on the UI thread to update the print settings. // Called on the UI thread to update the print settings.
void UpdatePrintSettings(std::unique_ptr<base::DictionaryValue> new_settings); void UpdatePrintSettings(std::unique_ptr<base::DictionaryValue> new_settings);

View file

@ -4,13 +4,14 @@
#include "chrome/browser/printing/print_job_worker_owner.h" #include "chrome/browser/printing/print_job_worker_owner.h"
#include "base/message_loop/message_loop.h" #include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
namespace printing { namespace printing {
PrintJobWorkerOwner::PrintJobWorkerOwner() PrintJobWorkerOwner::PrintJobWorkerOwner()
: task_runner_(base::MessageLoop::current()->task_runner()) { : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
}
PrintJobWorkerOwner::~PrintJobWorkerOwner() { PrintJobWorkerOwner::~PrintJobWorkerOwner() {
} }

View file

@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__ #ifndef CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__ #define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
#include <memory>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "printing/printing_context.h" #include "printing/printing_context.h"
@ -34,7 +36,8 @@ class PrintJobWorkerOwner
PrintingContext::Result result) = 0; PrintingContext::Result result) = 0;
// Detach the PrintJobWorker associated to this object. // Detach the PrintJobWorker associated to this object.
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) = 0; virtual std::unique_ptr<PrintJobWorker> DetachWorker(
PrintJobWorkerOwner* new_owner) = 0;
// Access the current settings. // Access the current settings.
virtual const PrintSettings& settings() const = 0; virtual const PrintSettings& settings() const = 0;

View file

@ -11,6 +11,7 @@
#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/printing/printer_query.h"
#include "chrome/common/print_messages.h" #include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "printing/page_size_margins.h" #include "printing/page_size_margins.h"
@ -116,8 +117,8 @@ void PrintPreviewMessageHandler::PrintToPDF(
options.GetInteger(printing::kPreviewRequestID, &request_id); options.GetInteger(printing::kPreviewRequestID, &request_id);
print_to_pdf_callback_map_[request_id] = callback; print_to_pdf_callback_map_[request_id] = callback;
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), options)); rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
} }
void PrintPreviewMessageHandler::RunPrintToPDFCallback( void PrintPreviewMessageHandler::RunPrintToPDFCallback(

View file

@ -4,6 +4,9 @@
#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/printing/printer_query.h"
#include <memory>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
@ -13,8 +16,8 @@
namespace printing { namespace printing {
PrinterQuery::PrinterQuery(int render_process_id, int render_view_id) PrinterQuery::PrinterQuery(int render_process_id, int render_frame_id)
: worker_(new PrintJobWorker(render_process_id, render_view_id, this)), : worker_(new PrintJobWorker(render_process_id, render_frame_id, this)),
is_print_dialog_box_shown_(false), is_print_dialog_box_shown_(false),
cookie_(PrintSettings::NewCookie()), cookie_(PrintSettings::NewCookie()),
last_status_(PrintingContext::FAILED) { last_status_(PrintingContext::FAILED) {
@ -25,7 +28,7 @@ PrinterQuery::~PrinterQuery() {
// The job should be finished (or at least canceled) when it is destroyed. // The job should be finished (or at least canceled) when it is destroyed.
DCHECK(!is_print_dialog_box_shown_); DCHECK(!is_print_dialog_box_shown_);
// If this fires, it is that this pending printer context has leaked. // If this fires, it is that this pending printer context has leaked.
DCHECK(!worker_.get()); DCHECK(!worker_);
} }
void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings, void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
@ -47,12 +50,13 @@ void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
} }
} }
PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) { std::unique_ptr<PrintJobWorker> PrinterQuery::DetachWorker(
PrintJobWorkerOwner* new_owner) {
DCHECK(callback_.is_null()); DCHECK(callback_.is_null());
DCHECK(worker_.get()); DCHECK(worker_);
worker_->SetNewOwner(new_owner); worker_->SetNewOwner(new_owner);
return worker_.release(); return std::move(worker_);
} }
const PrintSettings& PrinterQuery::settings() const { const PrintSettings& PrinterQuery::settings() const {
@ -63,30 +67,31 @@ int PrinterQuery::cookie() const {
return cookie_; return cookie_;
} }
void PrinterQuery::GetSettings( void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
GetSettingsAskParam ask_user_for_settings, int expected_page_count,
int expected_page_count, bool has_selection,
bool has_selection, MarginType margin_type,
MarginType margin_type, bool is_scripted,
const base::Closure& callback) { bool is_modifiable,
const base::Closure& callback) {
DCHECK(RunsTasksOnCurrentThread()); DCHECK(RunsTasksOnCurrentThread());
DCHECK(!is_print_dialog_box_shown_); DCHECK(!is_print_dialog_box_shown_ || !is_scripted);
StartWorker(callback); StartWorker(callback);
// Real work is done in PrintJobWorker::GetSettings(). // Real work is done in PrintJobWorker::GetSettings().
is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER; is_print_dialog_box_shown_ =
worker_->PostTask(FROM_HERE, ask_user_for_settings == GetSettingsAskParam::ASK_USER;
base::Bind(&PrintJobWorker::GetSettings, worker_->PostTask(
base::Unretained(worker_.get()), FROM_HERE,
is_print_dialog_box_shown_, base::Bind(&PrintJobWorker::GetSettings, base::Unretained(worker_.get()),
expected_page_count, is_print_dialog_box_shown_, expected_page_count, has_selection,
has_selection, margin_type, is_scripted, is_modifiable));
margin_type));
} }
void PrinterQuery::SetSettings(std::unique_ptr<base::DictionaryValue> new_settings, void PrinterQuery::SetSettings(
const base::Closure& callback) { std::unique_ptr<base::DictionaryValue> new_settings,
const base::Closure& callback) {
StartWorker(callback); StartWorker(callback);
worker_->PostTask(FROM_HERE, worker_->PostTask(FROM_HERE,
@ -97,7 +102,7 @@ void PrinterQuery::SetSettings(std::unique_ptr<base::DictionaryValue> new_settin
void PrinterQuery::StartWorker(const base::Closure& callback) { void PrinterQuery::StartWorker(const base::Closure& callback) {
DCHECK(callback_.is_null()); DCHECK(callback_.is_null());
DCHECK(worker_.get()); DCHECK(worker_);
// Lazily create the worker thread. There is one worker thread per print job. // Lazily create the worker thread. There is one worker thread per print job.
if (!worker_->IsRunning()) if (!worker_->IsRunning())
@ -107,7 +112,7 @@ void PrinterQuery::StartWorker(const base::Closure& callback) {
} }
void PrinterQuery::StopWorker() { void PrinterQuery::StopWorker() {
if (worker_.get()) { if (worker_) {
// http://crbug.com/66082: We're blocking on the PrinterQuery's worker // http://crbug.com/66082: We're blocking on the PrinterQuery's worker
// thread. It's not clear to me if this may result in blocking the current // thread. It's not clear to me if this may result in blocking the current
// thread for an unacceptable time. We should probably fix it. // thread for an unacceptable time. We should probably fix it.
@ -122,7 +127,7 @@ bool PrinterQuery::is_callback_pending() const {
} }
bool PrinterQuery::is_valid() const { bool PrinterQuery::is_valid() const {
return worker_.get() != NULL; return !!worker_;
} }
} // namespace printing } // namespace printing

View file

@ -9,6 +9,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/browser/printing/print_job_worker_owner.h" #include "chrome/browser/printing/print_job_worker_owner.h"
#include "printing/print_job_constants.h" #include "printing/print_job_constants.h"
@ -25,30 +26,32 @@ class PrintJobWorker;
class PrinterQuery : public PrintJobWorkerOwner { class PrinterQuery : public PrintJobWorkerOwner {
public: public:
// GetSettings() UI parameter. // GetSettings() UI parameter.
enum GetSettingsAskParam { enum class GetSettingsAskParam {
DEFAULTS, DEFAULTS,
ASK_USER, ASK_USER,
}; };
PrinterQuery(int render_process_id, int render_view_id); PrinterQuery(int render_process_id, int render_frame_id);
// PrintJobWorkerOwner implementation. // PrintJobWorkerOwner implementation.
virtual void GetSettingsDone(const PrintSettings& new_settings, void GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) override; PrintingContext::Result result) override;
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) override; std::unique_ptr<PrintJobWorker> DetachWorker(
virtual const PrintSettings& settings() const override; PrintJobWorkerOwner* new_owner) override;
virtual int cookie() const override; const PrintSettings& settings() const override;
int cookie() const override;
// Initializes the printing context. It is fine to call this function multiple // Initializes the printing context. It is fine to call this function multiple
// times to reinitialize the settings. |web_contents_observer| can be queried // times to reinitialize the settings. |web_contents_observer| can be queried
// to find the owner of the print setting dialog box. It is unused when // to find the owner of the print setting dialog box. It is unused when
// |ask_for_user_settings| is DEFAULTS. // |ask_for_user_settings| is DEFAULTS.
void GetSettings( void GetSettings(GetSettingsAskParam ask_user_for_settings,
GetSettingsAskParam ask_user_for_settings, int expected_page_count,
int expected_page_count, bool has_selection,
bool has_selection, MarginType margin_type,
MarginType margin_type, bool is_scripted,
const base::Closure& callback); bool is_modifiable,
const base::Closure& callback);
// Updates the current settings with |new_settings| dictionary values. // Updates the current settings with |new_settings| dictionary values.
void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings, void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings,
@ -66,7 +69,7 @@ class PrinterQuery : public PrintJobWorkerOwner {
bool is_valid() const; bool is_valid() const;
private: private:
virtual ~PrinterQuery(); ~PrinterQuery() override;
// Lazy create the worker thread. There is one worker thread per print job. // Lazy create the worker thread. There is one worker thread per print job.
void StartWorker(const base::Closure& callback); void StartWorker(const base::Closure& callback);

View file

@ -14,23 +14,12 @@
#include "chrome/browser/profiles/profile_io_data.h" #include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/common/print_messages.h" #include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/child_process_host.h" #include "content/public/common/child_process_host.h"
#include "printing/features/features.h"
#if defined(ENABLE_FULL_PRINTING)
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#endif
#if defined(OS_CHROMEOS)
#include <fcntl.h>
#include <map>
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "chrome/browser/printing/print_dialog_cloud.h"
#endif
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
@ -44,19 +33,6 @@ namespace printing {
namespace { namespace {
#if defined(OS_CHROMEOS)
typedef std::map<int, base::FilePath> SequenceToPathMap;
struct PrintingSequencePathMap {
SequenceToPathMap map;
int sequence;
};
// No locking, only access on the FILE thread.
static base::LazyInstance<PrintingSequencePathMap>
g_printing_file_descriptor_map = LAZY_INSTANCE_INITIALIZER;
#endif
void RenderParamsFromPrintSettings(const PrintSettings& settings, void RenderParamsFromPrintSettings(const PrintSettings& settings,
PrintMsg_Print_Params* params) { PrintMsg_Print_Params* params) {
params->page_size = settings.page_setup_device_units().physical_size(); params->page_size = settings.page_setup_device_units().physical_size();
@ -71,6 +47,7 @@ void RenderParamsFromPrintSettings(const PrintSettings& settings,
params->margin_top = settings.page_setup_device_units().content_area().y(); params->margin_top = settings.page_setup_device_units().content_area().y();
params->margin_left = settings.page_setup_device_units().content_area().x(); params->margin_left = settings.page_setup_device_units().content_area().x();
params->dpi = settings.dpi(); params->dpi = settings.dpi();
params->scale_factor = settings.scale_factor();
// Currently hardcoded at 72dpi. See PrintSettings' constructor. // Currently hardcoded at 72dpi. See PrintSettings' constructor.
params->desired_dpi = settings.desired_dpi(); params->desired_dpi = settings.desired_dpi();
// Always use an invalid cookie. // Always use an invalid cookie.
@ -78,10 +55,30 @@ void RenderParamsFromPrintSettings(const PrintSettings& settings,
params->selection_only = settings.selection_only(); params->selection_only = settings.selection_only();
params->supports_alpha_blend = settings.supports_alpha_blend(); params->supports_alpha_blend = settings.supports_alpha_blend();
params->should_print_backgrounds = settings.should_print_backgrounds(); params->should_print_backgrounds = settings.should_print_backgrounds();
params->display_header_footer = settings.display_header_footer();
params->title = settings.title(); params->title = settings.title();
params->url = settings.url(); params->url = settings.url();
} }
#if defined(OS_ANDROID)
content::WebContents* GetWebContentsForRenderFrame(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::RenderFrameHost* frame =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
return frame ? content::WebContents::FromRenderFrameHost(frame) : nullptr;
}
PrintViewManagerBasic* GetPrintManager(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* web_contents =
GetWebContentsForRenderFrame(render_process_id, render_frame_id);
return web_contents ? PrintViewManagerBasic::FromWebContents(web_contents)
: nullptr;
}
#endif
} // namespace } // namespace
PrintingMessageFilter::PrintingMessageFilter(int render_process_id) PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
@ -94,14 +91,13 @@ PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
PrintingMessageFilter::~PrintingMessageFilter() { PrintingMessageFilter::~PrintingMessageFilter() {
} }
void PrintingMessageFilter::OnDestruct() const {
BrowserThread::DeleteOnUIThread::Destruct(this);
}
void PrintingMessageFilter::OverrideThreadForMessage( void PrintingMessageFilter::OverrideThreadForMessage(
const IPC::Message& message, BrowserThread::ID* thread) { const IPC::Message& message, BrowserThread::ID* thread) {
#if defined(OS_CHROMEOS) #if defined(OS_ANDROID)
if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID ||
message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) {
*thread = BrowserThread::FILE;
}
#elif defined(OS_ANDROID)
if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID ||
message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) {
*thread = BrowserThread::UI; *thread = BrowserThread::UI;
@ -112,10 +108,7 @@ void PrintingMessageFilter::OverrideThreadForMessage(
bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) { bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true; bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message) IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message)
#if defined(OS_WIN) #if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection)
#endif
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting, IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting,
OnAllocateTempFileForPrinting) OnAllocateTempFileForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten, IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten,
@ -126,139 +119,46 @@ bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings, IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
OnUpdatePrintSettings) OnUpdatePrintSettings)
#if defined(ENABLE_FULL_PRINTING)
IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel)
#endif
IPC_MESSAGE_UNHANDLED(handled = false) IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP() IPC_END_MESSAGE_MAP()
return handled; return handled;
} }
#if defined(OS_WIN) #if defined(OS_ANDROID)
void PrintingMessageFilter::OnDuplicateSection(
base::SharedMemoryHandle renderer_handle,
base::SharedMemoryHandle* browser_handle) {
// Duplicate the handle in this process right now so the memory is kept alive
// (even if it is not mapped)
base::SharedMemory shared_buf(renderer_handle, true);
shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
}
#endif
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
void PrintingMessageFilter::OnAllocateTempFileForPrinting( void PrintingMessageFilter::OnAllocateTempFileForPrinting(
int render_view_id, int render_frame_id,
base::FileDescriptor* temp_file_fd, base::FileDescriptor* temp_file_fd,
int* sequence_number) { 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); DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
if (!wc)
return;
PrintViewManagerBasic* print_view_manager = PrintViewManagerBasic* print_view_manager =
PrintViewManagerBasic::FromWebContents(wc); GetPrintManager(render_process_id_, render_frame_id);
if (!print_view_manager)
return;
// The file descriptor is originally created in & passed from the Android // The file descriptor is originally created in & passed from the Android
// side, and it will handle the closing. // side, and it will handle the closing.
const base::FileDescriptor& file_descriptor = temp_file_fd->fd = print_view_manager->file_descriptor().fd;
print_view_manager->file_descriptor();
temp_file_fd->fd = file_descriptor.fd;
temp_file_fd->auto_close = false; temp_file_fd->auto_close = false;
#endif
} }
void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_view_id, void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_frame_id,
int sequence_number) { 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); DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
if (!wc)
return;
PrintViewManagerBasic* print_view_manager = PrintViewManagerBasic* print_view_manager =
PrintViewManagerBasic::FromWebContents(wc); GetPrintManager(render_process_id_, render_frame_id);
const base::FileDescriptor& file_descriptor = if (print_view_manager)
print_view_manager->file_descriptor(); print_view_manager->PdfWritingDone(true);
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);
content::RenderViewHost* view = content::RenderViewHost::FromID(
render_process_id_, render_view_id);
return view ? content::WebContents::FromRenderViewHost(view) : NULL;
} }
#endif // defined(OS_ANDROID)
void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_refptr<PrinterQuery> printer_query; scoped_refptr<PrinterQuery> printer_query;
#if 0 if (false) {
if (!profile_io_data_->printing_enabled()->GetValue()) {
// Reply with NULL query. // Reply with NULL query.
OnGetDefaultPrintSettingsReply(printer_query, reply_msg); OnGetDefaultPrintSettingsReply(printer_query, reply_msg);
return; return;
} }
#endif
printer_query = queue_->PopPrinterQuery(0); printer_query = queue_->PopPrinterQuery(0);
if (!printer_query.get()) { if (!printer_query.get()) {
printer_query = printer_query =
@ -268,14 +168,10 @@ void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
// Loads default settings. This is asynchronous, only the IPC message sender // Loads default settings. This is asynchronous, only the IPC message sender
// will hang until the settings are retrieved. // will hang until the settings are retrieved.
printer_query->GetSettings( printer_query->GetSettings(
PrinterQuery::DEFAULTS, PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS,
0, false, false,
false, base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, this,
DEFAULT_MARGINS, printer_query, reply_msg));
base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply,
this,
printer_query,
reply_msg));
} }
void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( void PrintingMessageFilter::OnGetDefaultPrintSettingsReply(
@ -312,14 +208,10 @@ void PrintingMessageFilter::OnScriptedPrint(
queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
} }
printer_query->GetSettings( printer_query->GetSettings(
PrinterQuery::ASK_USER, PrinterQuery::GetSettingsAskParam::ASK_USER, params.expected_pages_count,
params.expected_pages_count, params.has_selection, params.margin_type, true, true,
params.has_selection, base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this,
params.margin_type, printer_query, reply_msg));
base::Bind(&PrintingMessageFilter::OnScriptedPrintReply,
this,
printer_query,
reply_msg));
} }
void PrintingMessageFilter::OnScriptedPrintReply( void PrintingMessageFilter::OnScriptedPrintReply(
@ -407,11 +299,10 @@ void PrintingMessageFilter::OnUpdatePrintSettingsReply(
params.params.document_cookie = printer_query->cookie(); params.params.document_cookie = printer_query->cookie();
params.pages = PageRange::GetPages(printer_query->settings().ranges()); params.pages = PageRange::GetPages(printer_query->settings().ranges());
} }
PrintHostMsg_UpdatePrintSettings::WriteReplyParams( bool canceled = printer_query.get() &&
reply_msg, (printer_query->last_status() == PrintingContext::CANCEL);
params, PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params,
printer_query.get() && canceled);
(printer_query->last_status() == printing::PrintingContext::CANCEL));
Send(reply_msg); Send(reply_msg);
// If user hasn't cancelled. // If user hasn't cancelled.
if (printer_query.get()) { if (printer_query.get()) {

View file

@ -10,13 +10,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_message_filter.h"
#if defined(OS_WIN)
#include "base/memory/shared_memory.h"
#endif
struct PrintHostMsg_ScriptedPrint_Params; struct PrintHostMsg_ScriptedPrint_Params;
class Profile;
class ProfileIOData;
namespace base { namespace base {
class DictionaryValue; class DictionaryValue;
@ -29,7 +23,6 @@ class WebContents;
namespace printing { namespace printing {
class PrintJobManager;
class PrintQueriesQueue; class PrintQueriesQueue;
class PrinterQuery; class PrinterQuery;
@ -46,43 +39,26 @@ class PrintingMessageFilter : public content::BrowserMessageFilter {
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
private: private:
friend class base::DeleteHelper<PrintingMessageFilter>;
friend class content::BrowserThread;
virtual ~PrintingMessageFilter(); virtual ~PrintingMessageFilter();
#if defined(OS_WIN) void OnDestruct() const override;
// Used to pass resulting EMF from renderer to browser in printing.
void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
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) #if 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_frame_id,
base::FileDescriptor* temp_file_fd,
int* sequence_number);
void OnTempFileForPrintingWritten(int render_frame_id, int sequence_number);
// Updates the file descriptor for the PrintViewManagerBasic of a given // Updates the file descriptor for the PrintViewManagerBasic of a given
// render_view_id. // render_frame_id.
void UpdateFileDescriptor(int render_view_id, int fd); void UpdateFileDescriptor(int render_frame_id, int fd);
#endif #endif
// Given a render_view_id get the corresponding WebContents.
// Must be called on the UI thread.
content::WebContents* GetWebContentsForRenderView(int render_view_id);
// GetPrintSettingsForRenderView must be called via PostTask and
// base::Bind. Collapse the settings-specific params into a
// struct to avoid running into issues with too many params
// to base::Bind.
struct GetPrintSettingsForRenderViewParams;
// Get the default print setting. // Get the default print setting.
void OnGetDefaultPrintSettings(IPC::Message* reply_msg); void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
void OnGetDefaultPrintSettingsReply(scoped_refptr<PrinterQuery> printer_query, void OnGetDefaultPrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
@ -105,13 +81,6 @@ class PrintingMessageFilter : public content::BrowserMessageFilter {
void OnUpdatePrintSettingsReply(scoped_refptr<PrinterQuery> printer_query, void OnUpdatePrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg); IPC::Message* reply_msg);
#if defined(ENABLE_FULL_PRINTING)
// Check to see if print preview has been cancelled.
void OnCheckForCancel(int32_t preview_ui_id,
int preview_request_id,
bool* cancel);
#endif
const int render_process_id_; const int render_process_id_;
scoped_refptr<PrintQueriesQueue> queue_; scoped_refptr<PrintQueriesQueue> queue_;

View file

@ -8,23 +8,26 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
PrintMsg_Print_Params::PrintMsg_Print_Params() PrintMsg_Print_Params::PrintMsg_Print_Params()
: page_size(), : page_size(),
content_size(), content_size(),
printable_area(), printable_area(),
margin_top(0), margin_top(0),
margin_left(0), margin_left(0),
dpi(0), dpi(0),
min_shrink(0), scale_factor(1.0f),
max_shrink(0), desired_dpi(0),
desired_dpi(0), document_cookie(0),
document_cookie(0), selection_only(false),
selection_only(false), supports_alpha_blend(false),
supports_alpha_blend(false), preview_ui_id(-1),
print_scaling_option(blink::WebPrintScalingOptionSourceSize), preview_request_id(0),
title(), is_first_request(false),
url(), print_scaling_option(blink::WebPrintScalingOptionSourceSize),
should_print_backgrounds(false) { print_to_pdf(false),
} display_header_footer(false),
title(),
url(),
should_print_backgrounds(false) {}
PrintMsg_Print_Params::~PrintMsg_Print_Params() {} PrintMsg_Print_Params::~PrintMsg_Print_Params() {}
@ -35,15 +38,19 @@ void PrintMsg_Print_Params::Reset() {
margin_top = 0; margin_top = 0;
margin_left = 0; margin_left = 0;
dpi = 0; dpi = 0;
min_shrink = 0; scale_factor = 1.0f;
max_shrink = 0;
desired_dpi = 0; desired_dpi = 0;
document_cookie = 0; document_cookie = 0;
selection_only = false; selection_only = false;
supports_alpha_blend = false; supports_alpha_blend = false;
preview_ui_id = -1;
preview_request_id = 0;
is_first_request = false;
print_scaling_option = blink::WebPrintScalingOptionSourceSize; print_scaling_option = blink::WebPrintScalingOptionSourceSize;
title.clear(); print_to_pdf = false;
url.clear(); display_header_footer = false;
title = base::string16();
url = base::string16();
should_print_backgrounds = false; should_print_backgrounds = false;
} }

View file

@ -40,15 +40,18 @@ struct PrintMsg_Print_Params {
int margin_top; int margin_top;
int margin_left; int margin_left;
double dpi; double dpi;
double min_shrink; double scale_factor;
double max_shrink;
int desired_dpi; int desired_dpi;
bool rasterize_pdf;
int document_cookie; int document_cookie;
bool selection_only; bool selection_only;
bool supports_alpha_blend; bool supports_alpha_blend;
int32_t preview_ui_id;
int preview_request_id; int preview_request_id;
bool is_first_request;
blink::WebPrintScalingOption print_scaling_option; blink::WebPrintScalingOption print_scaling_option;
bool print_to_pdf; bool print_to_pdf;
bool display_header_footer;
base::string16 title; base::string16 title;
base::string16 url; base::string16 url;
bool should_print_backgrounds; bool should_print_backgrounds;
@ -95,11 +98,8 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// Specifies dots per inch. // Specifies dots per inch.
IPC_STRUCT_TRAITS_MEMBER(dpi) IPC_STRUCT_TRAITS_MEMBER(dpi)
// Minimum shrink factor. See PrintSettings::min_shrink for more information. // Specifies the scale factor in percent
IPC_STRUCT_TRAITS_MEMBER(min_shrink) IPC_STRUCT_TRAITS_MEMBER(scale_factor)
// Maximum shrink factor. See PrintSettings::max_shrink for more information.
IPC_STRUCT_TRAITS_MEMBER(max_shrink)
// Desired apparent dpi on paper. // Desired apparent dpi on paper.
IPC_STRUCT_TRAITS_MEMBER(desired_dpi) IPC_STRUCT_TRAITS_MEMBER(desired_dpi)
@ -113,9 +113,26 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// Does the printer support alpha blending? // Does the printer support alpha blending?
IPC_STRUCT_TRAITS_MEMBER(supports_alpha_blend) IPC_STRUCT_TRAITS_MEMBER(supports_alpha_blend)
// *** Parameters below are used only for print preview. ***
// The print preview ui associated with this request.
IPC_STRUCT_TRAITS_MEMBER(preview_ui_id)
// The id of the preview request.
IPC_STRUCT_TRAITS_MEMBER(preview_request_id)
// True if this is the first preview request.
IPC_STRUCT_TRAITS_MEMBER(is_first_request)
// Specifies the page scaling option for preview printing. // Specifies the page scaling option for preview printing.
IPC_STRUCT_TRAITS_MEMBER(print_scaling_option) IPC_STRUCT_TRAITS_MEMBER(print_scaling_option)
// True if print to pdf is requested.
IPC_STRUCT_TRAITS_MEMBER(print_to_pdf)
// Specifies if the header and footer should be rendered.
IPC_STRUCT_TRAITS_MEMBER(display_header_footer)
// Title string to be printed as header if requested by the user. // Title string to be printed as header if requested by the user.
IPC_STRUCT_TRAITS_MEMBER(title) IPC_STRUCT_TRAITS_MEMBER(title)

View file

@ -1087,16 +1087,16 @@ bool PrintWebViewHelper::UpdatePrintSettings(
SetPrintPagesParams(settings); SetPrintPagesParams(settings);
if (!PrintMsg_Print_Params_IsValid(settings.params)) { if (PrintMsg_Print_Params_IsValid(settings.params))
if (!print_for_preview_) return true;
print_preview_context_.set_error(PREVIEW_ERROR_INVALID_PRINTER_SETTINGS);
return false;
}
return true; if (print_for_preview_)
Send(new PrintHostMsg_ShowInvalidPrinterSettingsError(routing_id()));
else
print_preview_context_.set_error(PREVIEW_ERROR_INVALID_PRINTER_SETTINGS);
return false;
} }
bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebLocalFrame* frame, bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebLocalFrame* frame,
const blink::WebNode& node, const blink::WebNode& node,
int expected_pages_count) { int expected_pages_count) {
@ -1170,6 +1170,8 @@ bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
void PrintWebViewHelper::SetPrintPagesParams( void PrintWebViewHelper::SetPrintPagesParams(
const PrintMsg_PrintPages_Params& settings) { const PrintMsg_PrintPages_Params& settings) {
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
settings.params.document_cookie));
} }
bool PrintWebViewHelper::PreviewPageRendered(int page_number, bool PrintWebViewHelper::PreviewPageRendered(int page_number,