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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chromeos/printing/ppd_provider.cc
diff --git a/chromeos/printing/ppd_provider.cc b/chromeos/printing/ppd_provider.cc
new file mode 100644
index 0000000000000000000000000000000000000000..068a4acbd41e90846ac17f0786d90de931c40548
--- /dev/null
+++ b/chromeos/printing/ppd_provider.cc
@@ -0,0 +1,193 @@
+// 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.
+
skau 2016/09/17 00:59:59 ppd_provider.h should be included first https://go
Carlson 2016/10/06 15:56:05 Done.
+#include "base/json/json_parser.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chromeos/printing/ppd_cache.h"
+#include "chromeos/printing/ppd_provider.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
+
+using ::base::DictionaryValue;
+using ::base::Value;
+using ::net::URLFetcher;
+using ::net::URLFetcherDelegate;
+using ::std::string;
+using ::std::unique_ptr;
+
+namespace chromeos {
+namespace printing {
+namespace {
+
+const char* kJSONPPDKey = "compressedPpd";
+const char* kJSONLastUpdatedKey = "lastUpdatedTime";
+
+class PPDProviderImpl;
+
+// URLFetcherDelegate that just forwards the complete callback back to
+// the PPDProvider that owns the delegate.
+class ForwardingURLFetcherDelegate : public URLFetcherDelegate {
+ public:
+ ForwardingURLFetcherDelegate(PPDProviderImpl* owner) : owner_(owner) {}
+ ~ForwardingURLFetcherDelegate() override {}
+
+ // URLFetcherDelegate API method. Defined below since we need the
+ // PPDProviderImpl definition first.
+ void OnURLFetchComplete(const URLFetcher* source) override;
+
+ private:
+ // owner of this delegate.
+ PPDProviderImpl* owner_;
+};
+
+// TODO(justincarlson) - Determine what concurrency this class
+// needs to deal with, particularly around the lifetime of files
+// in the cache, but also for concurrent Lookups.
+class PPDProviderImpl : public PPDProvider {
+ public:
+ PPDProviderImpl(
+ scoped_refptr<net::URLRequestContextGetter> url_context_getter,
+ ::std::unique_ptr<PPDCache> cache,
+ const PPDProvider::Options& options)
+ : forwarding_delegate_(this),
+ url_context_getter_(url_context_getter),
+ cache_(std::move(cache)),
+ options_(options) {}
+ ~PPDProviderImpl() override {}
+
+ void Lookup(const string& manufacturer,
+ const string& model,
+ PPDProvider::LookupCallback cb) override {
+ auto tmp = cache_->Lookup(manufacturer, model);
+ if (tmp != nullptr) {
+ // Cache hit. Schedule the callback right now.
+ url_context_getter_->GetNetworkTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(cb, PPDProvider::SUCCESS, *tmp));
+ return;
+ }
+
+ done_callback_ = cb;
+ fetcher_ = net::URLFetcher::Create(GetLookupURL(manufacturer, model),
+ URLFetcher::GET, &forwarding_delegate_);
+ fetcher_->SetRequestContext(url_context_getter_.get());
+ fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
+ net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SEND_AUTH_DATA);
+ fetcher_->Start();
+ };
+
+ // Called when the fetcher completes its fetch.
+ void OnURLFetchComplete() {
+ // TODO(justincarlson) -- What does URLFetcher do with redirects? Does it
+ // automatically resolve them, or do we need to do something else?
+ string contents;
+ if ((fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS) ||
+ (fetcher_->GetResponseCode() != net::HTTP_OK) ||
+ !fetcher_->GetResponseAsString(&contents)) {
+ // Something went wrong with the fetch.
+ done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
+ } else {
+ auto parsed_json = ::base::JSONReader::Read(contents);
+ DictionaryValue* dict;
+ if (parsed_json == nullptr || //
+ 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.
+ !parsed_json->GetAsDictionary(&dict)) {
+ // Malformed response. TODO(justincarlson) - LOG something here?
+ done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
+ return;
+ }
+ std::string compressed_ppd_contents;
+ std::string last_updated_time_string;
+ uint64_t last_updated_time;
+ if (!(dict->GetString(kJSONPPDKey, &compressed_ppd_contents) &&
+ dict->GetString(kJSONLastUpdatedKey, &last_updated_time_string) &&
+ ::base::StringToUint64(last_updated_time_string,
+ &last_updated_time))) {
+ // Malformed response. TODO(justincarlson) - LOG something here?
+ done_callback_.Run(PPDProvider::SERVER_ERROR, Printer::PPDFile());
+ return;
+ }
+ auto ppd_file =
+ cache_->Store(manufacturer_, model_, base::Time::Now().ToJavaTime(),
+ last_updated_time, compressed_ppd_contents);
+ }
+ done_callback_.Run(PPDProvider::SUCCESS, Printer::PPDFile());
+ }
+
+ private:
+ // Generate a url to look up a manufacturer/model from the quirks server
+ GURL GetLookupURL(const string& manufacturer, const string& model) const {
+ return GURL(::base::JoinString(
+ {
+ "https://", //
+ options_.quirks_server, //
+ "/v2/printer/manufacturers/", //
+ manufacturer, //
+ "/models/", //
+ model, //
+ "?key=", //
+ options_.api_key //
+ },
+ ""));
+ }
+
+ // Manufacturer/model strings for the current lookup.
+ std::string manufacturer_;
+ std::string model_;
+
+ ForwardingURLFetcherDelegate forwarding_delegate_;
+ scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
+ unique_ptr<PPDCache> cache_;
+
+ // Construction-time options, immutable.
+ const PPDProvider::Options options_;
+ unique_ptr<::net::URLFetcher> fetcher_;
+ PPDProvider::LookupCallback done_callback_;
+};
+
+void ForwardingURLFetcherDelegate::OnURLFetchComplete(
+ const URLFetcher* source) {
+ owner_->OnURLFetchComplete();
+}
+
+} // namespace
+
+// static
+PPDProvider::Options PPDProvider::Defaults() {
+ PPDProvider::Options ret;
+ ret.quirks_server = "chromeosquirksserver-pa.googleapis.com";
+ // TODO(justincarlson) - How do we set a default api key? Can't include
+ // google_apis/google_api_keys directly.
+ // 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.
+ return ret;
+}
+
+// static
+unique_ptr<PPDProvider> PPDProvider::Create(
+ scoped_refptr<net::URLRequestContextGetter> url_context_getter,
+ unique_ptr<PPDCache> cache,
+ const PPDProvider::Options& options) {
+ return ::base::MakeUnique<PPDProviderImpl>(url_context_getter,
+ std::move(cache), options);
+}
+
+// static
+unique_ptr<PPDProvider> PPDProvider::Create(
+ scoped_refptr<net::URLRequestContextGetter> url_context_getter,
+ unique_ptr<PPDCache> cache) {
+ return ::base::MakeUnique<PPDProviderImpl>(url_context_getter,
+ std::move(cache), Defaults());
+}
+
+} // namespace printing
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698