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) { ...@@ -41,6 +41,7 @@ TEST(BlobStorageContextTest, IncrementDecrementRef) {
blob_data_handle = context.GetBlobDataFromUUID(kId); blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle); EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset(); blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Make sure its still there after inc/dec. // Make sure its still there after inc/dec.
EXPECT_TRUE(host.IncrementBlobRefCount(kId)); EXPECT_TRUE(host.IncrementBlobRefCount(kId));
...@@ -48,6 +49,7 @@ TEST(BlobStorageContextTest, IncrementDecrementRef) { ...@@ -48,6 +49,7 @@ TEST(BlobStorageContextTest, IncrementDecrementRef) {
blob_data_handle = context.GetBlobDataFromUUID(kId); blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle); EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset(); blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Make sure it goes away in the end. // Make sure it goes away in the end.
EXPECT_TRUE(host.DecrementBlobRefCount(kId)); EXPECT_TRUE(host.DecrementBlobRefCount(kId));
...@@ -82,6 +84,7 @@ TEST(BlobStorageContextTest, BlobDataHandle) { ...@@ -82,6 +84,7 @@ TEST(BlobStorageContextTest, BlobDataHandle) {
// Should disappear after dropping both handles. // Should disappear after dropping both handles.
blob_data_handle.reset(); blob_data_handle.reset();
another_handle.reset(); another_handle.reset();
fake_io_message_loop.RunUntilIdle();
blob_data_handle = context.GetBlobDataFromUUID(kId); blob_data_handle = context.GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle); EXPECT_FALSE(blob_data_handle);
} }
...@@ -150,6 +153,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) { ...@@ -150,6 +153,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) {
ASSERT_TRUE(blob_data_handle.get()); ASSERT_TRUE(blob_data_handle.get());
EXPECT_EQ(kId, blob_data_handle->data()->uuid()); EXPECT_EQ(kId, blob_data_handle->data()->uuid());
blob_data_handle.reset(); blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// The url registration should keep the blob alive even after // The url registration should keep the blob alive even after
// explicit references are dropped. // explicit references are dropped.
...@@ -157,6 +161,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) { ...@@ -157,6 +161,7 @@ TEST(BlobStorageContextTest, PublicBlobUrls) {
blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
EXPECT_TRUE(blob_data_handle); EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset(); blob_data_handle.reset();
fake_io_message_loop.RunUntilIdle();
// Finally get rid of the url registration and the blob. // Finally get rid of the url registration and the blob.
EXPECT_TRUE(host.RevokePublicBlobURL(kUrl)); EXPECT_TRUE(host.RevokePublicBlobURL(kUrl));
......
...@@ -13,44 +13,56 @@ ...@@ -13,44 +13,56 @@
namespace webkit_blob { namespace webkit_blob {
BlobDataHandle::BlobDataHandle(BlobData* blob_data, BlobStorageContext* context, BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared(
BlobData* blob_data,
BlobStorageContext* context,
base::SequencedTaskRunner* task_runner) base::SequencedTaskRunner* task_runner)
: blob_data_(blob_data), : blob_data_(blob_data),
context_(context->AsWeakPtr()), 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_->IncrementBlobRefCount(blob_data->uuid()); context_->IncrementBlobRefCount(blob_data->uuid());
blob_data_->AddRef();
} }
BlobDataHandle::~BlobDataHandle() { BlobData* BlobDataHandle::BlobDataHandleShared::data() const {
if (io_task_runner_->RunsTasksOnCurrentThread()) { return blob_data_;
// Note: Do not test context_ or alter the blob_data_ refcount }
// on the wrong thread.
const std::string& BlobDataHandle::BlobDataHandleShared::uuid() const {
return blob_data_->uuid();
}
BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() {
if (context_.get()) if (context_.get())
context_->DecrementBlobRefCount(blob_data_->uuid()); context_->DecrementBlobRefCount(blob_data_->uuid());
blob_data_->Release(); }
return;
}
io_task_runner_->PostTask( BlobDataHandle::BlobDataHandle(BlobData* blob_data,
FROM_HERE, BlobStorageContext* context,
base::Bind(&DeleteHelper, context_, base::Unretained(blob_data_))); 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 { BlobData* BlobDataHandle::data() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
return blob_data_; return shared_->data();
} }
// static std::string BlobDataHandle::uuid() const {
void BlobDataHandle::DeleteHelper( return shared_->uuid();
base::WeakPtr<BlobStorageContext> context,
BlobData* blob_data) {
if (context.get())
context->DecrementBlobRefCount(blob_data->uuid());
blob_data->Release();
} }
} // namespace webkit_blob } // namespace webkit_blob
...@@ -28,23 +28,42 @@ class BlobStorageContext; ...@@ -28,23 +28,42 @@ class BlobStorageContext;
class WEBKIT_STORAGE_BROWSER_EXPORT BlobDataHandle class WEBKIT_STORAGE_BROWSER_EXPORT BlobDataHandle
: public base::SupportsUserData::Data { : public base::SupportsUserData::Data {
public: public:
BlobDataHandle(const BlobDataHandle& other); // May be copied on any thread.
virtual ~BlobDataHandle(); // Maybe be deleted on any thread. virtual ~BlobDataHandle(); // Maybe be deleted on any thread.
BlobData* data() const; // May only be accessed on the IO thread. BlobData* data() const; // May only be accessed on the IO thread.
std::string uuid() const; // May be accessed on any thread.
private: private:
friend class BlobStorageContext; class BlobDataHandleShared
BlobDataHandle(BlobData* blob_data, BlobStorageContext* context, : public base::RefCountedThreadSafe<BlobDataHandleShared> {
public:
BlobDataHandleShared(BlobData* blob_data,
BlobStorageContext* context,
base::SequencedTaskRunner* task_runner); base::SequencedTaskRunner* task_runner);
static void DeleteHelper( BlobData* data() const;
base::WeakPtr<BlobStorageContext> context, const std::string& uuid() const;
BlobData* blob_data);
private:
friend class base::DeleteHelper<BlobDataHandleShared>;
friend class base::RefCountedThreadSafe<BlobDataHandleShared>;
friend class BlobDataHandle;
virtual ~BlobDataHandleShared();
BlobData* blob_data_; // Intentionally a raw ptr to a non-thread-safe ref. scoped_refptr<BlobData> blob_data_;
base::WeakPtr<BlobStorageContext> context_; base::WeakPtr<BlobStorageContext> context_;
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
DISALLOW_COPY_AND_ASSIGN(BlobDataHandle); DISALLOW_COPY_AND_ASSIGN(BlobDataHandleShared);
};
friend class BlobStorageContext;
BlobDataHandle(BlobData* blob_data, BlobStorageContext* context,
base::SequencedTaskRunner* task_runner);
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
scoped_refptr<BlobDataHandleShared> shared_;
}; };
} // namespace webkit_blob } // namespace webkit_blob
......
...@@ -53,7 +53,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext ...@@ -53,7 +53,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT BlobStorageContext
private: private:
friend class content::BlobStorageHost; friend class content::BlobStorageHost;
friend class BlobDataHandle; friend class BlobDataHandle::BlobDataHandleShared;
friend class ViewBlobInternalsJob; friend class ViewBlobInternalsJob;
enum EntryFlags { 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