• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/printing/printer_query.h"
6 
7 #include "base/bind.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"
14 
15 namespace printing {
16 
PrinterQuery()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());
24 }
25 
~PrinterQuery()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());
31 }
32 
GetSettingsDone(const PrintSettings & new_settings,PrintingContext::Result result)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();
40   } else {
41     // Failure.
42     cookie_ = 0;
43   }
44 
45   if (!callback_.is_null()) {
46     // This may cause reentrancy like to call StopWorker().
47     callback_.Run();
48     callback_.Reset();
49   }
50 }
51 
DetachWorker(PrintJobWorkerOwner * new_owner)52 PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) {
53   DCHECK(callback_.is_null());
54   DCHECK(worker_.get());
55 
56   worker_->SetNewOwner(new_owner);
57   return worker_.release();
58 }
59 
message_loop()60 base::MessageLoop* PrinterQuery::message_loop() {
61   return io_message_loop_;
62 }
63 
settings() const64 const PrintSettings& PrinterQuery::settings() const {
65   return settings_;
66 }
67 
cookie() const68 int PrinterQuery::cookie() const {
69   return cookie_;
70 }
71 
GetSettings(GetSettingsAskParam ask_user_for_settings,scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,int expected_page_count,bool has_selection,MarginType margin_type,const base::Closure & callback)72 void PrinterQuery::GetSettings(
73     GetSettingsAskParam ask_user_for_settings,
74     scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
75     int expected_page_count,
76     bool has_selection,
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_);
81 
82   StartWorker(callback);
83 
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(
87       FROM_HERE,
88       base::Bind(&PrintJobWorker::GetSettings,
89                  base::Unretained(worker_.get()),
90                  is_print_dialog_box_shown_,
91                  base::Passed(&web_contents_observer),
92                  expected_page_count,
93                  has_selection,
94                  margin_type));
95 }
96 
SetSettings(const base::DictionaryValue & new_settings,const base::Closure & callback)97 void PrinterQuery::SetSettings(const base::DictionaryValue& new_settings,
98                                const base::Closure& callback) {
99   StartWorker(callback);
100 
101   worker_->message_loop()->PostTask(
102       FROM_HERE,
103       base::Bind(&PrintJobWorker::SetSettings,
104                  base::Unretained(worker_.get()),
105                  new_settings.DeepCopy()));
106 }
107 
SetWorkerDestination(PrintDestinationInterface * destination)108 void PrinterQuery::SetWorkerDestination(
109     PrintDestinationInterface* destination) {
110   worker_->SetPrintDestination(destination);
111 }
112 
StartWorker(const base::Closure & callback)113 void PrinterQuery::StartWorker(const base::Closure& callback) {
114   DCHECK(callback_.is_null());
115   DCHECK(worker_.get());
116 
117   // Lazily create the worker thread. There is one worker thread per print job.
118   if (!worker_->message_loop())
119     worker_->Start();
120 
121   callback_ = callback;
122 }
123 
StopWorker()124 void PrinterQuery::StopWorker() {
125   if (worker_.get()) {
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;
130     worker_->Stop();
131     worker_.reset();
132   }
133 }
134 
is_callback_pending() const135 bool PrinterQuery::is_callback_pending() const {
136   return !callback_.is_null();
137 }
138 
is_valid() const139 bool PrinterQuery::is_valid() const {
140   return worker_.get() != NULL;
141 }
142 
143 }  // namespace printing
144