Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/printing/ppd_cache.h" | 5 #include "chromeos/printing/ppd_cache.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 // something is exceptionally hosed. | 84 // something is exceptionally hosed. |
| 85 if (!base::DeleteFile(contents_path, false)) { | 85 if (!base::DeleteFile(contents_path, false)) { |
| 86 LOG(ERROR) << "Failed to cleanup partially-written file " | 86 LOG(ERROR) << "Failed to cleanup partially-written file " |
| 87 << contents_path.LossyDisplayName(); | 87 << contents_path.LossyDisplayName(); |
| 88 return ret; | 88 return ret; |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 return ret; | 91 return ret; |
| 92 } | 92 } |
| 93 | 93 |
| 94 base::Optional<PpdProvider::AvailablePrintersMap> FindAvailablePrinters() | 94 const PpdProvider::AvailablePrintersMap* FindAvailablePrinters() override { |
| 95 override { | 95 if (available_printers_ != nullptr && |
| 96 base::Time::Now() - available_printers_timestamp_ < | |
| 97 options_.max_available_list_staleness) { | |
| 98 // Satisfy from memory cache. | |
| 99 return available_printers_.get(); | |
| 100 } | |
| 96 std::string buf; | 101 std::string buf; |
| 97 if (!MaybeReadAvailablePrintersCache(&buf)) { | 102 if (!MaybeReadAvailablePrintersCache(&buf)) { |
| 98 return base::nullopt; | 103 // Disk cache miss. |
| 104 return nullptr; | |
| 99 } | 105 } |
| 100 auto dict = base::DictionaryValue::From(base::JSONReader::Read(buf)); | 106 auto dict = base::DictionaryValue::From(base::JSONReader::Read(buf)); |
| 101 if (dict == nullptr) { | 107 if (dict == nullptr) { |
| 102 LOG(ERROR) << "Failed to deserialize available printers cache"; | 108 LOG(ERROR) << "Failed to deserialize available printers cache"; |
| 103 return base::nullopt; | 109 return nullptr; |
| 104 } | 110 } |
| 105 PpdProvider::AvailablePrintersMap ret; | 111 // Note if we got here, we've already set available_printers_timestamp_ to |
| 112 // the mtime of the file we read from. | |
| 113 available_printers_.reset(new PpdProvider::AvailablePrintersMap); | |
| 106 const base::ListValue* models; | 114 const base::ListValue* models; |
| 107 std::string model; | 115 std::string model; |
| 108 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); | 116 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); |
| 109 it.Advance()) { | 117 it.Advance()) { |
| 110 auto& out = ret[it.key()]; | 118 auto& out = (*available_printers_)[it.key()]; |
| 111 if (!it.value().GetAsList(&models)) { | 119 if (!it.value().GetAsList(&models)) { |
| 112 LOG(ERROR) << "Skipping malformed printer make: " << it.key(); | 120 LOG(ERROR) << "Skipping malformed printer make: " << it.key(); |
| 113 continue; | 121 continue; |
| 114 } | 122 } |
| 115 for (const auto& model_value : *models) { | 123 for (const auto& model_value : *models) { |
| 116 if (model_value->GetAsString(&model)) { | 124 if (model_value->GetAsString(&model)) { |
| 117 out.push_back(model); | 125 out.push_back(model); |
| 118 } else { | 126 } else { |
| 119 LOG(ERROR) << "Skipping malformed printer model in: " << it.key() | 127 LOG(ERROR) << "Skipping malformed printer model in: " << it.key() |
| 120 << ". Expected a string, found a " | 128 << ". Expected a string, found a " |
| 121 << base::Value::GetTypeName(model_value->GetType()); | 129 << base::Value::GetTypeName(model_value->GetType()); |
| 122 } | 130 } |
| 123 } | 131 } |
| 124 } | 132 } |
| 125 return ret; | 133 return available_printers_.get(); |
| 126 } | 134 } |
| 127 | 135 |
| 128 // Note we throw up our hands and fail (gracefully) to store if we encounter | 136 // Note we throw up our hands and fail (gracefully) to store if we encounter |
| 129 // non-unicode things in the strings of |available_printers|. Since these | 137 // non-unicode things in the strings of |available_printers|. Since these |
| 130 // strings come from a source we control, being less paranoid about these | 138 // strings come from a source we control, being less paranoid about these |
| 131 // values seems reasonable. | 139 // values seems reasonable. |
| 132 void StoreAvailablePrinters( | 140 void StoreAvailablePrinters(std::unique_ptr<PpdProvider::AvailablePrintersMap> |
| 133 const PpdProvider::AvailablePrintersMap& available_printers) override { | 141 available_printers) override { |
| 142 available_printers_ = std::move(available_printers); | |
| 143 available_printers_timestamp_ = base::Time::Now(); | |
| 134 // Convert the map to Values, in preparation for jsonification. | 144 // Convert the map to Values, in preparation for jsonification. |
| 135 base::DictionaryValue top_level; | 145 base::DictionaryValue top_level; |
| 136 for (const auto& entry : available_printers) { | 146 for (const auto& entry : *available_printers_) { |
| 137 auto printers = base::MakeUnique<base::ListValue>(); | 147 auto printers = base::MakeUnique<base::ListValue>(); |
| 138 printers->AppendStrings(entry.second); | 148 printers->AppendStrings(entry.second); |
| 139 top_level.Set(entry.first, std::move(printers)); | 149 top_level.Set(entry.first, std::move(printers)); |
| 140 } | 150 } |
| 141 std::string contents; | 151 std::string contents; |
| 142 if (!base::JSONWriter::Write(top_level, &contents)) { | 152 if (!base::JSONWriter::Write(top_level, &contents)) { |
| 143 LOG(ERROR) << "Failed to generate JSON"; | 153 LOG(ERROR) << "Failed to generate JSON"; |
| 144 return; | 154 return; |
| 145 } | 155 } |
| 146 if (contents.size() > options_.max_available_list_cached_size) { | 156 if (contents.size() > options_.max_available_list_cached_size) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 (base::Time::Now() - info.last_modified <= | 227 (base::Time::Now() - info.last_modified <= |
| 218 options_.max_available_list_staleness)) { | 228 options_.max_available_list_staleness)) { |
| 219 // We have a file that's recent enough to use. | 229 // We have a file that's recent enough to use. |
| 220 if (!base::ReadFileToStringWithMaxSize( | 230 if (!base::ReadFileToStringWithMaxSize( |
| 221 available_printers_file_, buf, | 231 available_printers_file_, buf, |
| 222 options_.max_available_list_cached_size)) { | 232 options_.max_available_list_cached_size)) { |
| 223 LOG(ERROR) << "Failed to read printer cache"; | 233 LOG(ERROR) << "Failed to read printer cache"; |
| 224 buf->clear(); | 234 buf->clear(); |
| 225 return false; | 235 return false; |
| 226 } | 236 } |
| 237 available_printers_timestamp_ = info.last_modified; | |
| 227 return true; | 238 return true; |
| 228 } | 239 } |
| 240 | |
| 229 // Either we don't have an openable file, or it's too old. | 241 // Either we don't have an openable file, or it's too old. |
| 230 // | 242 // |
| 231 // If we have an invalid file and it's not valid for reasons other than | 243 // If we have an invalid file and it's not valid for reasons other than |
| 232 // NOT_FOUND, that's unexpected and worth logging. Otherwise this is | 244 // NOT_FOUND, that's unexpected and worth logging. Otherwise this is |
| 233 // a normal cache miss. | 245 // a normal cache miss. |
| 234 if (!cache_file.IsValid() && | 246 if (!cache_file.IsValid() && |
| 235 cache_file.error_details() != base::File::FILE_ERROR_NOT_FOUND) { | 247 cache_file.error_details() != base::File::FILE_ERROR_NOT_FOUND) { |
| 236 LOG(ERROR) << "Unexpected result when attempting to open printer cache: " | 248 LOG(ERROR) << "Unexpected result when attempting to open printer cache: " |
| 237 << base::File::ErrorToString(cache_file.error_details()); | 249 << base::File::ErrorToString(cache_file.error_details()); |
| 238 } | 250 } |
| 239 return false; | 251 return false; |
| 240 } | 252 } |
| 241 | 253 |
| 254 // In-memory copy of the available printers map, null if we don't have an | |
| 255 // in-memory copy yet. Filled in the first time the map is fetched (whether | |
| 256 // from disk or server), and remains for the life of the PpdCache. | |
|
skau
2016/11/10 20:46:37
This isn't strictly true. It's reset when the cac
Carlson
2016/11/11 01:39:27
You're right, I changed this after I wrote the com
| |
| 257 std::unique_ptr<PpdProvider::AvailablePrintersMap> available_printers_; | |
| 258 // Timestamp for the in-memory copy of the cache. (The on-disk version uses | |
| 259 // the file mtime). | |
| 260 base::Time available_printers_timestamp_; | |
| 261 | |
| 242 const base::FilePath cache_base_dir_; | 262 const base::FilePath cache_base_dir_; |
| 243 const base::FilePath available_printers_file_; | 263 const base::FilePath available_printers_file_; |
| 244 const PpdCache::Options options_; | 264 const PpdCache::Options options_; |
| 245 | 265 |
| 246 DISALLOW_COPY_AND_ASSIGN(PpdCacheImpl); | 266 DISALLOW_COPY_AND_ASSIGN(PpdCacheImpl); |
| 247 }; | 267 }; |
| 248 | 268 |
| 249 } // namespace | 269 } // namespace |
| 250 | 270 |
| 251 // static | 271 // static |
| 252 std::unique_ptr<PpdCache> PpdCache::Create(const base::FilePath& cache_base_dir, | 272 std::unique_ptr<PpdCache> PpdCache::Create(const base::FilePath& cache_base_dir, |
| 253 const PpdCache::Options& options) { | 273 const PpdCache::Options& options) { |
| 254 return base::MakeUnique<PpdCacheImpl>(cache_base_dir, options); | 274 return base::MakeUnique<PpdCacheImpl>(cache_base_dir, options); |
| 255 } | 275 } |
| 256 | 276 |
| 257 } // namespace printing | 277 } // namespace printing |
| 258 } // namespace chromeos | 278 } // namespace chromeos |
| OLD | NEW |