1// Copyright 2014 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/blob_storage_host.h"
6
7#include "base/sequenced_task_runner.h"
8#include "base/strings/string_util.h"
9#include "storage/browser/blob/blob_data_handle.h"
10#include "storage/browser/blob/blob_storage_context.h"
11#include "url/gurl.h"
12
13using storage::BlobStorageContext;
14using storage::BlobData;
15
16namespace content {
17
18BlobStorageHost::BlobStorageHost(BlobStorageContext* context)
19    : context_(context->AsWeakPtr()) {
20}
21
22BlobStorageHost::~BlobStorageHost() {
23  if (!context_.get())
24    return;
25  for (std::set<GURL>::iterator iter = public_blob_urls_.begin();
26       iter != public_blob_urls_.end(); ++iter) {
27    context_->RevokePublicBlobURL(*iter);
28  }
29  for (BlobReferenceMap::iterator iter = blobs_inuse_map_.begin();
30       iter != blobs_inuse_map_.end(); ++iter) {
31    for (int i = 0; i < iter->second; ++i)
32      context_->DecrementBlobRefCount(iter->first);
33  }
34}
35
36bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) {
37  if (!context_.get() || uuid.empty() || context_->IsInUse(uuid))
38    return false;
39  context_->StartBuildingBlob(uuid);
40  blobs_inuse_map_[uuid] = 1;
41  return true;
42}
43
44bool BlobStorageHost::AppendBlobDataItem(
45    const std::string& uuid, const BlobData::Item& data_item) {
46  if (!context_.get() || !IsBeingBuiltInHost(uuid))
47    return false;
48  context_->AppendBlobDataItem(uuid, data_item);
49  return true;
50}
51
52bool BlobStorageHost::CancelBuildingBlob(const std::string& uuid) {
53  if (!context_.get() || !IsBeingBuiltInHost(uuid))
54    return false;
55  blobs_inuse_map_.erase(uuid);
56  context_->CancelBuildingBlob(uuid);
57  return true;
58}
59
60bool BlobStorageHost::FinishBuildingBlob(
61    const std::string& uuid, const std::string& content_type) {
62  if (!context_.get() || !IsBeingBuiltInHost(uuid))
63    return false;
64  context_->FinishBuildingBlob(uuid, content_type);
65  return true;
66}
67
68bool BlobStorageHost::IncrementBlobRefCount(const std::string& uuid) {
69  if (!context_.get() || !context_->IsInUse(uuid) ||
70      context_->IsBeingBuilt(uuid))
71    return false;
72  context_->IncrementBlobRefCount(uuid);
73  blobs_inuse_map_[uuid] += 1;
74  return true;
75}
76
77bool BlobStorageHost::DecrementBlobRefCount(const std::string& uuid) {
78  if (!context_.get() || !IsInUseInHost(uuid))
79    return false;
80  context_->DecrementBlobRefCount(uuid);
81  blobs_inuse_map_[uuid] -= 1;
82  if (blobs_inuse_map_[uuid] == 0)
83    blobs_inuse_map_.erase(uuid);
84  return true;
85}
86
87bool BlobStorageHost::RegisterPublicBlobURL(
88    const GURL& blob_url, const std::string& uuid) {
89  if (!context_.get() || !IsInUseInHost(uuid) ||
90      context_->IsUrlRegistered(blob_url))
91    return false;
92  context_->RegisterPublicBlobURL(blob_url, uuid);
93  public_blob_urls_.insert(blob_url);
94  return true;
95}
96
97bool BlobStorageHost::RevokePublicBlobURL(const GURL& blob_url) {
98  if (!context_.get() || !IsUrlRegisteredInHost(blob_url))
99    return false;
100  context_->RevokePublicBlobURL(blob_url);
101  public_blob_urls_.erase(blob_url);
102  return true;
103}
104
105bool BlobStorageHost::IsInUseInHost(const std::string& uuid) {
106  return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
107}
108
109bool BlobStorageHost::IsBeingBuiltInHost(const std::string& uuid) {
110  return IsInUseInHost(uuid) && context_->IsBeingBuilt(uuid);
111}
112
113bool BlobStorageHost::IsUrlRegisteredInHost(const GURL& blob_url) {
114  return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
115}
116
117}  // namespace content
118