1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/fileapi/chrome_blob_storage_context.h"
6
7#include "base/bind.h"
8#include "base/guid.h"
9#include "content/public/browser/blob_handle.h"
10#include "content/public/browser/browser_context.h"
11#include "content/public/browser/browser_thread.h"
12#include "storage/browser/blob/blob_data_handle.h"
13#include "storage/browser/blob/blob_storage_context.h"
14
15using base::UserDataAdapter;
16using storage::BlobStorageContext;
17
18namespace content {
19
20namespace {
21
22const char kBlobStorageContextKeyName[] = "content_blob_storage_context";
23
24class BlobHandleImpl : public BlobHandle {
25 public:
26  explicit BlobHandleImpl(scoped_ptr<storage::BlobDataHandle> handle)
27      : handle_(handle.Pass()) {
28  }
29
30  virtual ~BlobHandleImpl() {}
31
32  virtual std::string GetUUID() OVERRIDE {
33    return handle_->uuid();
34  }
35
36 private:
37  scoped_ptr<storage::BlobDataHandle> handle_;
38};
39
40}  // namespace
41
42ChromeBlobStorageContext::ChromeBlobStorageContext() {}
43
44ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
45    BrowserContext* context) {
46  if (!context->GetUserData(kBlobStorageContextKeyName)) {
47    scoped_refptr<ChromeBlobStorageContext> blob =
48        new ChromeBlobStorageContext();
49    context->SetUserData(
50        kBlobStorageContextKeyName,
51        new UserDataAdapter<ChromeBlobStorageContext>(blob.get()));
52    // Check first to avoid memory leak in unittests.
53    if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
54      BrowserThread::PostTask(
55          BrowserThread::IO, FROM_HERE,
56          base::Bind(&ChromeBlobStorageContext::InitializeOnIOThread, blob));
57    }
58  }
59
60  return UserDataAdapter<ChromeBlobStorageContext>::Get(
61      context, kBlobStorageContextKeyName);
62}
63
64void ChromeBlobStorageContext::InitializeOnIOThread() {
65  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66  context_.reset(new BlobStorageContext());
67}
68
69scoped_ptr<BlobHandle> ChromeBlobStorageContext::CreateMemoryBackedBlob(
70    const char* data, size_t length) {
71  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
72
73  std::string uuid(base::GenerateGUID());
74  scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
75  blob_data->AppendData(data, length);
76
77  scoped_ptr<storage::BlobDataHandle> blob_data_handle =
78      context_->AddFinishedBlob(blob_data.get());
79  if (!blob_data_handle)
80    return scoped_ptr<BlobHandle>();
81
82  scoped_ptr<BlobHandle> blob_handle(
83      new BlobHandleImpl(blob_data_handle.Pass()));
84  return blob_handle.Pass();
85}
86
87ChromeBlobStorageContext::~ChromeBlobStorageContext() {}
88
89void ChromeBlobStorageContext::DeleteOnCorrectThread() const {
90  if (BrowserThread::IsMessageLoopValid(BrowserThread::IO) &&
91      !BrowserThread::CurrentlyOn(BrowserThread::IO)) {
92    BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
93    return;
94  }
95  delete this;
96}
97
98}  // namespace content
99