Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(964)

Side by Side Diff: webkit/blob/blob_storage_context.cc

Issue 14139026: New blobstoragecontext for use in the main browser process, not plugged in yet. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/blob/blob_storage_controller.h" 5 #include "webkit/blob/blob_storage_context.h"
6 6
7 #include "base/bind.h"
8 #include "base/location.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop_proxy.h"
11 #include "base/sys_info.h"
8 #include "googleurl/src/gurl.h" 12 #include "googleurl/src/gurl.h"
9 #include "webkit/blob/blob_data.h" 13 #include "webkit/blob/blob_data.h"
10 14
11 namespace webkit_blob { 15 namespace webkit_blob {
12 16
13 namespace { 17 namespace {
14 18
15 // We can't use GURL directly for these hash fragment manipulations 19 // We can't use GURL directly for these hash fragment manipulations
16 // since it doesn't have specific knowlege of the BlobURL format. GURL 20 // since it doesn't have specific knowlege of the BlobURL format. GURL
17 // treats BlobURLs as if they were PathURLs which don't support hash 21 // treats BlobURLs as if they were PathURLs which don't support hash
18 // fragments. 22 // fragments.
19 23
20 bool BlobUrlHasRef(const GURL& url) { 24 bool BlobUrlHasRef(const GURL& url) {
21 return url.spec().find('#') != std::string::npos; 25 return url.spec().find('#') != std::string::npos;
22 } 26 }
23 27
24 GURL ClearBlobUrlRef(const GURL& url) { 28 GURL ClearBlobUrlRef(const GURL& url) {
25 size_t hash_pos = url.spec().find('#'); 29 size_t hash_pos = url.spec().find('#');
26 if (hash_pos == std::string::npos) 30 if (hash_pos == std::string::npos)
27 return url; 31 return url;
28 return GURL(url.spec().substr(0, hash_pos)); 32 return GURL(url.spec().substr(0, hash_pos));
29 } 33 }
30 34
31 static const int64 kMaxMemoryUsage = 1024 * 1024 * 1024; // 1G 35 // TODO(michaeln): use base::SysInfo::AmountOfPhysicalMemoryMB() in some
36 // way to come up with a better limit.
37 static const int64 kMaxMemoryUsage = 500 * 1024 * 1024; // Half a gig.
32 38
33 } // namespace 39 } // namespace
34 40
35 BlobStorageController::BlobStorageController() 41 //-----------------------------------------------------------------------
42 // BlobDataHandle
43 //-----------------------------------------------------------------------
44
45 BlobDataHandle::BlobDataHandle(BlobData* blob_data, BlobStorageContext* context,
46 base::SequencedTaskRunner* task_runner)
47 : blob_data_(blob_data),
48 context_(new base::WeakPtr<BlobStorageContext>(context->AsWeakPtr())),
49 io_task_runner_(task_runner) {
50 // Ensures the uuid remains registered and the underlying data is not deleted.
51 context_->get()->IncrementBlobRefCount(blob_data->uuid());
52 }
53
54 BlobDataHandle::~BlobDataHandle() {
55 if (io_task_runner_->RunsTasksOnCurrentThread()) {
56 if (context_->get())
57 context_->get()->DecrementBlobRefCount(blob_data_->uuid());
58 return;
59 }
60
61 // TODO: Be more careful about manipulating blob_data_ ref and threading.
62 // Currently, this is incorrect.
michaeln 2013/04/23 02:03:15 want to take care of this prior to commiting
63 io_task_runner_->PostTask(
64 FROM_HERE,
65 base::Bind(&DeleteHelper, base::Passed(&context_), blob_data_));
66 }
67
68 BlobData* BlobDataHandle::data() const {
69 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
70 return blob_data_.get();
71 }
72
73 // static
74 void BlobDataHandle::DeleteHelper(
75 scoped_ptr<base::WeakPtr<BlobStorageContext> > context,
76 scoped_refptr<BlobData> blob_data) {
77 if (context->get())
78 context->get()->DecrementBlobRefCount(blob_data->uuid());
79 }
80
81 //-----------------------------------------------------------------------
82 // BlobStorageHost
83 //-----------------------------------------------------------------------
84
85 BlobStorageHost::BlobStorageHost(BlobStorageContext* context)
86 : context_(context->AsWeakPtr()) {
87 }
88
89 BlobStorageHost::~BlobStorageHost() {
90 if (!context_)
91 return;
92 for (std::set<GURL>::iterator iter = public_blob_urls_.begin();
93 iter != public_blob_urls_.end(); ++iter) {
94 context_->RevokePublicBlobURL(*iter);
95 }
96 for (BlobReferenceMap::iterator iter = blobs_inuse_map_.begin();
97 iter != blobs_inuse_map_.end(); ++iter) {
98 for (int i = 0; i < iter->second; ++i)
99 context_->DecrementBlobRefCount(iter->first);
100 }
101 }
102
103 bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) {
104 if (!context_ || IsInUse(uuid) || context_->IsInUse(uuid))
105 return false;
106 context_->StartBuildingBlob(uuid);
107 blobs_inuse_map_[uuid] = 1;
108 return true;
109 }
110
111 bool BlobStorageHost::AppendBlobDataItem(
112 const std::string& uuid, const BlobData::Item& data_item) {
113 if (!context_ || !HasUseCountOfOne(uuid))
114 return false;
115 // TODO: Gotta think thru the case where the client tries to
116 // build too large a blob, and we kill it off. In that case, we could
117 // legitimately get messages to operate on things that do not exist.
michaeln 2013/04/23 02:03:15 ditto, prior to commit
118 context_->AppendBlobDataItem(uuid, data_item);
119 return true;
120 }
121
122 bool BlobStorageHost::CancelBuildingBlob(const std::string& uuid) {
123 if (!context_ || !HasUseCountOfOne(uuid))
124 return false;
125 blobs_inuse_map_.erase(uuid);
126 context_->CancelBuildingBlob(uuid);
127 return true;
128 }
129
130 bool BlobStorageHost::FinishBuildingBlob(
131 const std::string& uuid, const std::string& content_type) {
132 if (!context_ || !HasUseCountOfOne(uuid))
133 return false;
134 context_->FinishBuildingBlob(uuid, content_type);
135 return true;
136 }
137
138 bool BlobStorageHost::IncrementBlobRefCount(const std::string& uuid) {
139 if (!context_ || !context_->IsInUse(uuid))
140 return false;
141 context_->IncrementBlobRefCount(uuid);
142 blobs_inuse_map_[uuid] += 1;
143 return true;
144 }
145
146 bool BlobStorageHost::DecrementBlobRefCount(const std::string& uuid) {
147 if (!context_ || !IsInUse(uuid))
148 return false;
149 context_->DecrementBlobRefCount(uuid);
150 blobs_inuse_map_[uuid] -= 1;
151 if (blobs_inuse_map_[uuid] == 0)
152 blobs_inuse_map_.erase(uuid);
153 return true;
154 }
155
156 bool BlobStorageHost::RegisterPublicBlobURL(
157 const GURL& blob_url, const std::string& uuid) {
158 if (!context_ || !IsInUse(uuid) || context_->IsUrlRegistered(blob_url))
159 return false;
160 context_->RegisterPublicBlobURL(blob_url, uuid);
161 public_blob_urls_.insert(blob_url);
162 return true;
163 }
164
165 bool BlobStorageHost::RevokePublicBlobURL(const GURL& blob_url) {
166 if (!context_ || !IsUrlRegistered(blob_url))
167 return false;
168 context_->RevokePublicBlobURL(blob_url);
169 public_blob_urls_.erase(blob_url);
170 return true;
171 }
172
173 bool BlobStorageHost::IsInUse(const std::string& uuid) {
174 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
175 }
176
177 bool BlobStorageHost::HasUseCountOfOne(const std::string& uuid) {
178 return IsInUse(uuid) && (blobs_inuse_map_[uuid] == 1);
179 }
180
181 bool BlobStorageHost::IsUrlRegistered(const GURL& blob_url) {
182 return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
183 }
184
185 //-----------------------------------------------------------------------
186 // BlobStorageContext
187 //-----------------------------------------------------------------------
188
189 BlobStorageContext::BlobStorageContext()
36 : memory_usage_(0) { 190 : memory_usage_(0) {
37 } 191 }
38 192
39 BlobStorageController::~BlobStorageController() { 193 BlobStorageContext::~BlobStorageContext() {
40 } 194 }
41 195
42 void BlobStorageController::StartBuildingBlob(const GURL& url) { 196 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
43 DCHECK(url.SchemeIs("blob")); 197 const std::string& uuid) {
44 DCHECK(!BlobUrlHasRef(url)); 198 scoped_ptr<BlobDataHandle> result;
45 BlobData* blob_data = new BlobData; 199 BlobMap::iterator found = blob_map_.find(uuid);
46 unfinalized_blob_map_[url.spec()] = blob_data; 200 if (found == blob_map_.end())
47 IncrementBlobDataUsage(blob_data); 201 return result.Pass();
48 } 202 result.reset(new BlobDataHandle(found->second.second, this,
49 203 base::MessageLoopProxy::current()));
50 void BlobStorageController::AppendBlobDataItem( 204 return result.Pass();
51 const GURL& url, const BlobData::Item& item) { 205 }
52 DCHECK(url.SchemeIs("blob")); 206
53 DCHECK(!BlobUrlHasRef(url)); 207 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
54 BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); 208 const GURL& url) {
55 if (found == unfinalized_blob_map_.end()) 209 BlobURLMap::iterator found = public_blob_urls_.find(
210 BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url);
211 if (found == public_blob_urls_.end())
212 return scoped_ptr<BlobDataHandle>();
213 return GetBlobDataFromUUID(found->second);
214 }
215
216 scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob(
217 const BlobData* data) {
218 StartBuildingBlob(data->uuid());
219 for (std::vector<BlobData::Item>::const_iterator iter =
220 data->items().begin();
221 iter != data->items().end(); ++iter) {
222 AppendBlobDataItem(data->uuid(), *iter);
223 // TODO(michaeln): What if we exceed mem limits and it's removed.
224 }
225 FinishBuildingBlob(data->uuid(), data->content_type());
226 scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data->uuid());
227 DecrementBlobRefCount(data->uuid());
228 return handle.Pass();
229 }
230
231 void BlobStorageContext::StartBuildingBlob(const std::string& uuid) {
232 DCHECK(!IsInUse(uuid));
233 blob_map_[uuid] = std::make_pair(1 , new BlobData(uuid));
234 }
235
236 void BlobStorageContext::AppendBlobDataItem(
237 const std::string& uuid, const BlobData::Item& item) {
238 BlobMap::iterator found = blob_map_.find(uuid);
239 if (found == blob_map_.end())
56 return; 240 return;
57 BlobData* target_blob_data = found->second; 241 BlobData* target_blob_data = found->second.second;
58 DCHECK(target_blob_data); 242 DCHECK(target_blob_data);
59 243
60 memory_usage_ -= target_blob_data->GetMemoryUsage(); 244 memory_usage_ -= target_blob_data->GetMemoryUsage();
61 245
62 // The blob data is stored in the "canonical" way. That is, it only contains a 246 // The blob data is stored in the "canonical" way. That is, it only contains a
63 // list of Data and File items. 247 // list of Data and File items.
64 // 1) The Data item is denoted by the raw data and the range. 248 // 1) The Data item is denoted by the raw data and the range.
65 // 2) The File item is denoted by the file path, the range and the expected 249 // 2) The File item is denoted by the file path, the range and the expected
66 // modification time. 250 // modification time.
67 // 3) The FileSystem File item is denoted by the FileSystem URL, the range 251 // 3) The FileSystem File item is denoted by the FileSystem URL, the range
68 // and the expected modification time. 252 // and the expected modification time.
69 // All the Blob items in the passing blob data are resolved and expanded into 253 // All the Blob items in the passing blob data are resolved and expanded into
70 // a set of Data and File items. 254 // a set of Data, File, and FileSystemFile items.
71 255
72 DCHECK(item.length() > 0); 256 DCHECK(item.length() > 0);
73 switch (item.type()) { 257 switch (item.type()) {
74 case BlobData::Item::TYPE_BYTES: 258 case BlobData::Item::TYPE_BYTES:
75 DCHECK(!item.offset()); 259 DCHECK(!item.offset());
76 target_blob_data->AppendData(item.bytes(), item.length()); 260 target_blob_data->AppendData(item.bytes(), item.length());
77 break; 261 break;
78 case BlobData::Item::TYPE_FILE: 262 case BlobData::Item::TYPE_FILE:
79 AppendFileItem(target_blob_data, 263 AppendFileItem(target_blob_data,
80 item.path(), 264 item.path(),
81 item.offset(), 265 item.offset(),
82 item.length(), 266 item.length(),
83 item.expected_modification_time()); 267 item.expected_modification_time());
84 break; 268 break;
85 case BlobData::Item::TYPE_FILE_FILESYSTEM: 269 case BlobData::Item::TYPE_FILE_FILESYSTEM:
86 AppendFileSystemFileItem(target_blob_data, 270 AppendFileSystemFileItem(target_blob_data,
87 item.url(), 271 item.filesystem_url(),
88 item.offset(), 272 item.offset(),
89 item.length(), 273 item.length(),
90 item.expected_modification_time()); 274 item.expected_modification_time());
91 break; 275 break;
92 case BlobData::Item::TYPE_BLOB: { 276 case BlobData::Item::TYPE_BLOB: {
93 BlobData* src_blob_data = GetBlobDataFromUrl(item.url()); 277 scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid());
94 DCHECK(src_blob_data); 278 DCHECK(src.get());
95 if (src_blob_data) 279 if (src.get())
96 AppendStorageItems(target_blob_data, 280 AppendStorageItems(target_blob_data,
97 src_blob_data, 281 src->data(),
98 item.offset(), 282 item.offset(),
99 item.length()); 283 item.length());
100 break; 284 break;
101 } 285 }
102 default: 286 default:
103 NOTREACHED(); 287 NOTREACHED();
104 break; 288 break;
105 } 289 }
106 290
107 memory_usage_ += target_blob_data->GetMemoryUsage(); 291 memory_usage_ += target_blob_data->GetMemoryUsage();
108 292
109 // If we're using too much memory, drop this blob. 293 // If we're using too much memory, drop this blob.
110 // TODO(michaeln): Blob memory storage does not yet spill over to disk, 294 // TODO(michaeln): Blob memory storage does not yet spill over to disk,
111 // until it does, we'll prevent memory usage over a max amount. 295 // until it does, we'll prevent memory usage over a max amount.
112 if (memory_usage_ > kMaxMemoryUsage) 296 if (memory_usage_ > kMaxMemoryUsage) {
113 RemoveBlob(url); 297 // TODO(michaeln): Hoist this test up to before we go over.
298 DCHECK_EQ(1, found->second.first);
299 memory_usage_ -= target_blob_data->GetMemoryUsage();
300 blob_map_.erase(found);
301 }
114 } 302 }
115 303
116 void BlobStorageController::FinishBuildingBlob( 304 void BlobStorageContext::FinishBuildingBlob(
117 const GURL& url, const std::string& content_type) { 305 const std::string& uuid, const std::string& content_type) {
118 DCHECK(url.SchemeIs("blob")); 306 BlobMap::iterator found = blob_map_.find(uuid);
119 DCHECK(!BlobUrlHasRef(url)); 307 if (found == blob_map_.end())
120 BlobMap::iterator found = unfinalized_blob_map_.find(url.spec());
121 if (found == unfinalized_blob_map_.end())
122 return; 308 return;
123 found->second->set_content_type(content_type); 309 found->second.second->set_content_type(content_type);
124 blob_map_[url.spec()] = found->second;
125 unfinalized_blob_map_.erase(found);
126 } 310 }
127 311
128 void BlobStorageController::AddFinishedBlob(const GURL& url, 312 void BlobStorageContext::CancelBuildingBlob(const std::string& uuid) {
129 const BlobData* data) { 313 DecrementBlobRefCount(uuid);
130 StartBuildingBlob(url);
131 for (std::vector<BlobData::Item>::const_iterator iter =
132 data->items().begin();
133 iter != data->items().end(); ++iter) {
134 AppendBlobDataItem(url, *iter);
135 }
136 FinishBuildingBlob(url, data->content_type());
137 } 314 }
138 315
139 void BlobStorageController::CloneBlob( 316 void BlobStorageContext::IncrementBlobRefCount(const std::string& uuid) {
140 const GURL& url, const GURL& src_url) { 317 BlobMap::iterator found = blob_map_.find(uuid);
141 DCHECK(url.SchemeIs("blob")); 318 if (found == blob_map_.end()) {
142 DCHECK(!BlobUrlHasRef(url)); 319 DCHECK(false);
143
144 BlobData* blob_data = GetBlobDataFromUrl(src_url);
145 DCHECK(blob_data);
146 if (!blob_data)
147 return; 320 return;
148 321 }
149 blob_map_[url.spec()] = blob_data; 322 ++(found->second.first);
150 IncrementBlobDataUsage(blob_data);
151 } 323 }
152 324
153 void BlobStorageController::RemoveBlob(const GURL& url) { 325 void BlobStorageContext::DecrementBlobRefCount(const std::string& uuid) {
154 DCHECK(url.SchemeIs("blob")); 326 BlobMap::iterator found = blob_map_.find(uuid);
155 DCHECK(!BlobUrlHasRef(url)); 327 if (found == blob_map_.end())
156 328 return;
157 if (!RemoveFromMapHelper(&unfinalized_blob_map_, url)) 329 DCHECK_EQ(found->second.second->uuid(), uuid);
158 RemoveFromMapHelper(&blob_map_, url); 330 if (--(found->second.first) == 0) {
331 memory_usage_ -= found->second.second->GetMemoryUsage();
332 blob_map_.erase(found);
333 }
159 } 334 }
160 335
161 bool BlobStorageController::RemoveFromMapHelper( 336 void BlobStorageContext::RegisterPublicBlobURL(
162 BlobMap* map, const GURL& url) { 337 const GURL& blob_url, const std::string& uuid) {
163 BlobMap::iterator found = map->find(url.spec()); 338 DCHECK(!BlobUrlHasRef(blob_url));
164 if (found == map->end()) 339 DCHECK(IsInUse(uuid));
165 return false; 340 DCHECK(!IsUrlRegistered(blob_url));
166 if (DecrementBlobDataUsage(found->second)) 341 IncrementBlobRefCount(uuid);
167 memory_usage_ -= found->second->GetMemoryUsage(); 342 public_blob_urls_[blob_url] = uuid;
168 map->erase(found);
169 return true;
170 } 343 }
171 344
172 345 void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) {
173 BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { 346 DCHECK(!BlobUrlHasRef(blob_url));
174 BlobMap::iterator found = blob_map_.find( 347 if (!IsUrlRegistered(blob_url))
175 BlobUrlHasRef(url) ? ClearBlobUrlRef(url).spec() : url.spec()); 348 return;
176 return (found != blob_map_.end()) ? found->second : NULL; 349 DecrementBlobRefCount(public_blob_urls_[blob_url]);
350 public_blob_urls_.erase(blob_url);
177 } 351 }
178 352
179 void BlobStorageController::AppendStorageItems( 353 void BlobStorageContext::AppendStorageItems(
180 BlobData* target_blob_data, BlobData* src_blob_data, 354 BlobData* target_blob_data, BlobData* src_blob_data,
181 uint64 offset, uint64 length) { 355 uint64 offset, uint64 length) {
182 DCHECK(target_blob_data && src_blob_data && 356 DCHECK(target_blob_data && src_blob_data &&
183 length != static_cast<uint64>(-1)); 357 length != static_cast<uint64>(-1));
184 358
185 std::vector<BlobData::Item>::const_iterator iter = 359 std::vector<BlobData::Item>::const_iterator iter =
186 src_blob_data->items().begin(); 360 src_blob_data->items().begin();
187 if (offset) { 361 if (offset) {
188 for (; iter != src_blob_data->items().end(); ++iter) { 362 for (; iter != src_blob_data->items().end(); ++iter) {
189 if (offset >= iter->length()) 363 if (offset >= iter->length())
(...skipping 12 matching lines...) Expand all
202 static_cast<uint32>(new_length)); 376 static_cast<uint32>(new_length));
203 } else if (iter->type() == BlobData::Item::TYPE_FILE) { 377 } else if (iter->type() == BlobData::Item::TYPE_FILE) {
204 AppendFileItem(target_blob_data, 378 AppendFileItem(target_blob_data,
205 iter->path(), 379 iter->path(),
206 iter->offset() + offset, 380 iter->offset() + offset,
207 new_length, 381 new_length,
208 iter->expected_modification_time()); 382 iter->expected_modification_time());
209 } else { 383 } else {
210 DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); 384 DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM);
211 AppendFileSystemFileItem(target_blob_data, 385 AppendFileSystemFileItem(target_blob_data,
212 iter->url(), 386 iter->filesystem_url(),
213 iter->offset() + offset, 387 iter->offset() + offset,
214 new_length, 388 new_length,
215 iter->expected_modification_time()); 389 iter->expected_modification_time());
216 } 390 }
217 length -= new_length; 391 length -= new_length;
218 offset = 0; 392 offset = 0;
219 } 393 }
220 } 394 }
221 395
222 void BlobStorageController::AppendFileItem( 396 void BlobStorageContext::AppendFileItem(
223 BlobData* target_blob_data, 397 BlobData* target_blob_data,
224 const base::FilePath& file_path, uint64 offset, uint64 length, 398 const base::FilePath& file_path, uint64 offset, uint64 length,
225 const base::Time& expected_modification_time) { 399 const base::Time& expected_modification_time) {
226 target_blob_data->AppendFile(file_path, offset, length, 400 target_blob_data->AppendFile(file_path, offset, length,
227 expected_modification_time); 401 expected_modification_time);
228 402
229 // It may be a temporary file that should be deleted when no longer needed. 403 // It may be a temporary file that should be deleted when no longer needed.
230 scoped_refptr<ShareableFileReference> shareable_file = 404 scoped_refptr<ShareableFileReference> shareable_file =
231 ShareableFileReference::Get(file_path); 405 ShareableFileReference::Get(file_path);
232 if (shareable_file) 406 if (shareable_file)
233 target_blob_data->AttachShareableFileReference(shareable_file); 407 target_blob_data->AttachShareableFileReference(shareable_file);
234 } 408 }
235 409
236 void BlobStorageController::AppendFileSystemFileItem( 410 void BlobStorageContext::AppendFileSystemFileItem(
237 BlobData* target_blob_data, 411 BlobData* target_blob_data,
238 const GURL& url, uint64 offset, uint64 length, 412 const GURL& filesystem_url, uint64 offset, uint64 length,
239 const base::Time& expected_modification_time) { 413 const base::Time& expected_modification_time) {
240 target_blob_data->AppendFileSystemFile(url, offset, length, 414 target_blob_data->AppendFileSystemFile(filesystem_url, offset, length,
241 expected_modification_time); 415 expected_modification_time);
242 } 416 }
243 417
244 void BlobStorageController::IncrementBlobDataUsage(BlobData* blob_data) { 418 bool BlobStorageContext::IsInUse(const std::string& uuid) {
245 blob_data_usage_count_[blob_data] += 1; 419 return blob_map_.find(uuid) != blob_map_.end();
246 } 420 }
247 421
248 bool BlobStorageController::DecrementBlobDataUsage(BlobData* blob_data) { 422 bool BlobStorageContext::HasUseCountOfOne(const std::string& uuid) {
249 BlobDataUsageMap::iterator found = blob_data_usage_count_.find(blob_data); 423 return IsInUse(uuid) && (blob_map_[uuid].first == 1);
250 DCHECK(found != blob_data_usage_count_.end()); 424 }
251 if (--(found->second)) 425
252 return false; // Still in use 426 bool BlobStorageContext::IsUrlRegistered(const GURL& blob_url) {
253 blob_data_usage_count_.erase(found); 427 return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
254 return true;
255 } 428 }
256 429
257 } // namespace webkit_blob 430 } // namespace webkit_blob
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698