Commit 8e215a66 authored by ericu@chromium.org's avatar ericu@chromium.org

Allow BlobDataHandles to be copied, and have their UUIDs read, on any thread.

BUG=108012

Review URL: https://codereview.chromium.org/259773006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266817 0039d316-1c4b-4281-b951-d872f2087c98
parent e401d034
......@@ -41,6 +41,7 @@ TEST(BlobStorageContextTest, IncrementDecrementRef) {
blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Make sure its still there after inc/dec.
EXPECT_TRUE(host.IncrementBlobRefCount(kId));
......@@ -48,6 +49,7 @@ TEST(BlobStorageContextTest, IncrementDecrementRef) {
blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Make sure it goes away in the end.
EXPECT_TRUE(host.DecrementBlobRefCount(kId));
......@@ -82,6 +84,7 @@ TEST(BlobStorageContextTest, BlobDataHandle) {
// Should disappear after dropping both handles.
blob_data_handle.reset();
another_handle.reset();
fake_io_message_loop.RunUntilIdle();
blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle);
}
......@@ -150,6 +153,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) {
ASSERT_TRUE(blob_data_handle.get());
EXPECT_EQ(kId, blob_data_handle->data()->uuid());
blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// The url registration should keep the blob alive even after
// explicit references are dropped.
......@@ -157,6 +161,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) {
blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Finally get rid of the url registration and the blob.
EXPECT_TRUE(host.RevokePublicBlobURL(kUrl));
......
......@@ -13,44 +13,56 @@
namespace webkit_blob {
BlobDataHandle::BlobDataHandle(BlobData* blob_data, BlobStorageContext* context,
base::SequencedTaskRunner* task_runner)
BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared(
BlobData* blob_data,
BlobStorageContext* context,
base::SequencedTaskRunner* task_runner)
: blob_data_(blob_data),
context_(context->AsWeakPtr()),
io_task_runner_(task_runner) {
// Ensures the uuid remains registered and the underlying data is not deleted.
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
context_(context->AsWeakPtr()) {
context_->IncrementBlobRefCount(blob_data->uuid());
blob_data_->AddRef();
}
BlobDataHandle::~BlobDataHandle() {
if (io_task_runner_->RunsTasksOnCurrentThread()) {
// Note: Do not test context_ or alter the blob_data_ refcount
// on the wrong thread.
if (context_.get())
context_->DecrementBlobRefCount(blob_data_->uuid());
blob_data_->Release();
return;
}
BlobData* BlobDataHandle::BlobDataHandleShared::data() const {
return blob_data_;
}
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DeleteHelper, context_, base::Unretained(blob_data_)));
const std::string& BlobDataHandle::BlobDataHandleShared::uuid() const {
return blob_data_->uuid();
}
BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() {
if (context_.get())
context_->DecrementBlobRefCount(blob_data_->uuid());
}
BlobDataHandle::BlobDataHandle(BlobData* blob_data,
BlobStorageContext* context,
base::SequencedTaskRunner* task_runner)
: io_task_runner_(task_runner),
shared_(new BlobDataHandleShared(blob_data, context, task_runner)) {
DCHECK(io_task_runner_);
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
}
BlobDataHandle::BlobDataHandle(const BlobDataHandle& other) {
io_task_runner_ = other.io_task_runner_;
shared_ = other.shared_;
}
BlobDataHandle::~BlobDataHandle() {
BlobDataHandleShared* raw = shared_.get();
raw->AddRef();
shared_ = 0;
io_task_runner_->ReleaseSoon(FROM_HERE, raw);
}
BlobData* BlobDataHandle::data() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
return blob_data_;
return shared_->data();
}
// static
void BlobDataHandle::DeleteHelper(
base::WeakPtr<BlobStorageContext> context,
BlobData* blob_data) {
if (context.get())
context->DecrementBlobRefCount(blob_data->uuid());
blob_data->Release();
std::string BlobDataHandle::uuid() const {
return shared_->uuid();
}
} // namespace webkit_blob
......@@ -28,23 +28,42 @@ class BlobStorageContext;
class WEBKIT_STORAGE_BROWSER_EXPORT BlobDataHandle
: public base::SupportsUserData::Data {
public:
BlobDataHandle(const BlobDataHandle& other); // May be copied on any thread.
virtual ~BlobDataHandle(); // Maybe be deleted on any thread.
BlobData* data() const; // May only be accessed on the IO thread.
std::string uuid() const; // May be accessed on any thread.
private:
class BlobDataHandleShared
: public base::RefCountedThreadSafe<BlobDataHandleShared> {
public:
BlobDataHandleShared(BlobData* blob_data,
BlobStorageContext* context,
base::SequencedTaskRunner* task_runner);
BlobData* data() const;
const std::string& uuid() const;
private:
friend class base::DeleteHelper<BlobDataHandleShared>;
friend class base::RefCountedThreadSafe<BlobDataHandleShared>;
friend class BlobDataHandle;
virtual ~BlobDataHandleShared();
scoped_refptr<BlobData> blob_data_;
base::WeakPtr<BlobStorageContext> context_;
DISALLOW_COPY_AND_ASSIGN(BlobDataHandleShared);
};
friend class BlobStorageContext;
BlobDataHandle(BlobData* blob_data, BlobStorageContext* context,
base::SequencedTaskRunner* task_runner);
static void DeleteHelper(
base::WeakPtr<BlobStorageContext> context,
BlobData* blob_data);
BlobData* blob_data_; // Intentionally a raw ptr to a non-thread-safe ref.
base::WeakPtr<BlobStorageContext> context_;
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
DISALLOW_COPY_AND_ASSIGN(BlobDataHandle);
scoped_refptr<BlobDataHandleShared> shared_;
};
} // namespace webkit_blob
......
......@@ -53,7 +53,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext
private:
friend class content::BlobStorageHost;
friend class BlobDataHandle;
friend class BlobDataHandle::BlobDataHandleShared;
friend class ViewBlobInternalsJob;
enum EntryFlags {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment