1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/printing/printer_query.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "base/values.h"
12 #include "chrome/browser/printing/print_job_worker.h"
13 #include "chrome/browser/printing/printing_ui_web_contents_observer.h"
17 PrinterQuery::PrinterQuery()
18 : io_message_loop_(base::MessageLoop::current()),
19 worker_(new PrintJobWorker(this)),
20 is_print_dialog_box_shown_(false),
21 cookie_(PrintSettings::NewCookie()),
22 last_status_(PrintingContext::FAILED
) {
23 DCHECK(base::MessageLoopForIO::IsCurrent());
26 PrinterQuery::~PrinterQuery() {
27 // The job should be finished (or at least canceled) when it is destroyed.
28 DCHECK(!is_print_dialog_box_shown_
);
29 // If this fires, it is that this pending printer context has leaked.
30 DCHECK(!worker_
.get());
33 void PrinterQuery::GetSettingsDone(const PrintSettings
& new_settings
,
34 PrintingContext::Result result
) {
35 is_print_dialog_box_shown_
= false;
36 last_status_
= result
;
37 if (result
!= PrintingContext::FAILED
) {
38 settings_
= new_settings
;
39 cookie_
= PrintSettings::NewCookie();
45 if (!callback_
.is_null()) {
46 // This may cause reentrancy like to call StopWorker().
52 PrintJobWorker
* PrinterQuery::DetachWorker(PrintJobWorkerOwner
* new_owner
) {
53 DCHECK(callback_
.is_null());
54 DCHECK(worker_
.get());
56 worker_
->SetNewOwner(new_owner
);
57 return worker_
.release();
60 base::MessageLoop
* PrinterQuery::message_loop() {
61 return io_message_loop_
;
64 const PrintSettings
& PrinterQuery::settings() const {
68 int PrinterQuery::cookie() const {
72 void PrinterQuery::GetSettings(
73 GetSettingsAskParam ask_user_for_settings
,
74 scoped_ptr
<PrintingUIWebContentsObserver
> web_contents_observer
,
75 int expected_page_count
,
77 MarginType margin_type
,
78 const base::Closure
& callback
) {
79 DCHECK_EQ(io_message_loop_
, base::MessageLoop::current());
80 DCHECK(!is_print_dialog_box_shown_
);
82 StartWorker(callback
);
84 // Real work is done in PrintJobWorker::GetSettings().
85 is_print_dialog_box_shown_
= ask_user_for_settings
== ASK_USER
;
86 worker_
->message_loop()->PostTask(
88 base::Bind(&PrintJobWorker::GetSettings
,
89 base::Unretained(worker_
.get()),
90 is_print_dialog_box_shown_
,
91 base::Passed(&web_contents_observer
),
97 void PrinterQuery::SetSettings(const base::DictionaryValue
& new_settings
,
98 const base::Closure
& callback
) {
99 StartWorker(callback
);
101 worker_
->message_loop()->PostTask(
103 base::Bind(&PrintJobWorker::SetSettings
,
104 base::Unretained(worker_
.get()),
105 new_settings
.DeepCopy()));
108 void PrinterQuery::SetWorkerDestination(
109 PrintDestinationInterface
* destination
) {
110 worker_
->SetPrintDestination(destination
);
113 void PrinterQuery::StartWorker(const base::Closure
& callback
) {
114 DCHECK(callback_
.is_null());
115 DCHECK(worker_
.get());
117 // Lazily create the worker thread. There is one worker thread per print job.
118 if (!worker_
->message_loop())
121 callback_
= callback
;
124 void PrinterQuery::StopWorker() {
126 // http://crbug.com/66082: We're blocking on the PrinterQuery's worker
127 // thread. It's not clear to me if this may result in blocking the current
128 // thread for an unacceptable time. We should probably fix it.
129 base::ThreadRestrictions::ScopedAllowIO allow_io
;
135 bool PrinterQuery::is_callback_pending() const {
136 return !callback_
.is_null();
139 bool PrinterQuery::is_valid() const {
140 return worker_
.get() != NULL
;
143 } // namespace printing