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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 } // namespace | 28 } // namespace |
29 | 29 |
30 namespace printing { | 30 namespace printing { |
31 | 31 |
32 PrintJob::PrintJob() | 32 PrintJob::PrintJob() |
33 : ui_message_loop_(MessageLoop::current()), | 33 : ui_message_loop_(MessageLoop::current()), |
34 source_(NULL), | 34 source_(NULL), |
35 worker_(), | 35 worker_(), |
36 settings_(), | 36 settings_(), |
37 is_job_pending_(false), | 37 is_job_pending_(false), |
38 is_canceling_(false) { | 38 is_canceling_(false), |
| 39 ALLOW_THIS_IN_INITIALIZER_LIST(quit_factory_(this)) { |
39 DCHECK(ui_message_loop_); | 40 DCHECK(ui_message_loop_); |
40 // This is normally a UI message loop, but in unit tests, the message loop is | 41 // This is normally a UI message loop, but in unit tests, the message loop is |
41 // of the 'default' type. | 42 // of the 'default' type. |
42 DCHECK(ui_message_loop_->type() == MessageLoop::TYPE_UI || | 43 DCHECK(ui_message_loop_->type() == MessageLoop::TYPE_UI || |
43 ui_message_loop_->type() == MessageLoop::TYPE_DEFAULT); | 44 ui_message_loop_->type() == MessageLoop::TYPE_DEFAULT); |
44 ui_message_loop_->AddDestructionObserver(this); | 45 ui_message_loop_->AddDestructionObserver(this); |
45 } | 46 } |
46 | 47 |
47 PrintJob::~PrintJob() { | 48 PrintJob::~PrintJob() { |
48 ui_message_loop_->RemoveDestructionObserver(this); | 49 ui_message_loop_->RemoveDestructionObserver(this); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), NULL)); | 142 new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), NULL)); |
142 content::NotificationService::current()->Notify( | 143 content::NotificationService::current()->Notify( |
143 chrome::NOTIFICATION_PRINT_JOB_EVENT, | 144 chrome::NOTIFICATION_PRINT_JOB_EVENT, |
144 content::Source<PrintJob>(this), | 145 content::Source<PrintJob>(this), |
145 content::Details<JobEventDetails>(details.get())); | 146 content::Details<JobEventDetails>(details.get())); |
146 } | 147 } |
147 | 148 |
148 void PrintJob::Stop() { | 149 void PrintJob::Stop() { |
149 DCHECK_EQ(ui_message_loop_, MessageLoop::current()); | 150 DCHECK_EQ(ui_message_loop_, MessageLoop::current()); |
150 | 151 |
| 152 if (quit_factory_.HasWeakPtrs()) { |
| 153 // In case we're running a nested message loop to wait for a job to finish, |
| 154 // and we finished before the timeout, quit the nested loop right away. |
| 155 Quit(); |
| 156 quit_factory_.InvalidateWeakPtrs(); |
| 157 } |
| 158 |
151 // Be sure to live long enough. | 159 // Be sure to live long enough. |
152 scoped_refptr<PrintJob> handle(this); | 160 scoped_refptr<PrintJob> handle(this); |
153 | 161 |
154 MessageLoop* worker_loop = worker_->message_loop(); | 162 MessageLoop* worker_loop = worker_->message_loop(); |
155 if (worker_loop) { | 163 if (worker_loop) { |
156 ControlledWorkerShutdown(); | 164 ControlledWorkerShutdown(); |
157 | 165 |
158 is_job_pending_ = false; | 166 is_job_pending_ = false; |
159 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, | 167 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, |
160 content::Source<PrintJob>(this)); | 168 content::Source<PrintJob>(this)); |
(...skipping 25 matching lines...) Expand all Loading... |
186 content::Source<PrintJob>(this), | 194 content::Source<PrintJob>(this), |
187 content::Details<JobEventDetails>(details.get())); | 195 content::Details<JobEventDetails>(details.get())); |
188 Stop(); | 196 Stop(); |
189 is_canceling_ = false; | 197 is_canceling_ = false; |
190 } | 198 } |
191 | 199 |
192 bool PrintJob::FlushJob(int timeout_ms) { | 200 bool PrintJob::FlushJob(int timeout_ms) { |
193 // Make sure the object outlive this message loop. | 201 // Make sure the object outlive this message loop. |
194 scoped_refptr<PrintJob> handle(this); | 202 scoped_refptr<PrintJob> handle(this); |
195 | 203 |
196 // Stop() will eventually be called, which will get out of the inner message | 204 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
197 // loop. But, don't take it for granted and set a timer in case something goes | 205 base::Bind(&PrintJob::Quit, quit_factory_.GetWeakPtr()), timeout_ms); |
198 // wrong. | |
199 base::OneShotTimer<MessageLoop> quit_task; | |
200 if (timeout_ms) { | |
201 quit_task.Start(FROM_HERE, TimeDelta::FromMilliseconds(timeout_ms), | |
202 MessageLoop::current(), &MessageLoop::Quit); | |
203 } | |
204 | 206 |
205 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); | 207 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); |
206 MessageLoop::current()->Run(); | 208 MessageLoop::current()->Run(); |
207 | 209 |
208 return true; | 210 return true; |
209 } | 211 } |
210 | 212 |
211 void PrintJob::DisconnectSource() { | 213 void PrintJob::DisconnectSource() { |
212 source_ = NULL; | 214 source_ = NULL; |
213 if (document_.get()) | 215 if (document_.get()) |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 #endif | 343 #endif |
342 | 344 |
343 // Temporarily allow it until we fix | 345 // Temporarily allow it until we fix |
344 // http://code.google.com/p/chromium/issues/detail?id=67044 | 346 // http://code.google.com/p/chromium/issues/detail?id=67044 |
345 base::ThreadRestrictions::ScopedAllowIO allow_io; | 347 base::ThreadRestrictions::ScopedAllowIO allow_io; |
346 | 348 |
347 // Now make sure the thread object is cleaned up. | 349 // Now make sure the thread object is cleaned up. |
348 worker_->Stop(); | 350 worker_->Stop(); |
349 } | 351 } |
350 | 352 |
| 353 void PrintJob::Quit() { |
| 354 MessageLoop::current()->Quit(); |
| 355 } |
| 356 |
351 // Takes settings_ ownership and will be deleted in the receiving thread. | 357 // Takes settings_ ownership and will be deleted in the receiving thread. |
352 JobEventDetails::JobEventDetails(Type type, | 358 JobEventDetails::JobEventDetails(Type type, |
353 PrintedDocument* document, | 359 PrintedDocument* document, |
354 PrintedPage* page) | 360 PrintedPage* page) |
355 : document_(document), | 361 : document_(document), |
356 page_(page), | 362 page_(page), |
357 type_(type) { | 363 type_(type) { |
358 } | 364 } |
359 | 365 |
360 JobEventDetails::~JobEventDetails() { | 366 JobEventDetails::~JobEventDetails() { |
361 } | 367 } |
362 | 368 |
363 PrintedDocument* JobEventDetails::document() const { | 369 PrintedDocument* JobEventDetails::document() const { |
364 return document_; | 370 return document_; |
365 } | 371 } |
366 | 372 |
367 PrintedPage* JobEventDetails::page() const { | 373 PrintedPage* JobEventDetails::page() const { |
368 return page_; | 374 return page_; |
369 } | 375 } |
370 | 376 |
371 } // namespace printing | 377 } // namespace printing |
OLD | NEW |