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"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/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"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "cloud_print/gcp20/prototype/gcp20_switches.h"
19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
20558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochnamespace {
21558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kDraftExpirationSec = 10;
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kLocalPrintJobExpirationSec = 20;
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kErrorTimeoutSec = 30;
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Errors simulation constants:
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const double kPaperJamProbability = 1.0;
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kTooManyDraftsTimeout = 10;
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const size_t kMaxDrafts = 5;
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
31558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst base::FilePath::CharType kJobsPath[] = FILE_PATH_LITERAL("printjobs");
32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ValidateTicket(const std::string& ticket) {
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)std::string GenerateId() {
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return base::StringToLowerASCII(base::GenerateGUID());
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
41558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}  // namespace
42558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct PrintJobHandler::LocalPrintJobExtended {
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobExtended(const LocalPrintJob& job, const std::string& ticket)
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : data(job),
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        ticket(ticket),
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        state(LocalPrintJob::STATE_DRAFT) {}
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobExtended() : state(LocalPrintJob::STATE_DRAFT) {}
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ~LocalPrintJobExtended() {}
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJob data;
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string ticket;
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJob::State state;
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration;
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct PrintJobHandler::LocalPrintJobDraft {
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobDraft() {}
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  LocalPrintJobDraft(const std::string& ticket, const base::Time& expiration)
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : ticket(ticket),
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        expiration(expiration) {}
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ~LocalPrintJobDraft() {}
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string ticket;
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration;
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using base::StringPrintf;
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPrintJobHandler::PrintJobHandler() {
71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPrintJobHandler::~PrintJobHandler() {
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::CreateResult PrintJobHandler::CreatePrintJob(
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& ticket,
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* job_id_out,
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // TODO(maksymb): Use base::TimeDelta for timeout values
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // TODO(maksymb): Use base::TimeDelta for timeout values
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* error_timeout_out,
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description) {
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ValidateTicket(ticket))
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::CREATE_INVALID_TICKET;
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Let's simulate at least some errors just for testing.
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (CommandLine::ForCurrentProcess()->HasSwitch(
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          switches::kSimulatePrintingErrors)) {
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (base::RandDouble() <= kPaperJamProbability) {
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *error_description = "Paper jam, try again";
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::CREATE_PRINTER_ERROR;
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (drafts.size() > kMaxDrafts) {  // Another simulation of error: business
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *error_timeout_out = kTooManyDraftsTimeout;
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::CREATE_PRINTER_BUSY;
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string id = GenerateId();
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  drafts[id] = LocalPrintJobDraft(
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ticket,
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Time::Now() + base::TimeDelta::FromSeconds(kDraftExpirationSec));
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&PrintJobHandler::ForgetDraft, AsWeakPtr(), id),
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::TimeDelta::FromSeconds(kDraftExpirationSec));
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *job_id_out = id;
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *expires_in_out = kDraftExpirationSec;
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return LocalPrintJob::CREATE_SUCCESS;
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::SaveResult PrintJobHandler::SaveLocalPrintJob(
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const LocalPrintJob& job,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* job_id_out,
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description_out,
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* timeout_out) {
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string id;
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int expires_in;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (CreatePrintJob(std::string(), &id, &expires_in,
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         timeout_out, error_description_out)) {
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_INVALID_TICKET:
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_SUCCESS;
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_PRINTER_BUSY:
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_PRINTER_BUSY;
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_PRINTER_ERROR:
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_PRINTER_ERROR;
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::CREATE_SUCCESS:
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *job_id_out = id;
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return CompleteLocalPrintJob(job, id, expires_in_out,
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   error_description_out, timeout_out);
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return LocalPrintJob::SAVE_SUCCESS;
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)LocalPrintJob::SaveResult PrintJobHandler::CompleteLocalPrintJob(
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const LocalPrintJob& job,
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& job_id,
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* expires_in_out,
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string* error_description_out,
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* timeout_out) {
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!drafts.count(job_id)) {
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *timeout_out = kErrorTimeoutSec;
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_INVALID_PRINT_JOB;
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string file_extension;
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(maksymb): Gather together this type checking with Printer
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // supported types in kCdd.
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (job.content_type == "application/pdf") {
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "pdf";
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (job.content_type == "image/pwg-raster") {
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "pwg";
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (job.content_type == "image/jpeg") {
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    file_extension = "jpg";
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    error_description_out->clear();
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_INVALID_DOCUMENT_TYPE;
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CompleteDraft(job_id, job);
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator current_job =
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      jobs.find(job_id);
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!SavePrintJob(current_job->second.data.content,
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    current_job->second.ticket,
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    base::Time::Now(),
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    StringPrintf("%s", job_id.c_str()),
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    current_job->second.data.job_name, file_extension)) {
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetJobState(job_id, LocalPrintJob::STATE_ABORTED);
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *error_description_out = "IO error";
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return LocalPrintJob::SAVE_PRINTER_ERROR;
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetJobState(job_id, LocalPrintJob::STATE_DONE);
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *expires_in_out = static_cast<int>(GetJobExpiration(job_id).InSeconds());
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return LocalPrintJob::SAVE_SUCCESS;
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool PrintJobHandler::GetJobState(const std::string& id,
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  LocalPrintJob::Info* info_out) {
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  using base::Time;
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobDraft>::iterator draft = drafts.find(id);
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (draft != drafts.end()) {
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->state = LocalPrintJob::STATE_DRAFT;
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->expires_in =
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        static_cast<int>((draft->second.expiration - Time::Now()).InSeconds());
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator job = jobs.find(id);
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (job != jobs.end()) {
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->state = job->second.state;
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    info_out->expires_in = static_cast<int>(GetJobExpiration(id).InSeconds());
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool PrintJobHandler::SavePrintJob(const std::string& content,
212558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                   const std::string& ticket,
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const base::Time& create_time,
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& id,
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& title,
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   const std::string& file_extension) {
217558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  VLOG(1) << "Printing printjob: \"" + title + "\"";
218558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  base::FilePath directory(kJobsPath);
219558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!base::DirectoryExists(directory) &&
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !base::CreateDirectory(directory)) {
222558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
223558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
224558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time::Exploded create_time_exploded;
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  create_time.UTCExplode(&create_time_exploded);
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::FilePath::StringType job_prefix =
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      StringPrintf(FILE_PATH_LITERAL("%.4d%.2d%.2d-%.2d%.2d%.2d_"),
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.year,
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.month,
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.day_of_month,
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.hour,
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.minute,
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   create_time_exploded.second);
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::CreateTemporaryDirInDir(directory, job_prefix, &directory)) {
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "Cannot create directory for " << job_prefix;
237558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
238558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
239558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int written = base::WriteFile(directory.AppendASCII("ticket.xml"),
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                ticket.data(),
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                static_cast<int>(ticket.size()));
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (static_cast<size_t>(written) != ticket.size()) {
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    LOG(WARNING) << "Cannot save ticket.";
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
246558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  written = base::WriteFile(
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      directory.AppendASCII("data." + file_extension),
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      content.data(), static_cast<int>(content.size()));
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (static_cast<size_t>(written) != content.size()) {
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    LOG(WARNING) << "Cannot save data.";
253558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
254558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
255558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(0) << "Job saved at " << directory.value();
257558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return true;
258558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
259558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::SetJobState(const std::string& id,
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  LocalPrintJob::State state) {
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!drafts.count(id)) << "Draft should be completed at first";
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobExtended>::iterator job = jobs.find(id);
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(job != jobs.end());
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  job->second.state = state;
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (state) {
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_DRAFT:
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_ABORTED:
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case LocalPrintJob::STATE_DONE:
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      job->second.expiration =
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Time::Now() +
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec);
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::MessageLoop::current()->PostDelayedTask(
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          FROM_HERE,
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Bind(&PrintJobHandler::ForgetLocalJob, AsWeakPtr(), id),
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec));
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::CompleteDraft(const std::string& id,
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    const LocalPrintJob& job) {
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::map<std::string, LocalPrintJobDraft>::iterator draft = drafts.find(id);
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (draft != drafts.end()) {
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    jobs[id] = LocalPrintJobExtended(job, draft->second.ticket);
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    drafts.erase(draft);
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// TODO(maksymb): Use base::Time for expiration
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)base::TimeDelta PrintJobHandler::GetJobExpiration(const std::string& id) const {
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(jobs.count(id));
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::Time expiration = jobs.at(id).expiration;
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (expiration.is_null())
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return base::TimeDelta::FromSeconds(kLocalPrintJobExpirationSec);
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return expiration - base::Time::Now();
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::ForgetDraft(const std::string& id) {
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  drafts.erase(id);
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void PrintJobHandler::ForgetLocalJob(const std::string& id) {
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  jobs.erase(id);
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
311