print_job_handler.cc revision f2477e01787aa58f445919b809d89e252beef54f
1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// found in the LICENSE file.
4558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "cloud_print/gcp20/prototype/print_job_handler.h"
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/bind.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/command_line.h"
9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/file_util.h"
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/format_macros.h"
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/guid.h"
12558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/logging.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/message_loop/message_loop.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/rand_util.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/strings/string_util.h"
16558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/strings/stringprintf.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/time/time.h"
18558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochnamespace {
20558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kDraftExpirationSec = 10;
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kLocalPrintJobExpirationSec = 20;
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kErrorTimeoutSec = 30;
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Errors simulation constants:
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const double kPaperJamProbability = 1.0;
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kTooManyDraftsTimeout = 10;
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const size_t kMaxDrafts = 5;
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst base::FilePath::CharType kJobsPath[] = FILE_PATH_LITERAL("printjobs");
31558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ValidateTicket(const std::string& ticket) {
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)std::string GenerateId() {
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return StringToLowerASCII(base::GenerateGUID());
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
40558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}  // namespace
41558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct PrintJobHandler::LocalPrintJobExtended {
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobExtended(const LocalPrintJob& job, const std::string& ticket)
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : data(job),
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        ticket(ticket),
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        state(LocalPrintJob::STATE_DRAFT) {}
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobExtended() : state(LocalPrintJob::STATE_DRAFT) {}
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ~LocalPrintJobExtended() {}
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJob data;
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string ticket;
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJob::State state;
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration;
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct PrintJobHandler::LocalPrintJobDraft {
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobDraft() {}
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobDraft(const std::string& ticket, const base::Time& expiration)
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : ticket(ticket),
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        expiration(expiration) {}
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ~LocalPrintJobDraft() {}
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string ticket;
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration;
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using base::StringPrintf;
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPrintJobHandler::PrintJobHandler() {
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPrintJobHandler::~PrintJobHandler() {
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::CreateResult PrintJobHandler::CreatePrintJob(
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& ticket,
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* job_id_out,
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // TODO(maksymb): Use base::TimeDelta for timeout values
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // TODO(maksymb): Use base::TimeDelta for timeout values
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* error_timeout_out,
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description) {
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ValidateTicket(ticket))
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::CREATE_INVALID_TICKET;
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Let's simulate at least some errors just for testing.
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch("simulate-printing-errors")) {
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (base::RandDouble() <= kPaperJamProbability) {
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *error_description = "Paper jam, try again";
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::CREATE_PRINTER_ERROR;
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (drafts.size() > kMaxDrafts) {  // Another simulation of error: business
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *error_timeout_out = kTooManyDraftsTimeout;
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::CREATE_PRINTER_BUSY;
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string id = GenerateId();
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  drafts[id] = LocalPrintJobDraft(
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ticket,
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Time::Now() + base::TimeDelta::FromSeconds(kDraftExpirationSec));
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&PrintJobHandler::ForgetDraft, AsWeakPtr(), id),
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::TimeDelta::FromSeconds(kDraftExpirationSec));
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *job_id_out = id;
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *expires_in_out = kDraftExpirationSec;
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return LocalPrintJob::CREATE_SUCCESS;
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::SaveResult PrintJobHandler::SaveLocalPrintJob(
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const LocalPrintJob& job,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* job_id_out,
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description_out,
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* timeout_out) {
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string id;
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int expires_in;
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (CreatePrintJob(std::string(), &id, &expires_in,
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         timeout_out, error_description_out)) {
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_INVALID_TICKET:
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_SUCCESS;
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_PRINTER_BUSY:
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_PRINTER_BUSY;
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_PRINTER_ERROR:
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_PRINTER_ERROR;
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_SUCCESS:
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *job_id_out = id;
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return CompleteLocalPrintJob(job, id, expires_in_out,
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   error_description_out, timeout_out);
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_SUCCESS;
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::SaveResult PrintJobHandler::CompleteLocalPrintJob(
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const LocalPrintJob& job,
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& job_id,
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description_out,
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* timeout_out) {
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!drafts.count(job_id)) {
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *timeout_out = kErrorTimeoutSec;
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_INVALID_PRINT_JOB;
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string file_extension;
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(maksymb): Gather together this type checking with Printer
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // supported types in kCdd.
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (job.content_type == "application/pdf") {
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "pdf";
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (job.content_type == "image/pwg-raster") {
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "pwg";
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (job.content_type == "image/jpeg") {
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "jpg";
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    error_description_out->clear();
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_INVALID_DOCUMENT_TYPE;
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CompleteDraft(job_id, job);
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator current_job =
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      jobs.find(job_id);
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!SavePrintJob(current_job->second.data.content,
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    current_job->second.ticket,
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    base::Time::Now(),
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    StringPrintf("%s", job_id.c_str()),
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    current_job->second.data.job_name, file_extension)) {
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetJobState(job_id, LocalPrintJob::STATE_ABORTED);
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *error_description_out = "IO error";
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_PRINTER_ERROR;
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetJobState(job_id, LocalPrintJob::STATE_DONE);
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *expires_in_out = static_cast<int>(GetJobExpiration(job_id).InSeconds());
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return LocalPrintJob::SAVE_SUCCESS;
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool PrintJobHandler::GetJobState(const std::string& id,
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  LocalPrintJob::Info* info_out) {
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  using base::Time;
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobDraft>::iterator draft = drafts.find(id);
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (draft != drafts.end()) {
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->state = LocalPrintJob::STATE_DRAFT;
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->expires_in =
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        static_cast<int>((draft->second.expiration - Time::Now()).InSeconds());
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator job = jobs.find(id);
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (job != jobs.end()) {
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->state = job->second.state;
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->expires_in = static_cast<int>(GetJobExpiration(id).InSeconds());
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool PrintJobHandler::SavePrintJob(const std::string& content,
210558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                   const std::string& ticket,
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const base::Time& create_time,
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& id,
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& title,
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& file_extension) {
215558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  VLOG(1) << "Printing printjob: \"" + title + "\"";
216558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  base::FilePath directory(kJobsPath);
217558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!base::DirectoryExists(directory) &&
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !file_util::CreateDirectory(directory)) {
220558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
221558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
222558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time::Exploded create_time_exploded;
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  create_time.UTCExplode(&create_time_exploded);
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::FilePath::StringType job_prefix =
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      StringPrintf(FILE_PATH_LITERAL("%.4d%.2d%.2d-%.2d%.2d%.2d_"),
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.year,
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.month,
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.day_of_month,
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.hour,
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.minute,
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.second);
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!file_util::CreateTemporaryDirInDir(directory, job_prefix, &directory)) {
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "Cannot create directory for " << job_prefix;
235558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
236558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
237558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
238558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  int written = file_util::WriteFile(directory.AppendASCII("ticket.xml"),
239558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                     ticket.data(),
240558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                     static_cast<int>(ticket.size()));
241558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (static_cast<size_t>(written) != ticket.size()) {
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    LOG(WARNING) << "Cannot save ticket.";
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  written = file_util::WriteFile(
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      directory.AppendASCII("data." + file_extension),
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      content.data(), static_cast<int>(content.size()));
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (static_cast<size_t>(written) != content.size()) {
250558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    LOG(WARNING) << "Cannot save data.";
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
253558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  LOG(INFO) << "Job saved at " << directory.value();
255558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return true;
256558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
257558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::SetJobState(const std::string& id,
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  LocalPrintJob::State state) {
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!drafts.count(id)) << "Draft should be completed at first";
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator job = jobs.find(id);
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(job != jobs.end());
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  job->second.state = state;
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (state) {
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_DRAFT:
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_ABORTED:
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_DONE:
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      job->second.expiration =
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Time::Now() +
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec);
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::MessageLoop::current()->PostDelayedTask(
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          FROM_HERE,
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Bind(&PrintJobHandler::ForgetLocalJob, AsWeakPtr(), id),
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec));
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::CompleteDraft(const std::string& id,
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    const LocalPrintJob& job) {
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobDraft>::iterator draft = drafts.find(id);
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (draft != drafts.end()) {
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    jobs[id] = LocalPrintJobExtended(job, draft->second.ticket);
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    drafts.erase(draft);
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// TODO(maksymb): Use base::Time for expiration
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)base::TimeDelta PrintJobHandler::GetJobExpiration(const std::string& id) const {
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(jobs.count(id));
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration = jobs.at(id).expiration;
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (expiration.is_null())
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec);
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return expiration - base::Time::Now();
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::ForgetDraft(const std::string& id) {
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  drafts.erase(id);
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::ForgetLocalJob(const std::string& id) {
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  jobs.erase(id);
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
309