| 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_worker.h" | 5 #include "chrome/browser/printing/print_job_worker.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/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 // We know that is is a PrintJob object in this circumstance. | 46 // We know that is is a PrintJob object in this circumstance. |
| 47 content::Source<PrintJob>(static_cast<PrintJob*>(print_job)), | 47 content::Source<PrintJob>(static_cast<PrintJob*>(print_job)), |
| 48 content::Details<JobEventDetails>(details)); | 48 content::Details<JobEventDetails>(details)); |
| 49 } | 49 } |
| 50 | 50 |
| 51 PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner) | 51 PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner) |
| 52 : Thread("Printing_Worker"), | 52 : Thread("Printing_Worker"), |
| 53 owner_(owner), | 53 owner_(owner), |
| 54 weak_factory_(this) { | 54 weak_factory_(this) { |
| 55 // The object is created in the IO thread. | 55 // The object is created in the IO thread. |
| 56 DCHECK_EQ(owner_->message_loop(), MessageLoop::current()); | 56 DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); |
| 57 | 57 |
| 58 printing_context_.reset(PrintingContext::Create( | 58 printing_context_.reset(PrintingContext::Create( |
| 59 g_browser_process->GetApplicationLocale())); | 59 g_browser_process->GetApplicationLocale())); |
| 60 } | 60 } |
| 61 | 61 |
| 62 PrintJobWorker::~PrintJobWorker() { | 62 PrintJobWorker::~PrintJobWorker() { |
| 63 // The object is normally deleted in the UI thread, but when the user | 63 // The object is normally deleted in the UI thread, but when the user |
| 64 // cancels printing or in the case of print preview, the worker is destroyed | 64 // cancels printing or in the case of print preview, the worker is destroyed |
| 65 // on the I/O thread. | 65 // on the I/O thread. |
| 66 DCHECK_EQ(owner_->message_loop(), MessageLoop::current()); | 66 DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); |
| 67 Stop(); | 67 Stop(); |
| 68 } | 68 } |
| 69 | 69 |
| 70 void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) { | 70 void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) { |
| 71 DCHECK(page_number_ == PageNumber::npos()); | 71 DCHECK(page_number_ == PageNumber::npos()); |
| 72 owner_ = new_owner; | 72 owner_ = new_owner; |
| 73 } | 73 } |
| 74 | 74 |
| 75 void PrintJobWorker::SetPrintDestination( | 75 void PrintJobWorker::SetPrintDestination( |
| 76 PrintDestinationInterface* destination) { | 76 PrintDestinationInterface* destination) { |
| 77 destination_ = destination; | 77 destination_ = destination; |
| 78 } | 78 } |
| 79 | 79 |
| 80 void PrintJobWorker::GetSettings(bool ask_user_for_settings, | 80 void PrintJobWorker::GetSettings(bool ask_user_for_settings, |
| 81 gfx::NativeView parent_view, | 81 gfx::NativeView parent_view, |
| 82 int document_page_count, | 82 int document_page_count, |
| 83 bool has_selection, | 83 bool has_selection, |
| 84 MarginType margin_type) { | 84 MarginType margin_type) { |
| 85 DCHECK_EQ(message_loop(), MessageLoop::current()); | 85 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 86 DCHECK_EQ(page_number_, PageNumber::npos()); | 86 DCHECK_EQ(page_number_, PageNumber::npos()); |
| 87 | 87 |
| 88 // Recursive task processing is needed for the dialog in case it needs to be | 88 // Recursive task processing is needed for the dialog in case it needs to be |
| 89 // destroyed by a task. | 89 // destroyed by a task. |
| 90 // TODO(thestig): This code is wrong. SetNestableTasksAllowed(true) is needed | 90 // TODO(thestig): This code is wrong. SetNestableTasksAllowed(true) is needed |
| 91 // on the thread where the PrintDlgEx is called, and definitely both calls | 91 // on the thread where the PrintDlgEx is called, and definitely both calls |
| 92 // should happen on the same thread. See http://crbug.com/73466 | 92 // should happen on the same thread. See http://crbug.com/73466 |
| 93 // MessageLoop::current()->SetNestableTasksAllowed(true); | 93 // MessageLoop::current()->SetNestableTasksAllowed(true); |
| 94 printing_context_->set_margin_type(margin_type); | 94 printing_context_->set_margin_type(margin_type); |
| 95 | 95 |
| 96 // When we delegate to a destination, we don't ask the user for settings. | 96 // When we delegate to a destination, we don't ask the user for settings. |
| 97 // TODO(mad): Ask the destination for settings. | 97 // TODO(mad): Ask the destination for settings. |
| 98 if (ask_user_for_settings && destination_.get() == NULL) { | 98 if (ask_user_for_settings && destination_.get() == NULL) { |
| 99 BrowserThread::PostTask( | 99 BrowserThread::PostTask( |
| 100 BrowserThread::UI, FROM_HERE, | 100 BrowserThread::UI, FROM_HERE, |
| 101 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), | 101 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), |
| 102 base::Bind(&PrintJobWorker::GetSettingsWithUI, | 102 base::Bind(&PrintJobWorker::GetSettingsWithUI, |
| 103 base::Unretained(this), parent_view, | 103 base::Unretained(this), parent_view, |
| 104 document_page_count, has_selection))); | 104 document_page_count, has_selection))); |
| 105 } else { | 105 } else { |
| 106 BrowserThread::PostTask( | 106 BrowserThread::PostTask( |
| 107 BrowserThread::UI, FROM_HERE, | 107 BrowserThread::UI, FROM_HERE, |
| 108 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), | 108 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), |
| 109 base::Bind(&PrintJobWorker::UseDefaultSettings, | 109 base::Bind(&PrintJobWorker::UseDefaultSettings, |
| 110 base::Unretained(this)))); | 110 base::Unretained(this)))); |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 void PrintJobWorker::SetSettings(const DictionaryValue* const new_settings) { | 114 void PrintJobWorker::SetSettings(const DictionaryValue* const new_settings) { |
| 115 DCHECK_EQ(message_loop(), MessageLoop::current()); | 115 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 116 | 116 |
| 117 BrowserThread::PostTask( | 117 BrowserThread::PostTask( |
| 118 BrowserThread::UI, FROM_HERE, | 118 BrowserThread::UI, FROM_HERE, |
| 119 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), | 119 base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), |
| 120 base::Bind(&PrintJobWorker::UpdatePrintSettings, | 120 base::Bind(&PrintJobWorker::UpdatePrintSettings, |
| 121 base::Unretained(this), new_settings))); | 121 base::Unretained(this), new_settings))); |
| 122 } | 122 } |
| 123 | 123 |
| 124 void PrintJobWorker::UpdatePrintSettings( | 124 void PrintJobWorker::UpdatePrintSettings( |
| 125 const DictionaryValue* const new_settings) { | 125 const DictionaryValue* const new_settings) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 base::Bind(&PrintJobWorker::GetSettingsDone, | 187 base::Bind(&PrintJobWorker::GetSettingsDone, |
| 188 base::Unretained(this), result))); | 188 base::Unretained(this), result))); |
| 189 } | 189 } |
| 190 | 190 |
| 191 void PrintJobWorker::UseDefaultSettings() { | 191 void PrintJobWorker::UseDefaultSettings() { |
| 192 PrintingContext::Result result = printing_context_->UseDefaultSettings(); | 192 PrintingContext::Result result = printing_context_->UseDefaultSettings(); |
| 193 GetSettingsDone(result); | 193 GetSettingsDone(result); |
| 194 } | 194 } |
| 195 | 195 |
| 196 void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { | 196 void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { |
| 197 DCHECK_EQ(message_loop(), MessageLoop::current()); | 197 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 198 DCHECK_EQ(page_number_, PageNumber::npos()); | 198 DCHECK_EQ(page_number_, PageNumber::npos()); |
| 199 DCHECK_EQ(document_, new_document); | 199 DCHECK_EQ(document_, new_document); |
| 200 DCHECK(document_.get()); | 200 DCHECK(document_.get()); |
| 201 DCHECK(new_document->settings().Equals(printing_context_->settings())); | 201 DCHECK(new_document->settings().Equals(printing_context_->settings())); |
| 202 | 202 |
| 203 if (!document_.get() || page_number_ != PageNumber::npos() || | 203 if (!document_.get() || page_number_ != PageNumber::npos() || |
| 204 document_ != new_document) { | 204 document_ != new_document) { |
| 205 return; | 205 return; |
| 206 } | 206 } |
| 207 | 207 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 221 // Try to print already cached data. It may already have been generated for | 221 // Try to print already cached data. It may already have been generated for |
| 222 // the print preview. | 222 // the print preview. |
| 223 OnNewPage(); | 223 OnNewPage(); |
| 224 // Don't touch this anymore since the instance could be destroyed. It happens | 224 // Don't touch this anymore since the instance could be destroyed. It happens |
| 225 // if all the pages are printed a one sweep and the client doesn't have a | 225 // if all the pages are printed a one sweep and the client doesn't have a |
| 226 // handle to us anymore. There's a timing issue involved between the worker | 226 // handle to us anymore. There's a timing issue involved between the worker |
| 227 // thread and the UI thread. Take no chance. | 227 // thread and the UI thread. Take no chance. |
| 228 } | 228 } |
| 229 | 229 |
| 230 void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) { | 230 void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) { |
| 231 DCHECK_EQ(message_loop(), MessageLoop::current()); | 231 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 232 DCHECK_EQ(page_number_, PageNumber::npos()); | 232 DCHECK_EQ(page_number_, PageNumber::npos()); |
| 233 DCHECK(!new_document || | 233 DCHECK(!new_document || |
| 234 new_document->settings().Equals(printing_context_->settings())); | 234 new_document->settings().Equals(printing_context_->settings())); |
| 235 | 235 |
| 236 if (page_number_ != PageNumber::npos()) | 236 if (page_number_ != PageNumber::npos()) |
| 237 return; | 237 return; |
| 238 | 238 |
| 239 document_ = new_document; | 239 document_ = new_document; |
| 240 } | 240 } |
| 241 | 241 |
| 242 void PrintJobWorker::OnNewPage() { | 242 void PrintJobWorker::OnNewPage() { |
| 243 if (!document_.get()) // Spurious message. | 243 if (!document_.get()) // Spurious message. |
| 244 return; | 244 return; |
| 245 | 245 |
| 246 // message_loop() could return NULL when the print job is cancelled. | 246 // message_loop() could return NULL when the print job is cancelled. |
| 247 DCHECK_EQ(message_loop(), MessageLoop::current()); | 247 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 248 | 248 |
| 249 if (page_number_ == PageNumber::npos()) { | 249 if (page_number_ == PageNumber::npos()) { |
| 250 // Find first page to print. | 250 // Find first page to print. |
| 251 int page_count = document_->page_count(); | 251 int page_count = document_->page_count(); |
| 252 if (!page_count) { | 252 if (!page_count) { |
| 253 // We still don't know how many pages the document contains. We can't | 253 // We still don't know how many pages the document contains. We can't |
| 254 // start to print the document yet since the header/footer may refer to | 254 // start to print the document yet since the header/footer may refer to |
| 255 // the document's page count. | 255 // the document's page count. |
| 256 return; | 256 return; |
| 257 } | 257 } |
| 258 // We have enough information to initialize page_number_. | 258 // We have enough information to initialize page_number_. |
| 259 page_number_.Init(document_->settings(), page_count); | 259 page_number_.Init(document_->settings(), page_count); |
| 260 if (destination_.get() != NULL) | 260 if (destination_.get() != NULL) |
| 261 destination_->SetPageCount(page_count); | 261 destination_->SetPageCount(page_count); |
| 262 } | 262 } |
| 263 DCHECK_NE(page_number_, PageNumber::npos()); | 263 DCHECK_NE(page_number_, PageNumber::npos()); |
| 264 | 264 |
| 265 while (true) { | 265 while (true) { |
| 266 // Is the page available? | 266 // Is the page available? |
| 267 scoped_refptr<PrintedPage> page; | 267 scoped_refptr<PrintedPage> page; |
| 268 if (!document_->GetPage(page_number_.ToInt(), &page)) { | 268 if (!document_->GetPage(page_number_.ToInt(), &page)) { |
| 269 // We need to wait for the page to be available. | 269 // We need to wait for the page to be available. |
| 270 MessageLoop::current()->PostDelayedTask( | 270 base::MessageLoop::current()->PostDelayedTask( |
| 271 FROM_HERE, | 271 FROM_HERE, |
| 272 base::Bind(&PrintJobWorker::OnNewPage, weak_factory_.GetWeakPtr()), | 272 base::Bind(&PrintJobWorker::OnNewPage, weak_factory_.GetWeakPtr()), |
| 273 base::TimeDelta::FromMilliseconds(500)); | 273 base::TimeDelta::FromMilliseconds(500)); |
| 274 break; | 274 break; |
| 275 } | 275 } |
| 276 // The page is there, print it. | 276 // The page is there, print it. |
| 277 SpoolPage(page); | 277 SpoolPage(page); |
| 278 ++page_number_; | 278 ++page_number_; |
| 279 if (page_number_ == PageNumber::npos()) { | 279 if (page_number_ == PageNumber::npos()) { |
| 280 OnDocumentDone(); | 280 OnDocumentDone(); |
| 281 // Don't touch this anymore since the instance could be destroyed. | 281 // Don't touch this anymore since the instance could be destroyed. |
| 282 break; | 282 break; |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 } | 285 } |
| 286 | 286 |
| 287 void PrintJobWorker::Cancel() { | 287 void PrintJobWorker::Cancel() { |
| 288 // This is the only function that can be called from any thread. | 288 // This is the only function that can be called from any thread. |
| 289 printing_context_->Cancel(); | 289 printing_context_->Cancel(); |
| 290 // Cannot touch any member variable since we don't know in which thread | 290 // Cannot touch any member variable since we don't know in which thread |
| 291 // context we run. | 291 // context we run. |
| 292 } | 292 } |
| 293 | 293 |
| 294 void PrintJobWorker::OnDocumentDone() { | 294 void PrintJobWorker::OnDocumentDone() { |
| 295 DCHECK_EQ(message_loop(), MessageLoop::current()); | 295 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 296 DCHECK_EQ(page_number_, PageNumber::npos()); | 296 DCHECK_EQ(page_number_, PageNumber::npos()); |
| 297 DCHECK(document_.get()); | 297 DCHECK(document_.get()); |
| 298 | 298 |
| 299 if (printing_context_->DocumentDone() != PrintingContext::OK) { | 299 if (printing_context_->DocumentDone() != PrintingContext::OK) { |
| 300 OnFailure(); | 300 OnFailure(); |
| 301 return; | 301 return; |
| 302 } | 302 } |
| 303 | 303 |
| 304 owner_->message_loop()->PostTask( | 304 owner_->message_loop()->PostTask( |
| 305 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), | 305 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), |
| 306 JobEventDetails::DOC_DONE, document_, | 306 JobEventDetails::DOC_DONE, document_, |
| 307 scoped_refptr<PrintedPage>())); | 307 scoped_refptr<PrintedPage>())); |
| 308 | 308 |
| 309 // Makes sure the variables are reinitialized. | 309 // Makes sure the variables are reinitialized. |
| 310 document_ = NULL; | 310 document_ = NULL; |
| 311 } | 311 } |
| 312 | 312 |
| 313 void PrintJobWorker::SpoolPage(PrintedPage* page) { | 313 void PrintJobWorker::SpoolPage(PrintedPage* page) { |
| 314 DCHECK_EQ(message_loop(), MessageLoop::current()); | 314 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 315 DCHECK_NE(page_number_, PageNumber::npos()); | 315 DCHECK_NE(page_number_, PageNumber::npos()); |
| 316 | 316 |
| 317 // Signal everyone that the page is about to be printed. | 317 // Signal everyone that the page is about to be printed. |
| 318 owner_->message_loop()->PostTask( | 318 owner_->message_loop()->PostTask( |
| 319 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), | 319 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), |
| 320 JobEventDetails::NEW_PAGE, document_, | 320 JobEventDetails::NEW_PAGE, document_, |
| 321 make_scoped_refptr(page))); | 321 make_scoped_refptr(page))); |
| 322 | 322 |
| 323 // Preprocess. | 323 // Preprocess. |
| 324 if (printing_context_->NewPage() != PrintingContext::OK) { | 324 if (printing_context_->NewPage() != PrintingContext::OK) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 353 | 353 |
| 354 // Signal everyone that the page is printed. | 354 // Signal everyone that the page is printed. |
| 355 owner_->message_loop()->PostTask( | 355 owner_->message_loop()->PostTask( |
| 356 FROM_HERE, | 356 FROM_HERE, |
| 357 base::Bind(NotificationCallback, make_scoped_refptr(owner_), | 357 base::Bind(NotificationCallback, make_scoped_refptr(owner_), |
| 358 JobEventDetails::PAGE_DONE, document_, | 358 JobEventDetails::PAGE_DONE, document_, |
| 359 make_scoped_refptr(page))); | 359 make_scoped_refptr(page))); |
| 360 } | 360 } |
| 361 | 361 |
| 362 void PrintJobWorker::OnFailure() { | 362 void PrintJobWorker::OnFailure() { |
| 363 DCHECK_EQ(message_loop(), MessageLoop::current()); | 363 DCHECK_EQ(message_loop(), base::MessageLoop::current()); |
| 364 | 364 |
| 365 // We may loose our last reference by broadcasting the FAILED event. | 365 // We may loose our last reference by broadcasting the FAILED event. |
| 366 scoped_refptr<PrintJobWorkerOwner> handle(owner_); | 366 scoped_refptr<PrintJobWorkerOwner> handle(owner_); |
| 367 | 367 |
| 368 owner_->message_loop()->PostTask( | 368 owner_->message_loop()->PostTask( |
| 369 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), | 369 FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), |
| 370 JobEventDetails::FAILED, document_, | 370 JobEventDetails::FAILED, document_, |
| 371 scoped_refptr<PrintedPage>())); | 371 scoped_refptr<PrintedPage>())); |
| 372 Cancel(); | 372 Cancel(); |
| 373 | 373 |
| 374 // Makes sure the variables are reinitialized. | 374 // Makes sure the variables are reinitialized. |
| 375 document_ = NULL; | 375 document_ = NULL; |
| 376 page_number_ = PageNumber::npos(); | 376 page_number_ = PageNumber::npos(); |
| 377 } | 377 } |
| 378 | 378 |
| 379 } // namespace printing | 379 } // namespace printing |
| OLD | NEW |