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

Unified Diff: chromeos/printing/ppd_provider.cc

Issue 2476073003: Update PpdProvider threading model. (Closed)
Patch Set: Add more logging, add bypass for manufacturer issue Created 4 years, 1 month 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
index fcae71105236f94f1b8b861539916d6c54a39cad..68fea3d903d44564d9676281132c2e47aa3782b8 100644
--- a/chromeos/printing/ppd_provider.cc
+++ b/chromeos/printing/ppd_provider.cc
@@ -14,6 +14,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chromeos/printing/ppd_cache.h"
@@ -59,13 +60,16 @@ class PpdProviderImpl : public PpdProvider {
PpdProviderImpl(
const std::string& api_key,
scoped_refptr<net::URLRequestContextGetter> url_context_getter,
+ scoped_refptr<base::SequencedTaskRunner> disk_task_runner,
std::unique_ptr<PpdCache> cache,
const PpdProvider::Options& options)
: api_key_(api_key),
forwarding_delegate_(this),
url_context_getter_(url_context_getter),
+ disk_task_runner_(disk_task_runner),
cache_(std::move(cache)),
- options_(options) {
+ options_(options),
+ weak_factory_(this) {
CHECK_GT(options_.max_ppd_contents_size_, 0U);
}
~PpdProviderImpl() override {}
@@ -73,6 +77,21 @@ class PpdProviderImpl : public PpdProvider {
void Resolve(const Printer::PpdReference& ppd_reference,
const PpdProvider::ResolveCallback& cb) override {
CHECK(!cb.is_null());
+ CHECK(base::SequencedTaskRunnerHandle::IsSet())
+ << "Resolve must be called from a SequencedTaskRunner context";
+ CHECK(resolve_fetcher_ == nullptr)
+ << "Can't have concurrent PpdProvider Resolve calls";
+ resolve_done_task_runner_ = base::SequencedTaskRunnerHandle::Get();
stevenjb 2016/11/11 19:26:43 There is a lot of complexity here. I am wondering
Carlson 2016/11/11 23:06:50 I appreciate you taking the time to look carefully
+ disk_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&PpdProviderImpl::ResolveImpl,
+ weak_factory_.GetWeakPtr(), ppd_reference, cb));
stevenjb 2016/11/11 19:26:43 Here we would normally use TaskRunner::PostTaskAnd
Carlson 2016/11/11 23:06:50 I'm not sure that works for what we want here. Or
stevenjb 2016/11/11 23:25:37 See the documentaiton for TaskRunner::PostTaskAndR
+ }
+
+ // Do the work of Resolve on disk_task_runner
+ void ResolveImpl(const Printer::PpdReference& ppd_reference,
+ const PpdProvider::ResolveCallback& cb) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ CHECK(!cb.is_null());
CHECK(resolve_sequence_checker_.CalledOnValidSequence());
CHECK(base::SequencedTaskRunnerHandle::IsSet())
<< "Resolve must be called from a SequencedTaskRunner context";
@@ -82,7 +101,7 @@ class PpdProviderImpl : public PpdProvider {
base::Optional<base::FilePath> tmp = cache_->Find(ppd_reference);
if (tmp) {
// Cache hit. Schedule the callback now and return.
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ resolve_done_task_runner_->PostTask(
FROM_HERE, base::Bind(cb, PpdProvider::SUCCESS, tmp.value()));
stevenjb 2016/11/11 19:26:43 We would need to pass a unique_ptr<FilePath> to th
return;
}
@@ -94,7 +113,7 @@ class PpdProviderImpl : public PpdProvider {
// probably means the quirks server one doesn't work for some reason, so we
// shouldn't silently use it.
if (!ppd_reference.user_supplied_ppd_url.empty()) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ resolve_done_task_runner_->PostTask(
FROM_HERE, base::Bind(cb, PpdProvider::NOT_FOUND, base::FilePath()));
stevenjb 2016/11/11 19:26:44 This would return PpdProvider::NOT_FOUND.
return;
}
@@ -111,27 +130,36 @@ class PpdProviderImpl : public PpdProvider {
net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA);
resolve_fetcher_->Start();
- };
+ }
void AbortResolve() override {
// UrlFetcher guarantees that when the object has been destroyed, no further
// callbacks will occur.
resolve_fetcher_.reset();
+ resolve_done_task_runner_ = nullptr;
}
void QueryAvailable(const QueryAvailableCallback& cb) override {
CHECK(!cb.is_null());
- CHECK(query_sequence_checker_.CalledOnValidSequence());
- CHECK(base::SequencedTaskRunnerHandle::IsSet())
- << "QueryAvailable() must be called from a SequencedTaskRunner context";
CHECK(query_fetcher_ == nullptr)
<< "Can't have concurrent PpdProvider QueryAvailable() calls";
+ CHECK(base::SequencedTaskRunnerHandle::IsSet())
+ << "QueryAvailable() must be called from a SequencedTaskRunner context";
+ query_done_task_runner_ = base::SequencedTaskRunnerHandle::Get();
+ disk_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&PpdProviderImpl::QueryAvailableImpl,
+ weak_factory_.GetWeakPtr(), cb));
+ }
+
+ void QueryAvailableImpl(const QueryAvailableCallback& cb) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ CHECK(query_sequence_checker_.CalledOnValidSequence());
base::Optional<PpdProvider::AvailablePrintersMap> result =
cache_->FindAvailablePrinters();
if (result) {
// Satisfy from cache.
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ query_done_task_runner_->PostTask(
FROM_HERE, base::Bind(cb, PpdProvider::SUCCESS, result.value()));
return;
}
@@ -153,6 +181,7 @@ class PpdProviderImpl : public PpdProvider {
// UrlFetcher guarantees that when the object has been destroyed, no further
// callbacks will occur.
query_fetcher_.reset();
+ query_done_task_runner_ = nullptr;
}
bool CachePpd(const Printer::PpdReference& ppd_reference,
@@ -182,20 +211,25 @@ class PpdProviderImpl : public PpdProvider {
// fetch.
void OnResolveFetchComplete() {
CHECK(resolve_sequence_checker_.CalledOnValidSequence());
- // Scope the allocated |resolve_fetcher_| into this function so we clean it
- // up when we're done here instead of leaving it around until the next
- // Resolve() call.
- auto fetcher = std::move(resolve_fetcher_);
+ // Scope the allocated |resolve_fetcher_| and |resolve_done_task_runner_|
+ // into this function so we clean it up when we're done here instead of
+ // leaving it around until the next Resolve() call.
+ auto task_runner(std::move(resolve_done_task_runner_));
+ auto fetcher(std::move(resolve_fetcher_));
std::string contents;
if (!ValidateAndGetResponseAsString(*fetcher, &contents)) {
// Something went wrong with the fetch.
- resolve_done_callback_.Run(PpdProvider::SERVER_ERROR, base::FilePath());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(resolve_done_callback_,
+ PpdProvider::SERVER_ERROR, base::FilePath()));
return;
}
auto dict = base::DictionaryValue::From(base::JSONReader::Read(contents));
if (dict == nullptr) {
- resolve_done_callback_.Run(PpdProvider::SERVER_ERROR, base::FilePath());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(resolve_done_callback_,
+ PpdProvider::SERVER_ERROR, base::FilePath()));
return;
}
std::string ppd_contents;
@@ -205,7 +239,9 @@ class PpdProviderImpl : public PpdProvider {
dict->GetString(kJSONLastUpdatedKey, &last_updated_time_string) &&
base::StringToUint64(last_updated_time_string, &last_updated_time))) {
// Malformed response. TODO(justincarlson) - LOG something here?
- resolve_done_callback_.Run(PpdProvider::SERVER_ERROR, base::FilePath());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(resolve_done_callback_,
+ PpdProvider::SERVER_ERROR, base::FilePath()));
return;
}
@@ -224,25 +260,31 @@ class PpdProviderImpl : public PpdProvider {
auto ppd_file = cache_->Store(resolve_reference_, ppd_contents);
if (!ppd_file) {
// Failed to store.
- resolve_done_callback_.Run(PpdProvider::INTERNAL_ERROR, base::FilePath());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(resolve_done_callback_,
+ PpdProvider::INTERNAL_ERROR, base::FilePath()));
return;
}
- resolve_done_callback_.Run(PpdProvider::SUCCESS, ppd_file.value());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(resolve_done_callback_, PpdProvider::SUCCESS,
+ ppd_file.value()));
}
// Called on the same thread as QueryAvailable() when the fetcher completes
// its fetch.
void OnQueryAvailableFetchComplete() {
CHECK(query_sequence_checker_.CalledOnValidSequence());
- // Scope the object fetcher into this function so we clean it up when we're
- // done here instead of leaving it around until the next QueryAvailable()
- // call.
- auto fetcher = std::move(query_fetcher_);
+ // Scope the object fetcher and task_runner into this function so we clean
+ // it up when we're done here instead of leaving it around until the next
+ // QueryAvailable() call.
+ auto task_runner(std::move(query_done_task_runner_));
+ auto fetcher(std::move(query_fetcher_));
std::string contents;
if (!ValidateAndGetResponseAsString(*fetcher, &contents)) {
// Something went wrong with the fetch.
- query_done_callback_.Run(PpdProvider::SERVER_ERROR,
- AvailablePrintersMap());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(query_done_callback_, PpdProvider::SERVER_ERROR,
+ AvailablePrintersMap()));
return;
}
@@ -253,8 +295,9 @@ class PpdProviderImpl : public PpdProvider {
const base::ListValue* top_list;
if (top_dict == nullptr || !top_dict->GetList(kJSONTopListKey, &top_list)) {
LOG(ERROR) << "Malformed response from quirks server";
- query_done_callback_.Run(PpdProvider::SERVER_ERROR,
- PpdProvider::AvailablePrintersMap());
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(query_done_callback_, PpdProvider::SERVER_ERROR,
+ AvailablePrintersMap()));
return;
}
@@ -282,6 +325,7 @@ class PpdProviderImpl : public PpdProvider {
}
}
}
+
if (!result.empty()) {
cache_->StoreAvailablePrinters(result);
} else {
@@ -291,7 +335,8 @@ class PpdProviderImpl : public PpdProvider {
LOG(ERROR) << "Available printers map is unexpectedly empty. Refusing "
"to cache this.";
}
- query_done_callback_.Run(PpdProvider::SUCCESS, result);
+ task_runner->PostTask(FROM_HERE, base::Bind(query_done_callback_,
+ PpdProvider::SUCCESS, result));
}
// Generate a url to look up a manufacturer/model from the quirks server
@@ -326,13 +371,17 @@ class PpdProviderImpl : public PpdProvider {
// Reference we're currently trying to resolve.
Printer::PpdReference resolve_reference_;
+ // TaskRunner on which to invoke the Resolve callback;
+ scoped_refptr<base::SequencedTaskRunner> resolve_done_task_runner_;
+
// Callback to invoke on completion.
PpdProvider::ResolveCallback resolve_done_callback_;
// Check that Resolve() and its callback are sequenced appropriately.
base::SequenceChecker resolve_sequence_checker_;
- // Fetcher for the current call, if any.
+ // Fetcher for the current call, if any. resolve_fetcher_ is null if there
+ // is no running Resolve().
std::unique_ptr<net::URLFetcher> resolve_fetcher_;
// State held across a QueryAvailable() call.
@@ -340,6 +389,9 @@ class PpdProviderImpl : public PpdProvider {
// Callback to invoke on completion.
PpdProvider::QueryAvailableCallback query_done_callback_;
+ // TaskRunner on which to invoke the Query Available callback;
+ scoped_refptr<base::SequencedTaskRunner> query_done_task_runner_;
+
// Check that QueryAvailable() and its callback are sequenced appropriately.
base::SequenceChecker query_sequence_checker_;
@@ -353,10 +405,13 @@ class PpdProviderImpl : public PpdProvider {
ForwardingURLFetcherDelegate forwarding_delegate_;
scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
+ scoped_refptr<base::SequencedTaskRunner> disk_task_runner_;
std::unique_ptr<PpdCache> cache_;
// Construction-time options, immutable.
const PpdProvider::Options options_;
+
+ base::WeakPtrFactory<PpdProviderImpl> weak_factory_;
};
void ForwardingURLFetcherDelegate::OnURLFetchComplete(
@@ -370,10 +425,11 @@ void ForwardingURLFetcherDelegate::OnURLFetchComplete(
std::unique_ptr<PpdProvider> PpdProvider::Create(
const std::string& api_key,
scoped_refptr<net::URLRequestContextGetter> url_context_getter,
+ scoped_refptr<base::SequencedTaskRunner> disk_task_runner,
std::unique_ptr<PpdCache> cache,
const PpdProvider::Options& options) {
- return base::MakeUnique<PpdProviderImpl>(api_key, url_context_getter,
- std::move(cache), options);
+ return base::MakeUnique<PpdProviderImpl>(
+ api_key, url_context_getter, disk_task_runner, std::move(cache), options);
}
} // namespace printing

Powered by Google App Engine
This is Rietveld 408576698