| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/printing/print_job.h" | 5 #include "chrome/browser/printing/print_job.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 DCHECK(base::MessageLoopForUI::IsCurrent() || | 55 DCHECK(base::MessageLoopForUI::IsCurrent() || |
| 56 base::MessageLoop::current()->type() == | 56 base::MessageLoop::current()->type() == |
| 57 base::MessageLoop::TYPE_DEFAULT); | 57 base::MessageLoop::TYPE_DEFAULT); |
| 58 } | 58 } |
| 59 | 59 |
| 60 PrintJob::~PrintJob() { | 60 PrintJob::~PrintJob() { |
| 61 // The job should be finished (or at least canceled) when it is destroyed. | 61 // The job should be finished (or at least canceled) when it is destroyed. |
| 62 DCHECK(!is_job_pending_); | 62 DCHECK(!is_job_pending_); |
| 63 DCHECK(!is_canceling_); | 63 DCHECK(!is_canceling_); |
| 64 DCHECK(!worker_ || !worker_->IsRunning()); | 64 DCHECK(!worker_ || !worker_->IsRunning()); |
| 65 DCHECK(RunsTasksOnCurrentThread()); | 65 DCHECK(RunsTasksInCurrentSequence()); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void PrintJob::Initialize(PrintJobWorkerOwner* job, | 68 void PrintJob::Initialize(PrintJobWorkerOwner* job, |
| 69 PrintedPagesSource* source, | 69 PrintedPagesSource* source, |
| 70 int page_count) { | 70 int page_count) { |
| 71 DCHECK(!source_); | 71 DCHECK(!source_); |
| 72 DCHECK(!worker_); | 72 DCHECK(!worker_); |
| 73 DCHECK(!is_job_pending_); | 73 DCHECK(!is_job_pending_); |
| 74 DCHECK(!is_canceling_); | 74 DCHECK(!is_canceling_); |
| 75 DCHECK(!document_.get()); | 75 DCHECK(!document_.get()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 86 UpdatePrintedDocument(new_doc); | 86 UpdatePrintedDocument(new_doc); |
| 87 | 87 |
| 88 // Don't forget to register to our own messages. | 88 // Don't forget to register to our own messages. |
| 89 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, | 89 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| 90 content::Source<PrintJob>(this)); | 90 content::Source<PrintJob>(this)); |
| 91 } | 91 } |
| 92 | 92 |
| 93 void PrintJob::Observe(int type, | 93 void PrintJob::Observe(int type, |
| 94 const content::NotificationSource& source, | 94 const content::NotificationSource& source, |
| 95 const content::NotificationDetails& details) { | 95 const content::NotificationDetails& details) { |
| 96 DCHECK(RunsTasksOnCurrentThread()); | 96 DCHECK(RunsTasksInCurrentSequence()); |
| 97 DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type); | 97 DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type); |
| 98 | 98 |
| 99 OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr()); | 99 OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr()); |
| 100 } | 100 } |
| 101 | 101 |
| 102 void PrintJob::GetSettingsDone(const PrintSettings& new_settings, | 102 void PrintJob::GetSettingsDone(const PrintSettings& new_settings, |
| 103 PrintingContext::Result result) { | 103 PrintingContext::Result result) { |
| 104 NOTREACHED(); | 104 NOTREACHED(); |
| 105 } | 105 } |
| 106 | 106 |
| 107 std::unique_ptr<PrintJobWorker> PrintJob::DetachWorker( | 107 std::unique_ptr<PrintJobWorker> PrintJob::DetachWorker( |
| 108 PrintJobWorkerOwner* new_owner) { | 108 PrintJobWorkerOwner* new_owner) { |
| 109 NOTREACHED(); | 109 NOTREACHED(); |
| 110 return nullptr; | 110 return nullptr; |
| 111 } | 111 } |
| 112 | 112 |
| 113 const PrintSettings& PrintJob::settings() const { | 113 const PrintSettings& PrintJob::settings() const { |
| 114 return settings_; | 114 return settings_; |
| 115 } | 115 } |
| 116 | 116 |
| 117 int PrintJob::cookie() const { | 117 int PrintJob::cookie() const { |
| 118 // Always use an invalid cookie in this case. | 118 // Always use an invalid cookie in this case. |
| 119 if (!document_.get()) | 119 if (!document_.get()) |
| 120 return 0; | 120 return 0; |
| 121 return document_->cookie(); | 121 return document_->cookie(); |
| 122 } | 122 } |
| 123 | 123 |
| 124 void PrintJob::StartPrinting() { | 124 void PrintJob::StartPrinting() { |
| 125 DCHECK(RunsTasksOnCurrentThread()); | 125 DCHECK(RunsTasksInCurrentSequence()); |
| 126 if (!worker_->IsRunning() || is_job_pending_) { | 126 if (!worker_->IsRunning() || is_job_pending_) { |
| 127 NOTREACHED(); | 127 NOTREACHED(); |
| 128 return; | 128 return; |
| 129 } | 129 } |
| 130 | 130 |
| 131 // Real work is done in PrintJobWorker::StartPrinting(). | 131 // Real work is done in PrintJobWorker::StartPrinting(). |
| 132 worker_->PostTask(FROM_HERE, | 132 worker_->PostTask(FROM_HERE, |
| 133 base::Bind(&HoldRefCallback, make_scoped_refptr(this), | 133 base::Bind(&HoldRefCallback, make_scoped_refptr(this), |
| 134 base::Bind(&PrintJobWorker::StartPrinting, | 134 base::Bind(&PrintJobWorker::StartPrinting, |
| 135 base::Unretained(worker_.get()), | 135 base::Unretained(worker_.get()), |
| 136 base::RetainedRef(document_)))); | 136 base::RetainedRef(document_)))); |
| 137 // Set the flag right now. | 137 // Set the flag right now. |
| 138 is_job_pending_ = true; | 138 is_job_pending_ = true; |
| 139 | 139 |
| 140 // Tell everyone! | 140 // Tell everyone! |
| 141 scoped_refptr<JobEventDetails> details(new JobEventDetails( | 141 scoped_refptr<JobEventDetails> details(new JobEventDetails( |
| 142 JobEventDetails::NEW_DOC, 0, document_.get(), nullptr)); | 142 JobEventDetails::NEW_DOC, 0, document_.get(), nullptr)); |
| 143 content::NotificationService::current()->Notify( | 143 content::NotificationService::current()->Notify( |
| 144 chrome::NOTIFICATION_PRINT_JOB_EVENT, | 144 chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| 145 content::Source<PrintJob>(this), | 145 content::Source<PrintJob>(this), |
| 146 content::Details<JobEventDetails>(details.get())); | 146 content::Details<JobEventDetails>(details.get())); |
| 147 } | 147 } |
| 148 | 148 |
| 149 void PrintJob::Stop() { | 149 void PrintJob::Stop() { |
| 150 DCHECK(RunsTasksOnCurrentThread()); | 150 DCHECK(RunsTasksInCurrentSequence()); |
| 151 | 151 |
| 152 if (quit_factory_.HasWeakPtrs()) { | 152 if (quit_factory_.HasWeakPtrs()) { |
| 153 // In case we're running a nested run loop to wait for a job to finish, | 153 // In case we're running a nested run loop to wait for a job to finish, |
| 154 // and we finished before the timeout, quit the nested loop right away. | 154 // and we finished before the timeout, quit the nested loop right away. |
| 155 Quit(); | 155 Quit(); |
| 156 quit_factory_.InvalidateWeakPtrs(); | 156 quit_factory_.InvalidateWeakPtrs(); |
| 157 } | 157 } |
| 158 | 158 |
| 159 // Be sure to live long enough. | 159 // Be sure to live long enough. |
| 160 scoped_refptr<PrintJob> handle(this); | 160 scoped_refptr<PrintJob> handle(this); |
| 161 | 161 |
| 162 if (worker_->IsRunning()) { | 162 if (worker_->IsRunning()) { |
| 163 ControlledWorkerShutdown(); | 163 ControlledWorkerShutdown(); |
| 164 } else { | 164 } else { |
| 165 // Flush the cached document. | 165 // Flush the cached document. |
| 166 is_job_pending_ = false; | 166 is_job_pending_ = false; |
| 167 UpdatePrintedDocument(nullptr); | 167 UpdatePrintedDocument(nullptr); |
| 168 } | 168 } |
| 169 } | 169 } |
| 170 | 170 |
| 171 void PrintJob::Cancel() { | 171 void PrintJob::Cancel() { |
| 172 if (is_canceling_) | 172 if (is_canceling_) |
| 173 return; | 173 return; |
| 174 is_canceling_ = true; | 174 is_canceling_ = true; |
| 175 | 175 |
| 176 // Be sure to live long enough. | 176 // Be sure to live long enough. |
| 177 scoped_refptr<PrintJob> handle(this); | 177 scoped_refptr<PrintJob> handle(this); |
| 178 | 178 |
| 179 DCHECK(RunsTasksOnCurrentThread()); | 179 DCHECK(RunsTasksInCurrentSequence()); |
| 180 if (worker_ && worker_->IsRunning()) { | 180 if (worker_ && worker_->IsRunning()) { |
| 181 // Call this right now so it renders the context invalid. Do not use | 181 // Call this right now so it renders the context invalid. Do not use |
| 182 // InvokeLater since it would take too much time. | 182 // InvokeLater since it would take too much time. |
| 183 worker_->Cancel(); | 183 worker_->Cancel(); |
| 184 } | 184 } |
| 185 // Make sure a Cancel() is broadcast. | 185 // Make sure a Cancel() is broadcast. |
| 186 scoped_refptr<JobEventDetails> details( | 186 scoped_refptr<JobEventDetails> details( |
| 187 new JobEventDetails(JobEventDetails::FAILED, 0, nullptr, nullptr)); | 187 new JobEventDetails(JobEventDetails::FAILED, 0, nullptr, nullptr)); |
| 188 content::NotificationService::current()->Notify( | 188 content::NotificationService::current()->Notify( |
| 189 chrome::NOTIFICATION_PRINT_JOB_EVENT, | 189 chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 | 411 |
| 412 scoped_refptr<JobEventDetails> details(new JobEventDetails( | 412 scoped_refptr<JobEventDetails> details(new JobEventDetails( |
| 413 JobEventDetails::JOB_DONE, 0, document_.get(), nullptr)); | 413 JobEventDetails::JOB_DONE, 0, document_.get(), nullptr)); |
| 414 content::NotificationService::current()->Notify( | 414 content::NotificationService::current()->Notify( |
| 415 chrome::NOTIFICATION_PRINT_JOB_EVENT, | 415 chrome::NOTIFICATION_PRINT_JOB_EVENT, |
| 416 content::Source<PrintJob>(this), | 416 content::Source<PrintJob>(this), |
| 417 content::Details<JobEventDetails>(details.get())); | 417 content::Details<JobEventDetails>(details.get())); |
| 418 } | 418 } |
| 419 | 419 |
| 420 void PrintJob::ControlledWorkerShutdown() { | 420 void PrintJob::ControlledWorkerShutdown() { |
| 421 DCHECK(RunsTasksOnCurrentThread()); | 421 DCHECK(RunsTasksInCurrentSequence()); |
| 422 | 422 |
| 423 // The deadlock this code works around is specific to window messaging on | 423 // The deadlock this code works around is specific to window messaging on |
| 424 // Windows, so we aren't likely to need it on any other platforms. | 424 // Windows, so we aren't likely to need it on any other platforms. |
| 425 #if defined(OS_WIN) | 425 #if defined(OS_WIN) |
| 426 // We could easily get into a deadlock case if worker_->Stop() is used; the | 426 // We could easily get into a deadlock case if worker_->Stop() is used; the |
| 427 // printer driver created a window as a child of the browser window. By | 427 // printer driver created a window as a child of the browser window. By |
| 428 // canceling the job, the printer driver initiated dialog box is destroyed, | 428 // canceling the job, the printer driver initiated dialog box is destroyed, |
| 429 // which sends a blocking message to its parent window. If the browser window | 429 // which sends a blocking message to its parent window. If the browser window |
| 430 // thread is not processing messages, a deadlock occurs. | 430 // thread is not processing messages, a deadlock occurs. |
| 431 // | 431 // |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 : document_(document), page_(page), type_(type), job_id_(job_id) {} | 476 : document_(document), page_(page), type_(type), job_id_(job_id) {} |
| 477 | 477 |
| 478 JobEventDetails::~JobEventDetails() { | 478 JobEventDetails::~JobEventDetails() { |
| 479 } | 479 } |
| 480 | 480 |
| 481 PrintedDocument* JobEventDetails::document() const { return document_.get(); } | 481 PrintedDocument* JobEventDetails::document() const { return document_.get(); } |
| 482 | 482 |
| 483 PrintedPage* JobEventDetails::page() const { return page_.get(); } | 483 PrintedPage* JobEventDetails::page() const { return page_.get(); } |
| 484 | 484 |
| 485 } // namespace printing | 485 } // namespace printing |
| OLD | NEW |