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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chromeos/printing/ppd_cache.cc
diff --git a/chromeos/printing/ppd_cache.cc b/chromeos/printing/ppd_cache.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8584ea20b5a8f190bb96c2357913f7fa82d8b0a0
--- /dev/null
+++ b/chromeos/printing/ppd_cache.cc
@@ -0,0 +1,170 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/printing/ppd_cache.h"
+
+#include "base/files/file_util.h"
+#include "base/memory/ptr_util.h"
+#include "base/path_service.h"
+#include "base/strings/stringprintf.h"
+#include "chromeos/chromeos_paths.h"
+
+using base::FilePath;
+using base::Optional;
+using std::string;
+using std::unique_ptr;
+
+namespace chromeos {
+namespace printing {
+namespace {
+
+// Limits on key strings we'll accept. This limit is pretty arbitrary, we
+// just don't want to accept strings that are so long they might cause
+// memory pressure or somesuch.
+constexpr int kKeySizeLimit = 512;
+
+// "Manufacturer" used when storing and retrieving locally-keyed
+// files.
+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
+
+// Placeholder cache.
+class PPDCacheImpl : public PPDCache {
+ public:
+ PPDCacheImpl(const PPDCache::Options& options)
+ : cache_base_dir_(GetCacheBaseDirOrDie()) {}
+ ~PPDCacheImpl() override {}
+
+ // Public API functions.
+ Optional<FilePath> Find(const string& manufacturer,
+ const string& model) const override {
+ Optional<FilePath> ret;
+ if (model == kLocalModel) {
+ 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
+ return ret;
+ }
+ 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
+ KeyIsValid("Printer model", model))) {
+ return ret;
+ }
+
+ FilePath contents_path = GetCachePath(manufacturer, model);
+ if (base::PathExists(contents_path)) {
+ ret = contents_path;
+ }
+ return ret;
+ }
+
+ Optional<FilePath> FindLocal(const string& key) const override {
+ Optional<FilePath> ret;
+ if (!KeyIsValid("Printer identifier", key)) {
+ return ret;
+ }
+ FilePath contents_path = GetCachePath(kLocalModel, key);
+ if (base::PathExists(contents_path)) {
+ ret = contents_path;
+ }
+ return ret;
+ }
+
+ // Store a ppd that was manually added by a user, using the given key.
+ Optional<FilePath> StoreLocal(
+ const string& key,
+ const string& compressed_ppd_contents) override {
+ if (!KeyIsValid("Printer identifier", key)) {
+ return Optional<FilePath>();
+ }
+ return StoreCommon(kLocalModel, key, compressed_ppd_contents);
+ }
+
+ Optional<FilePath> Store(const string& manufacturer,
+ const string& model,
+ const string& compressed_ppd_contents) override {
+ if (model == kLocalModel) {
+ LOG(ERROR) << "Denying attempt to store auto-ppd under local namespace";
+ return Optional<FilePath>();
+ }
+ if (!(KeyIsValid("Printer manufacturer", manufacturer) &&
+ KeyIsValid("Printer model", model))) {
+ return Optional<FilePath>();
+ }
+ return StoreCommon(manufacturer, model, compressed_ppd_contents);
+ }
+
+ private:
+ // Shared Store* functionality. This can assume that all arguments have been
+ // pre-vetted and are valid.
+ Optional<FilePath> StoreCommon(const string& manufacturer,
+ const string& model,
+ const string& compressed_ppd_contents) {
+ Optional<FilePath> ret;
+ FilePath contents_path = GetCachePath(manufacturer, model);
+ if (base::WriteFile(contents_path, compressed_ppd_contents.data(),
+ compressed_ppd_contents.size()) ==
+ static_cast<int>(compressed_ppd_contents.size())) {
+ ret = contents_path;
+ } else {
+ LOG(ERROR) << "Failed to write " << compressed_ppd_contents.size()
+ << " bytes to " << contents_path.LossyDisplayName();
+ // Try to clean up the file, as it may have partial contents. Note that
+ // DeleteFile(nonexistant file) should return true, so failure here means
+ // something is exceptionally hosed.
+ if (!base::DeleteFile(contents_path, false)) {
+ 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.
+ << contents_path.LossyDisplayName();
+ }
+ }
+ return ret;
+ }
+
+ // File paths are generated via hashes of the manufacturer/model strings.
+ // This isn't because we're overly worried about collisions; rather, using the
+ // hash instead of the strings directly means we don't have to do any fiddly
+ // path escaping, stress about unicode concerns, or worry overmuch about path
+ // length limits.
+ FilePath GetCachePath(const string& manufacturer, const string& model) const {
+ size_t h = base::HashInts64(std::hash<std::string>()(manufacturer),
+ std::hash<std::string>()(model));
+ 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.
+ }
+
+ // Return whether or not the given cache key is valid. Log an error
+ // describing the problem if it's not valid.
+ 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
+ if (key.empty()) {
+ LOG(ERROR) << key_name << " cannot be empty.";
+ return false;
+ }
+ if (key.size() > kKeySizeLimit) {
+ LOG(ERROR) << key_name << " is too long. Limit is " << kKeySizeLimit;
+ return false;
+ }
+ return true;
+ }
+
+ // Retrieve the printer cache filepath from PathService, or die trying.
+ FilePath GetCacheBaseDirOrDie() const {
+ FilePath ret;
+ if (!PathService::Get(::chromeos::DIR_PRINTER_DRIVERS_CACHE, &ret)) {
+ LOG(FATAL) << "Failed to get printer cache directory.";
+ }
+ return ret;
+ }
+
+ const FilePath cache_base_dir_;
+};
+
+} // namespace
+
+// static
+unique_ptr<PPDCache> PPDCache::Create(const PPDCache::Options& options) {
+ return ::base::MakeUnique<PPDCacheImpl>(options);
+}
+
+// static
+unique_ptr<PPDCache> PPDCache::Create() {
+ 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.
+}
+
+} // namespace printing
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698