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

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

Issue 2343983004: Add PPDProvider barebones implementation and associated cache skeleton. (Closed)
Patch Set: Remove extra includes Created 4 years, 3 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
skau 2016/09/17 00:59:59 ppd_provider.h should be included first https://go
Carlson 2016/10/06 15:56:05 Done.
5 #include "base/json/json_parser.h"
6 #include "base/memory/ptr_util.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "base/time/time.h"
10 #include "base/values.h"
11 #include "chromeos/printing/ppd_cache.h"
12 #include "chromeos/printing/ppd_provider.h"
13 #include "net/base/load_flags.h"
14 #include "net/http/http_status_code.h"
15 #include "net/url_request/url_fetcher.h"
16 #include "net/url_request/url_fetcher_delegate.h"
17 #include "net/url_request/url_request_context_getter.h"
18 #include "url/gurl.h"
19
20 using ::base::DictionaryValue;
21 using ::base::Value;
22 using ::net::URLFetcher;
23 using ::net::URLFetcherDelegate;
24 using ::std::string;
25 using ::std::unique_ptr;
26
27 namespace chromeos {
28 namespace printing {
29 namespace {
30
31 const char* kJSONPPDKey = "compressedPpd";
32 const char* kJSONLastUpdatedKey = "lastUpdatedTime";
33
34 class PPDProviderImpl;
35
36 // URLFetcherDelegate that just forwards the complete callback back to
37 // the PPDProvider that owns the delegate.
38 class ForwardingURLFetcherDelegate : public URLFetcherDelegate {
39 public:
40 ForwardingURLFetcherDelegate(PPDProviderImpl* owner) : owner_(owner) {}
41 ~ForwardingURLFetcherDelegate() override {}
42
43 // URLFetcherDelegate API method. Defined below since we need the
44 // PPDProviderImpl definition first.
45 void OnURLFetchComplete(const URLFetcher* source) override;
46
47 private:
48 // owner of this delegate.
49 PPDProviderImpl* owner_;
50 };
51
52 // TODO(justincarlson) - Determine what concurrency this class
53 // needs to deal with, particularly around the lifetime of files
54 // in the cache, but also for concurrent Lookups.
55 class PPDProviderImpl : public PPDProvider {
56 public:
57 PPDProviderImpl(
58 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
59 ::std::unique_ptr<PPDCache> cache,
60 const PPDProvider::Options& options)
61 : forwarding_delegate_(this),
62 url_context_getter_(url_context_getter),
63 cache_(std::move(cache)),
64 options_(options) {}
65 ~PPDProviderImpl() override {}
66
67 void Lookup(const string& manufacturer,
68 const string& model,
69 PPDProvider::LookupCallback cb) override {
70 auto tmp = cache_->Lookup(manufacturer, model);
71 if (tmp != nullptr) {
72 // Cache hit. Schedule the callback right now.
73 url_context_getter_->GetNetworkTaskRunner()->PostTask(
74 FROM_HERE, base::Bind(cb, PPDProvider::SUCCESS, *tmp));
75 return;
76 }
77
78 done_callback_ = cb;
79 fetcher_ = net::URLFetcher::Create(GetLookupURL(manufacturer, model),
80 URLFetcher::GET, &forwarding_delegate_);
81 fetcher_->SetRequestContext(url_context_getter_.get());
82 fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
83 net::LOAD_DO_NOT_SAVE_COOKIES |
84 net::LOAD_DO_NOT_SEND_COOKIES |
85 net::LOAD_DO_NOT_SEND_AUTH_DATA);
86 fetcher_->Start();
87 };
88
89 // Called when the fetcher completes its fetch.
90 void OnURLFetchComplete() {
91 // TODO(justincarlson) -- What does URLFetcher do with redirects? Does it
92 // automatically resolve them, or do we need to do something else?
93 string contents;
94 if ((fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS) ||
95 (fetcher_->GetResponseCode() != net::HTTP_OK) ||
96 !fetcher_->GetResponseAsString(&contents)) {
97 // Something went wrong with the fetch.
98 done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
99 } else {
100 auto parsed_json = ::base::JSONReader::Read(contents);
101 DictionaryValue* dict;
102 if (parsed_json == nullptr || //
103 parsed_json->GetType() != Value::TYPE_DICTIONARY || //
skau 2016/09/17 00:59:59 GetAsDictionary implies this check and will fail s
Carlson 2016/10/06 15:56:05 Done.
104 !parsed_json->GetAsDictionary(&dict)) {
105 // Malformed response. TODO(justincarlson) - LOG something here?
106 done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
107 return;
108 }
109 std::string compressed_ppd_contents;
110 std::string last_updated_time_string;
111 uint64_t last_updated_time;
112 if (!(dict->GetString(kJSONPPDKey, &compressed_ppd_contents) &&
113 dict->GetString(kJSONLastUpdatedKey, &last_updated_time_string) &&
114 ::base::StringToUint64(last_updated_time_string,
115 &last_updated_time))) {
116 // Malformed response. TODO(justincarlson) - LOG something here?
117 done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
118 return;
119 }
120 auto ppd_file =
121 cache_->Store(manufacturer_, model_, base::Time::Now().ToJavaTime(),
122 last_updated_time, compressed_ppd_contents);
123 }
124 done_callback_.Run(PPDProvider::SUCCESS, Printer::PPDFile());
125 }
126
127 private:
128 // Generate a url to look up a manufacturer/model from the quirks server
129 GURL GetLookupURL(const string& manufacturer, const string& model) const {
130 return GURL(::base::JoinString(
131 {
132 "https://", //
133 options_.quirks_server, //
134 "/v2/printer/manufacturers/", //
135 manufacturer, //
136 "/models/", //
137 model, //
138 "?key=", //
139 options_.api_key //
140 },
141 ""));
142 }
143
144 // Manufacturer/model strings for the current lookup.
145 std::string manufacturer_;
146 std::string model_;
147
148 ForwardingURLFetcherDelegate forwarding_delegate_;
149 scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
150 unique_ptr<PPDCache> cache_;
151
152 // Construction-time options, immutable.
153 const PPDProvider::Options options_;
154 unique_ptr<::net::URLFetcher> fetcher_;
155 PPDProvider::LookupCallback done_callback_;
156 };
157
158 void ForwardingURLFetcherDelegate::OnURLFetchComplete(
159 const URLFetcher* source) {
160 owner_->OnURLFetchComplete();
161 }
162
163 } // namespace
164
165 // static
166 PPDProvider::Options PPDProvider::Defaults() {
167 PPDProvider::Options ret;
168 ret.quirks_server = "chromeosquirksserver-pa.googleapis.com";
169 // TODO(justincarlson) - How do we set a default api key? Can't include
170 // google_apis/google_api_keys directly.
171 // ret.api_key = ::google_apis::GetAPIKey();
skau 2016/09/17 00:59:59 It'll need to be passed in as it depends on the pl
Carlson 2016/10/06 15:56:05 Done.
172 return ret;
173 }
174
175 // static
176 unique_ptr<PPDProvider> PPDProvider::Create(
177 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
178 unique_ptr<PPDCache> cache,
179 const PPDProvider::Options& options) {
180 return ::base::MakeUnique<PPDProviderImpl>(url_context_getter,
181 std::move(cache), options);
182 }
183
184 // static
185 unique_ptr<PPDProvider> PPDProvider::Create(
186 scoped_refptr<net::URLRequestContextGetter> url_context_getter,
187 unique_ptr<PPDCache> cache) {
188 return ::base::MakeUnique<PPDProviderImpl>(url_context_getter,
189 std::move(cache), Defaults());
190 }
191
192 } // namespace printing
193 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698