• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/message_loop.h"
8 #include "base/threading/thread_restrictions.h"
9 #include "base/values.h"
10 #include "chrome/browser/printing/print_job_worker.h"
11 
12 namespace printing {
13 
PrinterQuery()14 PrinterQuery::PrinterQuery()
15     : io_message_loop_(MessageLoop::current()),
16       ALLOW_THIS_IN_INITIALIZER_LIST(worker_(new PrintJobWorker(this))),
17       is_print_dialog_box_shown_(false),
18       cookie_(PrintSettings::NewCookie()),
19       last_status_(PrintingContext::FAILED) {
20   DCHECK_EQ(io_message_loop_->type(), MessageLoop::TYPE_IO);
21 }
22 
~PrinterQuery()23 PrinterQuery::~PrinterQuery() {
24   // The job should be finished (or at least canceled) when it is destroyed.
25   DCHECK(!is_print_dialog_box_shown_);
26   // If this fires, it is that this pending printer context has leaked.
27   DCHECK(!worker_.get());
28   if (callback_.get()) {
29     // Be sure to cancel it.
30     callback_->Cancel();
31   }
32   // It may get deleted in a different thread that the one that created it.
33 }
34 
GetSettingsDone(const PrintSettings & new_settings,PrintingContext::Result result)35 void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
36                                    PrintingContext::Result result) {
37   is_print_dialog_box_shown_ = false;
38   last_status_ = result;
39   if (result != PrintingContext::FAILED) {
40     settings_ = new_settings;
41     cookie_ = PrintSettings::NewCookie();
42   } else {
43     // Failure.
44     cookie_ = 0;
45   }
46   if (callback_.get()) {
47     // This may cause reentrancy like to call StopWorker().
48     callback_->Run();
49     callback_.reset(NULL);
50   }
51 }
52 
DetachWorker(PrintJobWorkerOwner * new_owner)53 PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) {
54   DCHECK(!callback_.get());
55   DCHECK(worker_.get());
56   if (!worker_.get())
57     return NULL;
58   worker_->SetNewOwner(new_owner);
59   return worker_.release();
60 }
61 
message_loop()62 MessageLoop* PrinterQuery::message_loop() {
63   return io_message_loop_;
64 }
65 
settings() const66 const PrintSettings& PrinterQuery::settings() const {
67   return settings_;
68 }
69 
cookie() const70 int PrinterQuery::cookie() const {
71   return cookie_;
72 }
73 
GetSettings(GetSettingsAskParam ask_user_for_settings,gfx::NativeView parent_view,int expected_page_count,bool has_selection,bool use_overlays,CancelableTask * callback)74 void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
75                                gfx::NativeView parent_view,
76                                int expected_page_count,
77                                bool has_selection,
78                                bool use_overlays,
79                                CancelableTask* callback) {
80   DCHECK_EQ(io_message_loop_, MessageLoop::current());
81   DCHECK(!is_print_dialog_box_shown_);
82   if (!StartWorker(callback))
83     return;
84 
85   // Real work is done in PrintJobWorker::Init().
86   is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER;
87   worker_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
88       worker_.get(),
89       &PrintJobWorker::GetSettings,
90       is_print_dialog_box_shown_,
91       parent_view,
92       expected_page_count,
93       has_selection,
94       use_overlays));
95 }
96 
SetSettings(const DictionaryValue & new_settings,CancelableTask * callback)97 void PrinterQuery::SetSettings(const DictionaryValue& new_settings,
98                                CancelableTask* callback) {
99   if (!StartWorker(callback))
100     return;
101 
102   worker_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
103       worker_.get(),
104       &PrintJobWorker::SetSettings,
105       new_settings.DeepCopy()));
106 }
107 
StartWorker(CancelableTask * callback)108 bool PrinterQuery::StartWorker(CancelableTask* callback) {
109   DCHECK(!callback_.get());
110   DCHECK(worker_.get());
111   if (!worker_.get())
112     return false;
113 
114   // Lazy create the worker thread. There is one worker thread per print job.
115   if (!worker_->message_loop()) {
116     if (!worker_->Start()) {
117       if (callback) {
118         callback->Cancel();
119         delete callback;
120       }
121       NOTREACHED();
122       return false;
123     }
124   }
125   callback_.reset(callback);
126   return true;
127 }
128 
StopWorker()129 void PrinterQuery::StopWorker() {
130   if (worker_.get()) {
131     // http://crbug.com/66082: We're blocking on the PrinterQuery's worker
132     // thread.  It's not clear to me if this may result in blocking the current
133     // thread for an unacceptable time.  We should probably fix it.
134     base::ThreadRestrictions::ScopedAllowIO allow_io;
135     worker_->Stop();
136     worker_.reset();
137   }
138 }
139 
is_callback_pending() const140 bool PrinterQuery::is_callback_pending() const {
141   return callback_.get() != NULL;
142 }
143 
is_valid() const144 bool PrinterQuery::is_valid() const {
145   return worker_.get() != NULL;
146 }
147 
148 }  // namespace printing
149