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