Home | History | Annotate | Download | only in printing
      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 
     14 namespace printing {
     15 
     16 PrinterQuery::PrinterQuery(int render_process_id, int render_view_id)
     17     : worker_(new PrintJobWorker(render_process_id, render_view_id, this)),
     18       is_print_dialog_box_shown_(false),
     19       cookie_(PrintSettings::NewCookie()),
     20       last_status_(PrintingContext::FAILED) {
     21   DCHECK(base::MessageLoopForIO::IsCurrent());
     22 }
     23 
     24 PrinterQuery::~PrinterQuery() {
     25   // The job should be finished (or at least canceled) when it is destroyed.
     26   DCHECK(!is_print_dialog_box_shown_);
     27   // If this fires, it is that this pending printer context has leaked.
     28   DCHECK(!worker_.get());
     29 }
     30 
     31 void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
     32                                    PrintingContext::Result result) {
     33   is_print_dialog_box_shown_ = false;
     34   last_status_ = result;
     35   if (result != PrintingContext::FAILED) {
     36     settings_ = new_settings;
     37     cookie_ = PrintSettings::NewCookie();
     38   } else {
     39     // Failure.
     40     cookie_ = 0;
     41   }
     42 
     43   if (!callback_.is_null()) {
     44     // This may cause reentrancy like to call StopWorker().
     45     callback_.Run();
     46     callback_.Reset();
     47   }
     48 }
     49 
     50 PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) {
     51   DCHECK(callback_.is_null());
     52   DCHECK(worker_.get());
     53 
     54   worker_->SetNewOwner(new_owner);
     55   return worker_.release();
     56 }
     57 
     58 const PrintSettings& PrinterQuery::settings() const {
     59   return settings_;
     60 }
     61 
     62 int PrinterQuery::cookie() const {
     63   return cookie_;
     64 }
     65 
     66 void PrinterQuery::GetSettings(
     67     GetSettingsAskParam ask_user_for_settings,
     68     int expected_page_count,
     69     bool has_selection,
     70     MarginType margin_type,
     71     const base::Closure& callback) {
     72   DCHECK(RunsTasksOnCurrentThread());
     73   DCHECK(!is_print_dialog_box_shown_);
     74 
     75   StartWorker(callback);
     76 
     77   // Real work is done in PrintJobWorker::GetSettings().
     78   is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER;
     79   worker_->PostTask(FROM_HERE,
     80                     base::Bind(&PrintJobWorker::GetSettings,
     81                                base::Unretained(worker_.get()),
     82                                is_print_dialog_box_shown_,
     83                                expected_page_count,
     84                                has_selection,
     85                                margin_type));
     86 }
     87 
     88 void PrinterQuery::SetSettings(scoped_ptr<base::DictionaryValue> new_settings,
     89                                const base::Closure& callback) {
     90   StartWorker(callback);
     91 
     92   worker_->PostTask(FROM_HERE,
     93                     base::Bind(&PrintJobWorker::SetSettings,
     94                                base::Unretained(worker_.get()),
     95                                base::Passed(&new_settings)));
     96 }
     97 
     98 void PrinterQuery::StartWorker(const base::Closure& callback) {
     99   DCHECK(callback_.is_null());
    100   DCHECK(worker_.get());
    101 
    102   // Lazily create the worker thread. There is one worker thread per print job.
    103   if (!worker_->IsRunning())
    104     worker_->Start();
    105 
    106   callback_ = callback;
    107 }
    108 
    109 void PrinterQuery::StopWorker() {
    110   if (worker_.get()) {
    111     // http://crbug.com/66082: We're blocking on the PrinterQuery's worker
    112     // thread.  It's not clear to me if this may result in blocking the current
    113     // thread for an unacceptable time.  We should probably fix it.
    114     base::ThreadRestrictions::ScopedAllowIO allow_io;
    115     worker_->Stop();
    116     worker_.reset();
    117   }
    118 }
    119 
    120 bool PrinterQuery::is_callback_pending() const {
    121   return !callback_.is_null();
    122 }
    123 
    124 bool PrinterQuery::is_valid() const {
    125   return worker_.get() != NULL;
    126 }
    127 
    128 }  // namespace printing
    129