Skip to content

Commit

Permalink
Convert PpdCache and PpdProvider to TaskScheduler.
Browse files Browse the repository at this point in the history
Part of the larger Chromium migration away from BrowserThreads.

BUG=734279, 667892

Review-Url: https://codereview.chromium.org/2939373003
Cr-Commit-Position: refs/heads/master@{#480963}
  • Loading branch information
skau authored and Commit Bot committed Jun 20, 2017
1 parent 156c709 commit 4fb6e69
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 212 deletions.
12 changes: 2 additions & 10 deletions chrome/browser/chromeos/printing/ppd_provider_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chromeos/printing/ppd_cache.h"
#include "chromeos/printing/ppd_provider.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/google_api_keys.h"
#include "net/url_request/url_request_context_getter.h"

Expand All @@ -22,16 +21,9 @@ scoped_refptr<PpdProvider> CreateProvider(Profile* profile) {
base::FilePath ppd_cache_path =
profile->GetPath().Append(FILE_PATH_LITERAL("PPDCache"));

auto cache = PpdCache::Create(ppd_cache_path,
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::CACHE)
.get());

return PpdProvider::Create(g_browser_process->GetApplicationLocale(),
g_browser_process->system_request_context(), cache,
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::FILE)
.get());
g_browser_process->system_request_context(),
PpdCache::Create(ppd_cache_path));
}

} // namespace printing
Expand Down
220 changes: 103 additions & 117 deletions chromeos/printing/ppd_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
Expand All @@ -28,150 +30,134 @@ namespace chromeos {
namespace printing {
namespace {

class PpdCacheImpl : public PpdCache {
public:
PpdCacheImpl(const base::FilePath& cache_base_dir,
const scoped_refptr<base::SequencedTaskRunner>& disk_task_runner)
: cache_base_dir_(cache_base_dir), disk_task_runner_(disk_task_runner) {}

// Public API functions.
void Find(const std::string& key, const FindCallback& cb) override {
// Ensure the cache lives until the op is over.
AddRef();
++inflight_ops_;
disk_task_runner_->PostTask(
FROM_HERE, base::Bind(&PpdCacheImpl::FindImpl, this, key,
base::SequencedTaskRunnerHandle::Get(), cb));
}
// Return the (full) path to the file we expect to find the given key at.
base::FilePath FilePathForKey(const base::FilePath& base_dir,
const std::string& key) {
std::string hashed_key = crypto::SHA256HashString(key);
return base_dir.Append(base::HexEncode(hashed_key.data(), hashed_key.size()));
}

// Store the given contents at the given key. If cb is non-null, it will
// be invoked on completion.
void Store(const std::string& key,
const std::string& contents,
const base::Callback<void()>& cb) override {
AddRef();
++inflight_ops_;
disk_task_runner_->PostTask(
FROM_HERE, base::Bind(&PpdCacheImpl::StoreImpl, this, key, contents,
base::SequencedTaskRunnerHandle::Get(), cb));
// If the cache doesn't already exist, create it.
void MaybeCreateCache(const base::FilePath& base_dir) {
if (!base::PathExists(base_dir)) {
base::CreateDirectory(base_dir);
}
}

bool Idle() const override { return inflight_ops_ == 0; }

private:
~PpdCacheImpl() override {}

// If the cache doesn't already exist, create it.
void MaybeCreateCache() {
if (!base::PathExists(cache_base_dir_)) {
base::CreateDirectory(cache_base_dir_);
}
// Find implementation, blocks on file access. Must be run on a thread that
// allows I/O.
PpdCache::FindResult FindImpl(const base::FilePath& cache_dir,
const std::string& key) {
base::ThreadRestrictions::AssertIOAllowed();

PpdCache::FindResult result;
result.success = false;
if (!base::PathExists(cache_dir)) {
// If the cache dir was missing, we'll miss anyway.
return result;
}

// Find implementation, runs on the i/o thread.
void FindImpl(const std::string& key,
const scoped_refptr<base::SequencedTaskRunner>& callback_runner,
const FindCallback& cb) {
base::ThreadRestrictions::AssertIOAllowed();
FindResult result;
result.success = false;
MaybeCreateCache();
base::File file(FilePathForKey(key),
base::File::FLAG_OPEN | base::File::FLAG_READ);

if (file.IsValid()) {
int64_t len = file.GetLength();
if (len >= static_cast<int64_t>(crypto::kSHA256Length) &&
len <= static_cast<int64_t>(kMaxPpdSizeBytes) +
static_cast<int64_t>(crypto::kSHA256Length)) {
std::unique_ptr<char[]> buf(new char[len]);
if (file.ReadAtCurrentPos(buf.get(), len) == len) {
base::StringPiece contents(buf.get(), len - crypto::kSHA256Length);
base::StringPiece checksum(buf.get() + len - crypto::kSHA256Length,
crypto::kSHA256Length);
if (crypto::SHA256HashString(contents) == checksum) {
base::File::Info info;
if (file.GetInfo(&info)) {
result.success = true;
result.age = base::Time::Now() - info.last_modified;
contents.CopyToString(&result.contents);
}
} else {
LOG(ERROR) << "Bad checksum for cache key " << key;
base::File file(FilePathForKey(cache_dir, key),
base::File::FLAG_OPEN | base::File::FLAG_READ);

if (file.IsValid()) {
int64_t len = file.GetLength();
if (len >= static_cast<int64_t>(crypto::kSHA256Length) &&
len <= static_cast<int64_t>(kMaxPpdSizeBytes) +
static_cast<int64_t>(crypto::kSHA256Length)) {
std::unique_ptr<char[]> buf(new char[len]);
if (file.ReadAtCurrentPos(buf.get(), len) == len) {
base::StringPiece contents(buf.get(), len - crypto::kSHA256Length);
base::StringPiece checksum(buf.get() + len - crypto::kSHA256Length,
crypto::kSHA256Length);
if (crypto::SHA256HashString(contents) == checksum) {
base::File::Info info;
if (file.GetInfo(&info)) {
result.success = true;
result.age = base::Time::Now() - info.last_modified;
contents.CopyToString(&result.contents);
}
} else {
LOG(ERROR) << "Bad checksum for cache key " << key;
}
}
}
callback_runner->PostTask(FROM_HERE,
base::Bind(&PpdCacheImpl::ReplyAndRelease, this,
base::Bind(cb, result)));
}

// If |cb| is non-null, invoke it on this thread, then decrement the refcount.
void ReplyAndRelease(const base::Callback<void()>& cb) {
if (!cb.is_null()) {
cb.Run();
}
--inflight_ops_;
Release();
// Object may be destroyed here, so no further access to object data
// allowed.
}
return result;
}

// Store implementation, runs on the i/o thread.
void StoreImpl(
const std::string& key,
const std::string& contents,
const scoped_refptr<base::SequencedTaskRunner>& callback_runner,
const base::Callback<void()> cb) {
base::ThreadRestrictions::AssertIOAllowed();
MaybeCreateCache();
if (contents.size() > kMaxPpdSizeBytes) {
LOG(ERROR) << "Ignoring attempt to cache large object";
} else {
auto path = FilePathForKey(key);
base::File file(path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
std::string checksum = crypto::SHA256HashString(contents);
if (!file.IsValid() ||
file.WriteAtCurrentPos(contents.data(), contents.size()) !=
static_cast<int>(contents.size()) ||
file.WriteAtCurrentPos(checksum.data(), checksum.size()) !=
static_cast<int>(checksum.size())) {
LOG(ERROR) << "Failed to create ppd cache file";
file.Close();
if (!base::DeleteFile(path, false)) {
LOG(ERROR) << "Failed to cleanup failed creation.";
}
// Store implementation, blocks on file access. Must be run on a thread that
// allows I/O.
void StoreImpl(const base::FilePath& cache_dir,
const std::string& key,
const std::string& contents) {
base::ThreadRestrictions::AssertIOAllowed();

MaybeCreateCache(cache_dir);
if (contents.size() > kMaxPpdSizeBytes) {
LOG(ERROR) << "Ignoring attempt to cache large object";
} else {
auto path = FilePathForKey(cache_dir, key);
base::File file(path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
std::string checksum = crypto::SHA256HashString(contents);
if (!file.IsValid() ||
file.WriteAtCurrentPos(contents.data(), contents.size()) !=
static_cast<int>(contents.size()) ||
file.WriteAtCurrentPos(checksum.data(), checksum.size()) !=
static_cast<int>(checksum.size())) {
LOG(ERROR) << "Failed to create ppd cache file";
file.Close();
if (!base::DeleteFile(path, false)) {
LOG(ERROR) << "Failed to cleanup failed creation.";
}
}
callback_runner->PostTask(
FROM_HERE, base::Bind(&PpdCacheImpl::ReplyAndRelease, this, cb));
}
}

// Return the (full) path to the file we expect to find the given key at.
base::FilePath FilePathForKey(const std::string& key) {
std::string hashed_key = crypto::SHA256HashString(key);
return cache_base_dir_.Append(
base::HexEncode(hashed_key.data(), hashed_key.size()));
class PpdCacheImpl : public PpdCache {
public:
explicit PpdCacheImpl(const base::FilePath& cache_base_dir)
: cache_base_dir_(cache_base_dir),
fetch_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::TaskPriority::USER_VISIBLE, base::MayBlock(),
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
store_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::TaskPriority::BACKGROUND, base::MayBlock(),
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {}

// Public API functions.
void Find(const std::string& key, const FindCallback& cb) override {
base::PostTaskAndReplyWithResult(
fetch_task_runner_.get(), FROM_HERE,
base::Bind(&FindImpl, cache_base_dir_, key), cb);
}

int inflight_ops_ = 0;
// Store the given contents at the given key. If cb is non-null, it will
// be invoked on completion.
void Store(const std::string& key,
const std::string& contents,
const base::Closure& cb) override {
store_task_runner_->PostTaskAndReply(
FROM_HERE, base::Bind(&StoreImpl, cache_base_dir_, key, contents), cb);
}

private:
~PpdCacheImpl() override {}

base::FilePath cache_base_dir_;
scoped_refptr<base::SequencedTaskRunner> disk_task_runner_;
scoped_refptr<base::SequencedTaskRunner> fetch_task_runner_;
scoped_refptr<base::SequencedTaskRunner> store_task_runner_;

DISALLOW_COPY_AND_ASSIGN(PpdCacheImpl);
};

} // namespace

// static
scoped_refptr<PpdCache> PpdCache::Create(
const base::FilePath& cache_base_dir,
scoped_refptr<base::SequencedTaskRunner> disk_task_runner) {
return scoped_refptr<PpdCache>(
new PpdCacheImpl(cache_base_dir, disk_task_runner));
scoped_refptr<PpdCache> PpdCache::Create(const base::FilePath& cache_base_dir) {
return scoped_refptr<PpdCache>(new PpdCacheImpl(cache_base_dir));
}

} // namespace printing
Expand Down
11 changes: 2 additions & 9 deletions chromeos/printing/ppd_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "chromeos/chromeos_export.h"

Expand Down Expand Up @@ -46,9 +45,7 @@ class CHROMEOS_EXPORT PpdCache : public base::RefCounted<PpdCache> {
// Create and return a Ppdcache that uses cache_dir to store state. If
// cache_base_dir does not exist, it will be lazily created the first time the
// cache needs to store state.
static scoped_refptr<PpdCache> Create(
const base::FilePath& cache_base_dir,
scoped_refptr<base::SequencedTaskRunner> disk_task_runner);
static scoped_refptr<PpdCache> Create(const base::FilePath& cache_base_dir);

// Start a Find, looking, for an entry with the given key that is at most
// |max_age| old. |cb| will be invoked on the calling thread.
Expand All @@ -58,11 +55,7 @@ class CHROMEOS_EXPORT PpdCache : public base::RefCounted<PpdCache> {
// be invoked on completion.
virtual void Store(const std::string& key,
const std::string& contents,
const base::Callback<void()>& cb) = 0;

// Hook for testing. Returns true if all outstanding cache operations
// are complete.
virtual bool Idle() const = 0;
const base::Closure& cb) = 0;

protected:
friend class base::RefCounted<PpdCache>;
Expand Down
Loading

0 comments on commit 4fb6e69

Please sign in to comment.