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

Side by Side Diff: chromeos/printing/ppd_cache.cc

Issue 2343983004: Add PPDProvider barebones implementation and associated cache skeleton. (Closed)
Patch Set: Initial PPDProvider/PPDCache implementation. Also, add associated unittests. This doesn't plumb th… Created 4 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2016 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 "chromeos/printing/ppd_cache.h"
6
7 #include "base/files/file_util.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/path_service.h"
10 #include "base/strings/stringprintf.h"
11 #include "chromeos/chromeos_paths.h"
12
13 using base::FilePath;
14 using base::Optional;
15 using std::string;
16 using std::unique_ptr;
17
18 namespace chromeos {
19 namespace printing {
20 namespace {
21
22 // Limits on key strings we'll accept. This limit is pretty arbitrary, we
23 // just don't want to accept strings that are so long they might cause
24 // memory pressure or somesuch.
25 constexpr int kKeySizeLimit = 512;
26
27 // "Manufacturer" used when storing and retrieving locally-keyed
28 // files.
29 const char* kLocalModel = "local";
skau 2016/10/07 16:29:06 const char[] for string constants
Carlson 2016/10/14 19:28:56 OK, but any particular reason why?
skau 2016/10/14 22:10:16 Consistency. It looks to be the common interpreta
30
31 // Placeholder cache.
32 class PPDCacheImpl : public PPDCache {
33 public:
34 PPDCacheImpl(const PPDCache::Options& options)
35 : cache_base_dir_(GetCacheBaseDirOrDie()) {}
36 ~PPDCacheImpl() override {}
37
38 // Public API functions.
39 Optional<FilePath> Find(const string& manufacturer,
40 const string& model) const override {
41 Optional<FilePath> ret;
42 if (model == kLocalModel) {
43 LOG(ERROR) << "Denying attempt to store auto-ppd under local namespace";
skau 2016/10/07 16:29:06 Denying attempt to retrieve local ppd from auto na
Carlson 2016/10/14 19:28:56 Obsolete
44 return ret;
45 }
46 if (!(KeyIsValid("Printer manufacturer", manufacturer) &&
skau 2016/10/07 16:29:06 Is "Printer manufacturer" a constant?
Carlson 2016/10/14 19:28:56 Obsolete
47 KeyIsValid("Printer model", model))) {
48 return ret;
49 }
50
51 FilePath contents_path = GetCachePath(manufacturer, model);
52 if (base::PathExists(contents_path)) {
53 ret = contents_path;
54 }
55 return ret;
56 }
57
58 Optional<FilePath> FindLocal(const string& key) const override {
59 Optional<FilePath> ret;
60 if (!KeyIsValid("Printer identifier", key)) {
61 return ret;
62 }
63 FilePath contents_path = GetCachePath(kLocalModel, key);
64 if (base::PathExists(contents_path)) {
65 ret = contents_path;
66 }
67 return ret;
68 }
69
70 // Store a ppd that was manually added by a user, using the given key.
71 Optional<FilePath> StoreLocal(
72 const string& key,
73 const string& compressed_ppd_contents) override {
74 if (!KeyIsValid("Printer identifier", key)) {
75 return Optional<FilePath>();
76 }
77 return StoreCommon(kLocalModel, key, compressed_ppd_contents);
78 }
79
80 Optional<FilePath> Store(const string& manufacturer,
81 const string& model,
82 const string& compressed_ppd_contents) override {
83 if (model == kLocalModel) {
84 LOG(ERROR) << "Denying attempt to store auto-ppd under local namespace";
85 return Optional<FilePath>();
86 }
87 if (!(KeyIsValid("Printer manufacturer", manufacturer) &&
88 KeyIsValid("Printer model", model))) {
89 return Optional<FilePath>();
90 }
91 return StoreCommon(manufacturer, model, compressed_ppd_contents);
92 }
93
94 private:
95 // Shared Store* functionality. This can assume that all arguments have been
96 // pre-vetted and are valid.
97 Optional<FilePath> StoreCommon(const string& manufacturer,
98 const string& model,
99 const string& compressed_ppd_contents) {
100 Optional<FilePath> ret;
101 FilePath contents_path = GetCachePath(manufacturer, model);
102 if (base::WriteFile(contents_path, compressed_ppd_contents.data(),
103 compressed_ppd_contents.size()) ==
104 static_cast<int>(compressed_ppd_contents.size())) {
105 ret = contents_path;
106 } else {
107 LOG(ERROR) << "Failed to write " << compressed_ppd_contents.size()
108 << " bytes to " << contents_path.LossyDisplayName();
109 // Try to clean up the file, as it may have partial contents. Note that
110 // DeleteFile(nonexistant file) should return true, so failure here means
111 // something is exceptionally hosed.
112 if (!base::DeleteFile(contents_path, false)) {
113 LOG(FATAL) << "Failed to cleanup partially-written file "
skau 2016/10/07 16:29:06 LOG(FATAL) will crash Chrome and thus the entire U
Carlson 2016/10/14 19:28:56 Done.
114 << contents_path.LossyDisplayName();
115 }
116 }
117 return ret;
118 }
119
120 // File paths are generated via hashes of the manufacturer/model strings.
121 // This isn't because we're overly worried about collisions; rather, using the
122 // hash instead of the strings directly means we don't have to do any fiddly
123 // path escaping, stress about unicode concerns, or worry overmuch about path
124 // length limits.
125 FilePath GetCachePath(const string& manufacturer, const string& model) const {
126 size_t h = base::HashInts64(std::hash<std::string>()(manufacturer),
127 std::hash<std::string>()(model));
128 return cache_base_dir_.Append(base::StringPrintf("%zx", h));
skau 2016/10/07 16:29:06 Can we attach an appropriate file extension like .
Carlson 2016/10/14 19:28:56 Done.
129 }
130
131 // Return whether or not the given cache key is valid. Log an error
132 // describing the problem if it's not valid.
133 bool KeyIsValid(const string& key_name, const string& key) const {
skau 2016/10/07 16:29:06 Is there a way to clarify that this validation is
Carlson 2016/10/14 19:28:56 Obsolete
134 if (key.empty()) {
135 LOG(ERROR) << key_name << " cannot be empty.";
136 return false;
137 }
138 if (key.size() > kKeySizeLimit) {
139 LOG(ERROR) << key_name << " is too long. Limit is " << kKeySizeLimit;
140 return false;
141 }
142 return true;
143 }
144
145 // Retrieve the printer cache filepath from PathService, or die trying.
146 FilePath GetCacheBaseDirOrDie() const {
147 FilePath ret;
148 if (!PathService::Get(::chromeos::DIR_PRINTER_DRIVERS_CACHE, &ret)) {
149 LOG(FATAL) << "Failed to get printer cache directory.";
150 }
151 return ret;
152 }
153
154 const FilePath cache_base_dir_;
155 };
156
157 } // namespace
158
159 // static
160 unique_ptr<PPDCache> PPDCache::Create(const PPDCache::Options& options) {
161 return ::base::MakeUnique<PPDCacheImpl>(options);
162 }
163
164 // static
165 unique_ptr<PPDCache> PPDCache::Create() {
166 return ::base::MakeUnique<PPDCacheImpl>(PPDCache::Options());
skau 2016/10/07 16:29:06 nit: If we're always passing an Options struct, we
Carlson 2016/10/14 19:28:56 Done.
167 }
168
169 } // namespace printing
170 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698