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
3// found in the LICENSE file.
4
5#include "chrome/browser/printing/print_preview_data_service.h"
6
7#include "base/memory/ref_counted_memory.h"
8#include "base/memory/singleton.h"
9#include "base/stl_util.h"
10#include "printing/print_job_constants.h"
11
12// PrintPreviewDataStore stores data for preview workflow and preview printing
13// workflow.
14//
15// NOTE:
16//   This class stores a list of PDFs. The list |index| is zero-based and can
17// be |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete preview
18// document. The PDF stored at |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| is
19// optimized with font subsetting, compression, etc. PDF's stored at all other
20// indices are unoptimized.
21//
22// PrintPreviewDataStore owns the data and is responsible for freeing it when
23// either:
24//    a) There is a new data.
25//    b) When PrintPreviewDataStore is destroyed.
26//
27class PrintPreviewDataStore : public base::RefCounted<PrintPreviewDataStore> {
28 public:
29  PrintPreviewDataStore() {}
30
31  // Get the preview page for the specified |index|.
32  void GetPreviewDataForIndex(int index,
33                              scoped_refptr<base::RefCountedBytes>* data) {
34    if (IsInvalidIndex(index))
35      return;
36
37    PreviewPageDataMap::iterator it = page_data_map_.find(index);
38    if (it != page_data_map_.end())
39      *data = it->second.get();
40  }
41
42  // Set/Update the preview data entry for the specified |index|.
43  void SetPreviewDataForIndex(int index, const base::RefCountedBytes* data) {
44    if (IsInvalidIndex(index))
45      return;
46
47    page_data_map_[index] = const_cast<base::RefCountedBytes*>(data);
48  }
49
50  // Returns the available draft page count.
51  int GetAvailableDraftPageCount() {
52    int page_data_map_size = page_data_map_.size();
53    if (ContainsKey(page_data_map_, printing::COMPLETE_PREVIEW_DOCUMENT_INDEX))
54      page_data_map_size--;
55    return page_data_map_size;
56  }
57
58 private:
59  friend class base::RefCounted<PrintPreviewDataStore>;
60
61  // 1:1 relationship between page index and its associated preview data.
62  // Key: Page index is zero-based and can be
63  // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete preview
64  // document.
65  // Value: Preview data.
66  typedef std::map<int, scoped_refptr<base::RefCountedBytes> >
67      PreviewPageDataMap;
68
69  ~PrintPreviewDataStore() {}
70
71  static bool IsInvalidIndex(int index) {
72    return (index != printing::COMPLETE_PREVIEW_DOCUMENT_INDEX &&
73            index < printing::FIRST_PAGE_INDEX);
74  }
75
76  PreviewPageDataMap page_data_map_;
77
78  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDataStore);
79};
80
81// static
82PrintPreviewDataService* PrintPreviewDataService::GetInstance() {
83  return Singleton<PrintPreviewDataService>::get();
84}
85
86PrintPreviewDataService::PrintPreviewDataService() {
87}
88
89PrintPreviewDataService::~PrintPreviewDataService() {
90}
91
92void PrintPreviewDataService::GetDataEntry(
93    int32 preview_ui_id,
94    int index,
95    scoped_refptr<base::RefCountedBytes>* data_bytes) {
96  *data_bytes = NULL;
97  PreviewDataStoreMap::const_iterator it = data_store_map_.find(preview_ui_id);
98  if (it != data_store_map_.end())
99    it->second->GetPreviewDataForIndex(index, data_bytes);
100}
101
102void PrintPreviewDataService::SetDataEntry(
103    int32 preview_ui_id,
104    int index,
105    const base::RefCountedBytes* data_bytes) {
106  if (!ContainsKey(data_store_map_, preview_ui_id))
107    data_store_map_[preview_ui_id] = new PrintPreviewDataStore();
108
109  data_store_map_[preview_ui_id]->SetPreviewDataForIndex(index, data_bytes);
110}
111
112void PrintPreviewDataService::RemoveEntry(int32 preview_ui_id) {
113  data_store_map_.erase(preview_ui_id);
114}
115
116int PrintPreviewDataService::GetAvailableDraftPageCount(int32 preview_ui_id) {
117  PreviewDataStoreMap::const_iterator it = data_store_map_.find(preview_ui_id);
118  return (it == data_store_map_.end()) ?
119      0 : it->second->GetAvailableDraftPageCount();
120}
121