Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: chrome/service/cloud_print/print_system_cups.cc

Issue 9693064: ScopedPrinterInfoSetter on crash prone blocks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/service/cloud_print/print_system.h" 5 #include "chrome/service/cloud_print/print_system.h"
6 6
7 #include <cups/cups.h> 7 #include <cups/cups.h>
8 #include <dlfcn.h> 8 #include <dlfcn.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <pthread.h> 10 #include <pthread.h>
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 233
234 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherCUPS); 234 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherCUPS);
235 }; 235 };
236 236
237 class PrinterWatcherCUPS 237 class PrinterWatcherCUPS
238 : public PrintSystem::PrinterWatcher { 238 : public PrintSystem::PrinterWatcher {
239 public: 239 public:
240 PrinterWatcherCUPS(PrintSystemCUPS* print_system, 240 PrinterWatcherCUPS(PrintSystemCUPS* print_system,
241 const std::string& printer_name) 241 const std::string& printer_name)
242 : printer_name_(printer_name), 242 : printer_name_(printer_name),
243 delegate_(NULL), 243 delegate_(NULL),
Albert Bodenhamer 2012/03/13 23:57:39 why is this changed?
Vitaly Buka (NO REVIEWS) 2012/03/14 00:11:20 It was attempt to fix style, but still incorrectly
244 print_system_(print_system) { 244 print_system_(print_system) {
245 } 245 }
246 246
247 ~PrinterWatcherCUPS() { 247 ~PrinterWatcherCUPS() {
248 StopWatching(); 248 StopWatching();
249 } 249 }
250 250
251 // PrintSystem::PrinterWatcher implementation. 251 // PrintSystem::PrinterWatcher implementation.
252 virtual bool StartWatching( 252 virtual bool StartWatching(
253 PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE{ 253 PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE{
254 scoped_refptr<printing::PrintBackend> print_backend(
255 printing::PrintBackend::CreateInstance(NULL));
256 child_process_logging::ScopedPrinterInfoSetter prn_info(
257 print_backend->GetPrinterDriverInfo(printer_name));
254 if (delegate_ != NULL) 258 if (delegate_ != NULL)
255 StopWatching(); 259 StopWatching();
256 delegate_ = delegate; 260 delegate_ = delegate;
257 settings_hash_ = GetSettingsHash(); 261 settings_hash_ = GetSettingsHash();
258 // Schedule next job status update. 262 // Schedule next job status update.
259 MessageLoop::current()->PostDelayedTask( 263 MessageLoop::current()->PostDelayedTask(
260 FROM_HERE, 264 FROM_HERE,
261 base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this), 265 base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this),
262 base::TimeDelta::FromSeconds(kJobUpdateTimeoutSeconds)); 266 base::TimeDelta::FromSeconds(kJobUpdateTimeoutSeconds));
263 // Schedule next printer check. 267 // Schedule next printer check.
264 // TODO(gene): Randomize time for the next printer update. 268 // TODO(gene): Randomize time for the next printer update.
265 MessageLoop::current()->PostDelayedTask( 269 MessageLoop::current()->PostDelayedTask(
266 FROM_HERE, 270 FROM_HERE,
267 base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this), 271 base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this),
268 print_system_->GetUpdateTimeout()); 272 print_system_->GetUpdateTimeout());
269 return true; 273 return true;
270 } 274 }
271 275
272 virtual bool StopWatching() OVERRIDE{ 276 virtual bool StopWatching() OVERRIDE{
273 delegate_ = NULL; 277 delegate_ = NULL;
274 return true; 278 return true;
275 } 279 }
276 280
277 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { 281 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
278 DCHECK(printer_info); 282 DCHECK(printer_info);
279 return print_system_->GetPrinterInfo(printer_name_, printer_info); 283 return print_system_->GetPrinterInfo(printer_name_, printer_info);
280 } 284 }
281 285
282 void JobStatusUpdate() {
283 if (delegate_ == NULL)
284 return; // Orphan call. We have been stopped already.
285 // For CUPS proxy, we are going to fire OnJobChanged notification
286 // periodically. Higher level will check if there are any outstanding
287 // jobs for this printer and check their status. If printer has no
288 // outstanding jobs, OnJobChanged() will do nothing.
289 delegate_->OnJobChanged();
290 MessageLoop::current()->PostDelayedTask(
291 FROM_HERE,
292 base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this),
293 base::TimeDelta::FromSeconds(kJobUpdateTimeoutSeconds));
294 }
295
296 void PrinterUpdate() {
297 if (delegate_ == NULL)
298 return; // Orphan call. We have been stopped already.
299 VLOG(1) << "CP_CUPS: Checking for printer updates: " << printer_name_;
300 if (print_system_->NotifyDelete() &&
301 !print_system_->IsValidPrinter(printer_name_)) {
302 delegate_->OnPrinterDeleted();
303 VLOG(1) << "CP_CUPS: Printer deleted: " << printer_name_;
304 } else {
305 std::string new_hash = GetSettingsHash();
306 if (settings_hash_ != new_hash) {
307 settings_hash_ = new_hash;
308 delegate_->OnPrinterChanged();
309 VLOG(1) << "CP_CUPS: Printer update detected for: " << printer_name_;
310 }
311 }
312 MessageLoop::current()->PostDelayedTask(
313 FROM_HERE,
314 base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this),
315 print_system_->GetUpdateTimeout());
316 }
317
318 private: 286 private:
319 std::string GetSettingsHash() { 287 std::string GetSettingsHash() {
320 printing::PrinterBasicInfo info; 288 printing::PrinterBasicInfo info;
321 if (!print_system_->GetPrinterInfo(printer_name_, &info)) 289 if (!print_system_->GetPrinterInfo(printer_name_, &info))
322 return std::string(); 290 return std::string();
323 291
324 printing::PrinterCapsAndDefaults caps; 292 printing::PrinterCapsAndDefaults caps;
325 if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps)) 293 if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps))
326 return std::string(); 294 return std::string();
327 295
328 std::string to_hash(info.printer_name); 296 std::string to_hash(info.printer_name);
329 to_hash += info.printer_description; 297 to_hash += info.printer_description;
330 std::map<std::string, std::string>::const_iterator it; 298 std::map<std::string, std::string>::const_iterator it;
331 for (it = info.options.begin(); it != info.options.end(); ++it) { 299 for (it = info.options.begin(); it != info.options.end(); ++it) {
332 to_hash += it->first; 300 to_hash += it->first;
333 to_hash += it->second; 301 to_hash += it->second;
334 } 302 }
335 303
336 to_hash += caps.printer_capabilities; 304 to_hash += caps.printer_capabilities;
337 to_hash += caps.caps_mime_type; 305 to_hash += caps.caps_mime_type;
338 to_hash += caps.printer_defaults; 306 to_hash += caps.printer_defaults;
339 to_hash += caps.defaults_mime_type; 307 to_hash += caps.defaults_mime_type;
340 308
341 return base::MD5String(to_hash); 309 return base::MD5String(to_hash);
342 } 310 }
343
344 std::string printer_name_; 311 std::string printer_name_;
345 PrintSystem::PrinterWatcher::Delegate* delegate_; 312 PrintSystem::PrinterWatcher::Delegate* delegate_;
346 scoped_refptr<PrintSystemCUPS> print_system_; 313 scoped_refptr<PrintSystemCUPS> print_system_;
347 std::string settings_hash_; 314 std::string settings_hash_;
348 315
349 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherCUPS); 316 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherCUPS);
350 }; 317 };
351 318
352 class JobSpoolerCUPS : public PrintSystem::JobSpooler { 319 class JobSpoolerCUPS : public PrintSystem::JobSpooler {
353 public: 320 public:
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 472
506 bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, 473 bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name,
507 const std::string& print_ticket_data) { 474 const std::string& print_ticket_data) {
508 DCHECK(initialized_); 475 DCHECK(initialized_);
509 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data, 476 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data,
510 false)); 477 false));
511 return ticket_value != NULL && ticket_value->IsType(Value::TYPE_DICTIONARY); 478 return ticket_value != NULL && ticket_value->IsType(Value::TYPE_DICTIONARY);
512 } 479 }
513 480
514 // Print ticket on linux is a JSON string containing only one dictionary. 481 // Print ticket on linux is a JSON string containing only one dictionary.
515 bool PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket, 482 bool PrintSystemCUPS::ParsePrintTicket(
516 std::map<std::string, std::string>* options) { 483 const std::string& print_ticket,
484 std::map<std::string, std::string>* options) {
517 DCHECK(options); 485 DCHECK(options);
518 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket, false)); 486 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket, false));
519 if (ticket_value == NULL || !ticket_value->IsType(Value::TYPE_DICTIONARY)) 487 if (ticket_value == NULL || !ticket_value->IsType(Value::TYPE_DICTIONARY))
520 return false; 488 return false;
521 489
522 options->clear(); 490 options->clear();
523 DictionaryValue* ticket_dict = 491 DictionaryValue* ticket_dict =
524 static_cast<DictionaryValue*>(ticket_value.get()); 492 static_cast<DictionaryValue*>(ticket_value.get());
525 DictionaryValue::key_iterator it(ticket_dict->begin_keys()); 493 DictionaryValue::key_iterator it(ticket_dict->begin_keys());
526 for (; it != ticket_dict->end_keys(); ++it) { 494 for (; it != ticket_dict->end_keys(); ++it) {
(...skipping 18 matching lines...) Expand all
545 return false; 513 return false;
546 514
547 PrintServerInfoCUPS::CapsMap::iterator caps_it = 515 PrintServerInfoCUPS::CapsMap::iterator caps_it =
548 server_info->caps_cache.find(printer_name); 516 server_info->caps_cache.find(printer_name);
549 if (caps_it != server_info->caps_cache.end()) { 517 if (caps_it != server_info->caps_cache.end()) {
550 *printer_info = caps_it->second; 518 *printer_info = caps_it->second;
551 return true; 519 return true;
552 } 520 }
553 521
554 // TODO(gene): Retry multiple times in case of error. 522 // TODO(gene): Retry multiple times in case of error.
523 child_process_logging::ScopedPrinterInfoSetter prn_info(server_info->backend-> GetPrinterDriverInfo());
Albert Bodenhamer 2012/03/13 23:57:39 80 chars
Vitaly Buka (NO REVIEWS) 2012/03/14 00:11:20 Done.
555 if (!server_info->backend->GetPrinterCapsAndDefaults(short_printer_name, 524 if (!server_info->backend->GetPrinterCapsAndDefaults(short_printer_name,
556 printer_info) ) { 525 printer_info) ) {
557 return false; 526 return false;
558 } 527 }
559 528
560 server_info->caps_cache[printer_name] = *printer_info; 529 server_info->caps_cache[printer_name] = *printer_info;
561 return true; 530 return true;
562 } 531 }
563 532
564 bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name, 533 bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name,
565 PlatformJobId job_id, 534 PlatformJobId job_id,
566 PrintJobDetails *job_details) { 535 PrintJobDetails *job_details) {
567 DCHECK(initialized_); 536 DCHECK(initialized_);
568 DCHECK(job_details); 537 DCHECK(job_details);
569 538
570 std::string short_printer_name; 539 std::string short_printer_name;
571 PrintServerInfoCUPS* server_info = 540 PrintServerInfoCUPS* server_info =
572 FindServerByFullName(printer_name, &short_printer_name); 541 FindServerByFullName(printer_name, &short_printer_name);
573 if (!server_info) 542 if (!server_info)
574 return false; 543 return false;
575 544
545 child_process_logging::ScopedPrinterInfoSetter prn_info(
546 server_info->backend->GetPrinterDriverInfo());
576 cups_job_t* jobs = NULL; 547 cups_job_t* jobs = NULL;
577 int num_jobs = GetJobs(&jobs, server_info->url, 548 int num_jobs = GetJobs(&jobs, server_info->url,
578 short_printer_name.c_str(), 1, -1); 549 short_printer_name.c_str(), 1, -1);
579 bool error = (num_jobs == 0) && (cupsLastError() > IPP_OK_EVENTS_COMPLETE); 550 bool error = (num_jobs == 0) && (cupsLastError() > IPP_OK_EVENTS_COMPLETE);
580 if (error) { 551 if (error) {
581 VLOG(1) << "CP_CUPS: Error getting jobs from CUPS server. Printer:" 552 VLOG(1) << "CP_CUPS: Error getting jobs from CUPS server. Printer:"
582 << printer_name 553 << printer_name
583 << " Error: " 554 << " Error: "
584 << static_cast<int>(cupsLastError()); 555 << static_cast<int>(cupsLastError());
585 return false; 556 return false;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 bool* dry_run) { 702 bool* dry_run) {
732 DCHECK(initialized_); 703 DCHECK(initialized_);
733 VLOG(1) << "CP_CUPS: Spooling print job for: " << printer_name; 704 VLOG(1) << "CP_CUPS: Spooling print job for: " << printer_name;
734 705
735 std::string short_printer_name; 706 std::string short_printer_name;
736 PrintServerInfoCUPS* server_info = 707 PrintServerInfoCUPS* server_info =
737 FindServerByFullName(printer_name, &short_printer_name); 708 FindServerByFullName(printer_name, &short_printer_name);
738 if (!server_info) 709 if (!server_info)
739 return false; 710 return false;
740 711
712 child_process_logging::ScopedPrinterInfoSetter prn_info(
713 server_info->backend->GetPrinterDriverInfo(printer_name));
714
741 // We need to store options as char* string for the duration of the 715 // We need to store options as char* string for the duration of the
742 // cupsPrintFile2 call. We'll use map here to store options, since 716 // cupsPrintFile2 call. We'll use map here to store options, since
743 // Dictionary value from JSON parser returns wchat_t. 717 // Dictionary value from JSON parser returns wchat_t.
744 std::map<std::string, std::string> options; 718 std::map<std::string, std::string> options;
745 bool res = ParsePrintTicket(print_ticket, &options); 719 bool res = ParsePrintTicket(print_ticket, &options);
746 DCHECK(res); // If print ticket is invalid we still print using defaults. 720 DCHECK(res); // If print ticket is invalid we still print using defaults.
747 721
748 // Check if this is a dry run (test) job. 722 // Check if this is a dry run (test) job.
749 *dry_run = CloudPrintHelpers::IsDryRunJob(tags); 723 *dry_run = CloudPrintHelpers::IsDryRunJob(tags);
750 if (*dry_run) { 724 if (*dry_run) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 792
819 void PrintSystemCUPS::RunCapsCallback( 793 void PrintSystemCUPS::RunCapsCallback(
820 const PrinterCapsAndDefaultsCallback& callback, 794 const PrinterCapsAndDefaultsCallback& callback,
821 bool succeeded, 795 bool succeeded,
822 const std::string& printer_name, 796 const std::string& printer_name,
823 const printing::PrinterCapsAndDefaults& printer_info) { 797 const printing::PrinterCapsAndDefaults& printer_info) {
824 callback.Run(succeeded, printer_name, printer_info); 798 callback.Run(succeeded, printer_name, printer_info);
825 } 799 }
826 800
827 } // namespace cloud_print 801 } // namespace cloud_print
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698