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

Side by Side Diff: chromeos/printing/ppd_provider.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_provider.h"
6
7 #include "base/files/file_util.h"
8 #include "base/json/json_parser.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "chromeos/printing/ppd_cache.h"
15 #include "net/base/load_flags.h"
16 #include "net/http/http_status_code.h"
17 #include "net/url_request/url_fetcher.h"
18 #include "net/url_request/url_fetcher_delegate.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "url/gurl.h"
21
22 using ::base::DictionaryValue;
23 using ::base::FilePath;
24 using ::base::Optional;
25 using ::base::Value;
26 using ::net::URLFetcher;
27 using ::net::URLFetcherDelegate;
28 using ::std::string;
29 using ::std::unique_ptr;
30
31 namespace chromeos {
32 namespace printing {
33 namespace {
34
35 // Expected fields from the quirks server.
36 const char* kJSONPPDKey = "compressedPpd";
37 const char* kJSONLastUpdatedKey = "lastUpdatedTime";
38
39 class PPDProviderImpl;
40
41 // URLFetcherDelegate that just forwards the complete callback back to
42 // the PPDProvider that owns the delegate.
43 class ForwardingURLFetcherDelegate : public URLFetcherDelegate {
44 public:
45 ForwardingURLFetcherDelegate(PPDProviderImpl* owner) : owner_(owner) {}
46 ~ForwardingURLFetcherDelegate() override {}
47
48 // URLFetcherDelegate API method. Defined below since we need the
49 // PPDProviderImpl definition first.
50 void OnURLFetchComplete(const URLFetcher* source) override;
51
52 private:
53 // owner of this delegate.
54 PPDProviderImpl* owner_;
55 };
56
57 class PPDProviderImpl : public PPDProvider {
58 public:
59 PPDProviderImpl(
60 const string& api_key,
61 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
62 unique_ptr<PPDCache> cache,
63 const PPDProvider::Options& options)
64 : api_key_(api_key),
65 forwarding_delegate_(this),
66 url_context_getter_(url_context_getter),
67 cache_(std::move(cache)),
68 options_(options) {}
69 ~PPDProviderImpl() override {}
70
71 void Resolve(const string& manufacturer,
72 const string& model,
73 PPDProvider::ResolveCallback cb) override {
74 auto tmp = cache_->Find(manufacturer, model);
75 if (tmp) {
76 // Cache hit. Schedule the callback right now.
77 url_context_getter_->GetNetworkTaskRunner()->PostTask(
78 FROM_HERE, base::Bind(cb, PPDProvider::SUCCESS, tmp.value()));
79 return;
80 }
81
82 manufacturer_ = manufacturer;
83 model_ = model;
84 done_callback_ = cb;
85 fetcher_ = net::URLFetcher::Create(GetLookupURL(manufacturer, model),
86 URLFetcher::GET, &forwarding_delegate_);
87 fetcher_->SetRequestContext(url_context_getter_.get());
88 fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
89 net::LOAD_DO_NOT_SAVE_COOKIES |
90 net::LOAD_DO_NOT_SEND_COOKIES |
91 net::LOAD_DO_NOT_SEND_AUTH_DATA);
92 fetcher_->Start();
93 };
94
95 bool StoreLocal(const std::string& printer_id,
96 base::FilePath ppd_file) override {
97 string contents;
98 // TODO(justincarlson) - Resolve what we're doing around compression. We
99 // may need to compress the file here.
100 if (!ReadFileToString(ppd_file, &contents)) {
101 LOG(ERROR) << "Failed to read ppd file " << ppd_file.LossyDisplayName();
102 return false;
103 }
104 return static_cast<bool>(cache_->StoreLocal(printer_id, contents));
105 }
106
107 void ResolveLocal(const string& printer_id,
108 PPDProvider::ResolveCallback cb) override {
109 auto tmp = cache_->FindLocal(printer_id);
skau 2016/10/07 16:29:06 Can you write out this type? It's not clear that
Carlson 2016/10/14 19:28:56 Done.
110 if (tmp) {
111 // Found it.
112 url_context_getter_->GetNetworkTaskRunner()->PostTask(
113 FROM_HERE, base::Bind(cb, PPDProvider::SUCCESS, tmp.value()));
114 } else {
115 // Doesn't exist. No further resolution should be attempted since
116 // it was originally a local addition.
117 url_context_getter_->GetNetworkTaskRunner()->PostTask(
118 FROM_HERE, base::Bind(cb, PPDProvider::NOT_FOUND, FilePath()));
119 }
120 }
121
122 // Called on the network thread when the fetcher completes its fetch.
123 void OnURLFetchComplete() {
124 // TODO(justincarlson) -- What does URLFetcher do with redirects? Does it
125 // automatically resolve them, or do we need to do something else?
126 string contents;
127 if ((fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS) ||
128 (fetcher_->GetResponseCode() != net::HTTP_OK) ||
129 !fetcher_->GetResponseAsString(&contents)) {
130 // Something went wrong with the fetch.
131 done_callback_.Run(PPDProvider::SERVER_ERROR, FilePath());
132 return;
133 }
134 auto parsed_json = ::base::JSONReader::Read(contents);
135 DictionaryValue* dict;
136 if (parsed_json == nullptr || //
skau 2016/10/07 16:29:06 are you forcing it to wrap with the comment //?
Carlson 2016/10/14 19:28:56 Yes. I think it's easier to read this way, and AF
137 !parsed_json->GetAsDictionary(&dict)) {
138 // Malformed response. TODO(justincarlson) - LOG something here?
139 done_callback_.Run(PPDProvider::SERVER_ERROR, FilePath());
140 return;
141 }
142 string compressed_ppd_contents;
143 string last_updated_time_string;
144 uint64_t last_updated_time;
145 if (!(dict->GetString(kJSONPPDKey, &compressed_ppd_contents) &&
146 dict->GetString(kJSONLastUpdatedKey, &last_updated_time_string) &&
147 ::base::StringToUint64(last_updated_time_string,
148 &last_updated_time))) {
149 // Malformed response. TODO(justincarlson) - LOG something here?
150 done_callback_.Run(PPDProvider::SERVER_ERROR, FilePath());
151 return;
152 }
153 auto ppd_file =
154 cache_->Store(manufacturer_, model_, compressed_ppd_contents);
155 if (!ppd_file) {
156 // Failed to store.
157 done_callback_.Run(PPDProvider::INTERNAL_ERROR, FilePath());
158 return;
159 }
160 done_callback_.Run(PPDProvider::SUCCESS, ppd_file.value());
161 }
162
163 private:
164 // Generate a url to look up a manufacturer/model from the quirks server
165 GURL GetLookupURL(const string& manufacturer, const string& model) const {
166 return GURL(::base::JoinString(
167 {
168 "https://", //
169 options_.quirks_server, //
170 "/v2/printer/manufacturers/", //
171 manufacturer, //
172 "/models/", //
173 model, //
174 "?key=", //
175 api_key_ //
176 },
177 ""));
178 }
179
180 // API key for accessing quirks server.
181 const string api_key_;
182
183 // Manufacturer/model strings for the current lookup.
184 string manufacturer_;
185 string model_;
186
187 ForwardingURLFetcherDelegate forwarding_delegate_;
188 scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
189 unique_ptr<PPDCache> cache_;
190
191 PPDProvider::ResolveCallback done_callback_;
192
193 // Construction-time options, immutable.
194 const PPDProvider::Options options_;
195 unique_ptr<::net::URLFetcher> fetcher_;
196 };
197
198 void ForwardingURLFetcherDelegate::OnURLFetchComplete(
199 const URLFetcher* source) {
200 owner_->OnURLFetchComplete();
201 }
202
203 } // namespace
204
205 // static
206 PPDProvider::Options PPDProvider::Defaults() {
207 PPDProvider::Options ret;
208 ret.quirks_server = "chromeosquirksserver-pa.googleapis.com";
209 return ret;
210 }
211
212 // static
213 unique_ptr<PPDProvider> PPDProvider::Create(
214 const string& api_key,
215 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
216 unique_ptr<PPDCache> cache,
217 const PPDProvider::Options& options) {
218 return ::base::MakeUnique<PPDProviderImpl>(api_key, url_context_getter,
219 std::move(cache), options);
220 }
221
222 // static
223 unique_ptr<PPDProvider> PPDProvider::Create(
224 const string& api_key,
225 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
226 unique_ptr<PPDCache> cache) {
227 return ::base::MakeUnique<PPDProviderImpl>(api_key, url_context_getter,
228 std::move(cache), Defaults());
229 }
230
231 } // namespace printing
232 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698