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

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
« no previous file with comments | « webkit/blob/blob_storage_context.h ('k') | webkit/blob/blob_storage_context_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_(context->AsWeakPtr()),
49 io_task_runner_(task_runner) {
50 // Ensures the uuid remains registered and the underlying data is not deleted.
51 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
52 context_->IncrementBlobRefCount(blob_data->uuid());
53 blob_data_->AddRef();
54 }
55
56 BlobDataHandle::~BlobDataHandle() {
57 if (io_task_runner_->RunsTasksOnCurrentThread()) {
58 // Note: Do not test context_ on the wrong thread.
michaeln 2013/04/26 00:37:59 changed this code comment to // Note: Do not
59 if (context_.get())
60 context_->DecrementBlobRefCount(blob_data_->uuid());
61 blob_data_->Release();
62 return;
63 }
64
65 io_task_runner_->PostTask(
66 FROM_HERE,
67 base::Bind(&DeleteHelper, context_, base::Unretained(blob_data_)));
68 }
69
70 BlobData* BlobDataHandle::data() const {
71 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
72 return blob_data_;
73 }
74
75 // static
76 void BlobDataHandle::DeleteHelper(
77 base::WeakPtr<BlobStorageContext> context,
78 BlobData* blob_data) {
79 if (context.get())
80 context->DecrementBlobRefCount(blob_data->uuid());
81 blob_data->Release();
82 }
83
84 //-----------------------------------------------------------------------
85 // BlobStorageHost
86 //-----------------------------------------------------------------------
87
88 BlobStorageHost::BlobStorageHost(BlobStorageContext* context)
89 : context_(context->AsWeakPtr()) {
90 }
91
92 BlobStorageHost::~BlobStorageHost() {
93 if (!context_)
94 return;
95 for (std::set<GURL>::iterator iter = public_blob_urls_.begin();
96 iter != public_blob_urls_.end(); ++iter) {
97 context_->RevokePublicBlobURL(*iter);
98 }
99 for (BlobReferenceMap::iterator iter = blobs_inuse_map_.begin();
100 iter != blobs_inuse_map_.end(); ++iter) {
101 for (int i = 0; i < iter->second; ++i)
102 context_->DecrementBlobRefCount(iter->first);
103 }
104 }
105
106 bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) {
107 if (!context_ || uuid.empty() || context_->IsInUse(uuid))
108 return false;
109 context_->StartBuildingBlob(uuid);
110 blobs_inuse_map_[uuid] = 1;
111 return true;
112 }
113
114 bool BlobStorageHost::AppendBlobDataItem(
115 const std::string& uuid, const BlobData::Item& data_item) {
116 if (!context_ || !IsBeingBuiltInHost(uuid))
117 return false;
118 context_->AppendBlobDataItem(uuid, data_item);
119 return true;
120 }
121
122 bool BlobStorageHost::CancelBuildingBlob(const std::string& uuid) {
123 if (!context_ || !IsBeingBuiltInHost(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_ || !IsBeingBuiltInHost(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) || context_->IsBeingBuilt(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_ || !IsInUseInHost(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_ || !IsInUseInHost(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_ || !IsUrlRegisteredInHost(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::IsInUseInHost(const std::string& uuid) {
174 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
175 }
176
177 bool BlobStorageHost::IsBeingBuiltInHost(const std::string& uuid) {
178 return IsInUseInHost(uuid) && context_->IsBeingBuilt(uuid);
179 }
180
181 bool BlobStorageHost::IsUrlRegisteredInHost(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::BlobMapEntry::BlobMapEntry()
190 : refcount(0), flags(0) {
191 }
192
193 BlobStorageContext::BlobMapEntry::BlobMapEntry(
194 int refcount, int flags, BlobData* data)
195 : refcount(refcount), flags(flags), data(data) {
196 }
197
198 BlobStorageContext::BlobMapEntry::~BlobMapEntry() {
199 }
200
201 BlobStorageContext::BlobStorageContext()
36 : memory_usage_(0) { 202 : memory_usage_(0) {
37 } 203 }
38 204
39 BlobStorageController::~BlobStorageController() { 205 BlobStorageContext::~BlobStorageContext() {
40 } 206 }
41 207
42 void BlobStorageController::StartBuildingBlob(const GURL& url) { 208 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
43 DCHECK(url.SchemeIs("blob")); 209 const std::string& uuid) {
44 DCHECK(!BlobUrlHasRef(url)); 210 scoped_ptr<BlobDataHandle> result;
45 BlobData* blob_data = new BlobData; 211 BlobMap::iterator found = blob_map_.find(uuid);
46 unfinalized_blob_map_[url.spec()] = blob_data; 212 if (found == blob_map_.end())
47 IncrementBlobDataUsage(blob_data); 213 return result.Pass();
48 } 214 if (found->second.flags & EXCEEDED_MEMORY)
49 215 return result.Pass();
50 void BlobStorageController::AppendBlobDataItem( 216 DCHECK(!(found->second.flags & BEING_BUILT));
51 const GURL& url, const BlobData::Item& item) { 217 result.reset(new BlobDataHandle(found->second.data, this,
52 DCHECK(url.SchemeIs("blob")); 218 base::MessageLoopProxy::current()));
53 DCHECK(!BlobUrlHasRef(url)); 219 return result.Pass();
54 BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); 220 }
55 if (found == unfinalized_blob_map_.end()) 221
56 return; 222 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
57 BlobData* target_blob_data = found->second; 223 const GURL& url) {
224 BlobURLMap::iterator found = public_blob_urls_.find(
225 BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url);
226 if (found == public_blob_urls_.end())
227 return scoped_ptr<BlobDataHandle>();
228 return GetBlobDataFromUUID(found->second);
229 }
230
231 scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob(
232 const BlobData* data) {
233 StartBuildingBlob(data->uuid());
234 for (std::vector<BlobData::Item>::const_iterator iter =
235 data->items().begin();
236 iter != data->items().end(); ++iter) {
237 AppendBlobDataItem(data->uuid(), *iter);
238 }
239 FinishBuildingBlob(data->uuid(), data->content_type());
240 scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data->uuid());
241 DecrementBlobRefCount(data->uuid());
242 return handle.Pass();
243 }
244
245 void BlobStorageContext::StartBuildingBlob(const std::string& uuid) {
246 DCHECK(!IsInUse(uuid) && !uuid.empty());
247 blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid));
248 }
249
250 void BlobStorageContext::AppendBlobDataItem(
251 const std::string& uuid, const BlobData::Item& item) {
252 DCHECK(IsBeingBuilt(uuid));
253 BlobMap::iterator found = blob_map_.find(uuid);
254 if (found == blob_map_.end())
255 return;
256 if (found->second.flags & EXCEEDED_MEMORY)
257 return;
258 BlobData* target_blob_data = found->second.data;
58 DCHECK(target_blob_data); 259 DCHECK(target_blob_data);
59 260
60 memory_usage_ -= target_blob_data->GetMemoryUsage(); 261 bool exceeded_memory = false;
61 262
62 // The blob data is stored in the "canonical" way. That is, it only contains a 263 // The blob data is stored in the canonical way which only contains a
63 // list of Data and File items. 264 // list of Data, File, and FileSystem items. Aggregated TYPE_BLOB items
64 // 1) The Data item is denoted by the raw data and the range. 265 // are expanded into the primitive constituent types.
266 // 1) The Data item is denoted by the raw data and length.
65 // 2) The File item is denoted by the file path, the range and the expected 267 // 2) The File item is denoted by the file path, the range and the expected
66 // modification time. 268 // modification time.
67 // 3) The FileSystem File item is denoted by the FileSystem URL, the range 269 // 3) The FileSystem File item is denoted by the FileSystem URL, the range
68 // and the expected modification time. 270 // and the expected modification time.
69 // All the Blob items in the passing blob data are resolved and expanded into 271 // 4) The Blob items are expanded.
70 // a set of Data and File items. 272 // TODO(michaeln): Would be nice to avoid copying Data items when expanding.
71 273
72 DCHECK(item.length() > 0); 274 DCHECK(item.length() > 0);
73 switch (item.type()) { 275 switch (item.type()) {
74 case BlobData::Item::TYPE_BYTES: 276 case BlobData::Item::TYPE_BYTES:
75 DCHECK(!item.offset()); 277 DCHECK(!item.offset());
76 target_blob_data->AppendData(item.bytes(), item.length()); 278 exceeded_memory = !AppendBytesItem(target_blob_data,
279 item.bytes(),
280 static_cast<int64>(item.length()));
77 break; 281 break;
78 case BlobData::Item::TYPE_FILE: 282 case BlobData::Item::TYPE_FILE:
79 AppendFileItem(target_blob_data, 283 AppendFileItem(target_blob_data,
80 item.path(), 284 item.path(),
81 item.offset(), 285 item.offset(),
82 item.length(), 286 item.length(),
83 item.expected_modification_time()); 287 item.expected_modification_time());
84 break; 288 break;
85 case BlobData::Item::TYPE_FILE_FILESYSTEM: 289 case BlobData::Item::TYPE_FILE_FILESYSTEM:
86 AppendFileSystemFileItem(target_blob_data, 290 AppendFileSystemFileItem(target_blob_data,
87 item.url(), 291 item.filesystem_url(),
88 item.offset(), 292 item.offset(),
89 item.length(), 293 item.length(),
90 item.expected_modification_time()); 294 item.expected_modification_time());
91 break; 295 break;
92 case BlobData::Item::TYPE_BLOB: { 296 case BlobData::Item::TYPE_BLOB: {
93 BlobData* src_blob_data = GetBlobDataFromUrl(item.url()); 297 scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid());
94 DCHECK(src_blob_data); 298 DCHECK(src.get());
michaeln 2013/04/26 00:26:57 in exceeded_mem situations, this dcheck will trip.
95 if (src_blob_data) 299 if (src.get())
96 AppendStorageItems(target_blob_data, 300 exceeded_memory = !ExpandStorageItems(target_blob_data,
97 src_blob_data, 301 src->data(),
98 item.offset(), 302 item.offset(),
99 item.length()); 303 item.length());
100 break; 304 break;
101 } 305 }
102 default: 306 default:
103 NOTREACHED(); 307 NOTREACHED();
104 break; 308 break;
105 } 309 }
106 310
107 memory_usage_ += target_blob_data->GetMemoryUsage(); 311 // If we're using too much memory, drop this blob's data.
108
109 // If we're using too much memory, drop this blob.
110 // TODO(michaeln): Blob memory storage does not yet spill over to disk, 312 // 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. 313 // as a stop gap, we'll prevent memory usage over a max amount.
112 if (memory_usage_ > kMaxMemoryUsage) 314 if (exceeded_memory) {
113 RemoveBlob(url); 315 memory_usage_ -= target_blob_data->GetMemoryUsage();
316 found->second.flags |= EXCEEDED_MEMORY;
317 found->second.data = new BlobData(uuid);
318 return;
319 }
114 } 320 }
115 321
116 void BlobStorageController::FinishBuildingBlob( 322 void BlobStorageContext::FinishBuildingBlob(
117 const GURL& url, const std::string& content_type) { 323 const std::string& uuid, const std::string& content_type) {
118 DCHECK(url.SchemeIs("blob")); 324 DCHECK(IsBeingBuilt(uuid));
119 DCHECK(!BlobUrlHasRef(url)); 325 BlobMap::iterator found = blob_map_.find(uuid);
120 BlobMap::iterator found = unfinalized_blob_map_.find(url.spec()); 326 if (found == blob_map_.end())
121 if (found == unfinalized_blob_map_.end())
122 return; 327 return;
123 found->second->set_content_type(content_type); 328 found->second.data->set_content_type(content_type);
124 blob_map_[url.spec()] = found->second; 329 found->second.flags &= ~BEING_BUILT;
125 unfinalized_blob_map_.erase(found);
126 } 330 }
127 331
128 void BlobStorageController::AddFinishedBlob(const GURL& url, 332 void BlobStorageContext::CancelBuildingBlob(const std::string& uuid) {
129 const BlobData* data) { 333 DCHECK(IsBeingBuilt(uuid));
130 StartBuildingBlob(url); 334 DecrementBlobRefCount(uuid);
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 } 335 }
138 336
139 void BlobStorageController::CloneBlob( 337 void BlobStorageContext::IncrementBlobRefCount(const std::string& uuid) {
140 const GURL& url, const GURL& src_url) { 338 BlobMap::iterator found = blob_map_.find(uuid);
141 DCHECK(url.SchemeIs("blob")); 339 if (found == blob_map_.end()) {
142 DCHECK(!BlobUrlHasRef(url)); 340 DCHECK(false);
143
144 BlobData* blob_data = GetBlobDataFromUrl(src_url);
145 DCHECK(blob_data);
146 if (!blob_data)
147 return; 341 return;
148 342 }
149 blob_map_[url.spec()] = blob_data; 343 ++(found->second.refcount);
150 IncrementBlobDataUsage(blob_data);
151 } 344 }
152 345
153 void BlobStorageController::RemoveBlob(const GURL& url) { 346 void BlobStorageContext::DecrementBlobRefCount(const std::string& uuid) {
154 DCHECK(url.SchemeIs("blob")); 347 BlobMap::iterator found = blob_map_.find(uuid);
155 DCHECK(!BlobUrlHasRef(url)); 348 if (found == blob_map_.end())
156 349 return;
157 if (!RemoveFromMapHelper(&unfinalized_blob_map_, url)) 350 DCHECK_EQ(found->second.data->uuid(), uuid);
158 RemoveFromMapHelper(&blob_map_, url); 351 if (--(found->second.refcount) == 0) {
352 memory_usage_ -= found->second.data->GetMemoryUsage();
353 blob_map_.erase(found);
354 }
159 } 355 }
160 356
161 bool BlobStorageController::RemoveFromMapHelper( 357 void BlobStorageContext::RegisterPublicBlobURL(
162 BlobMap* map, const GURL& url) { 358 const GURL& blob_url, const std::string& uuid) {
163 BlobMap::iterator found = map->find(url.spec()); 359 DCHECK(!BlobUrlHasRef(blob_url));
164 if (found == map->end()) 360 DCHECK(IsInUse(uuid));
165 return false; 361 DCHECK(!IsUrlRegistered(blob_url));
166 if (DecrementBlobDataUsage(found->second)) 362 IncrementBlobRefCount(uuid);
167 memory_usage_ -= found->second->GetMemoryUsage(); 363 public_blob_urls_[blob_url] = uuid;
168 map->erase(found);
169 return true;
170 } 364 }
171 365
172 366 void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) {
173 BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { 367 DCHECK(!BlobUrlHasRef(blob_url));
174 BlobMap::iterator found = blob_map_.find( 368 if (!IsUrlRegistered(blob_url))
175 BlobUrlHasRef(url) ? ClearBlobUrlRef(url).spec() : url.spec()); 369 return;
176 return (found != blob_map_.end()) ? found->second : NULL; 370 DecrementBlobRefCount(public_blob_urls_[blob_url]);
371 public_blob_urls_.erase(blob_url);
177 } 372 }
178 373
179 void BlobStorageController::AppendStorageItems( 374 bool BlobStorageContext::ExpandStorageItems(
180 BlobData* target_blob_data, BlobData* src_blob_data, 375 BlobData* target_blob_data, BlobData* src_blob_data,
181 uint64 offset, uint64 length) { 376 uint64 offset, uint64 length) {
182 DCHECK(target_blob_data && src_blob_data && 377 DCHECK(target_blob_data && src_blob_data &&
183 length != static_cast<uint64>(-1)); 378 length != static_cast<uint64>(-1));
184 379
185 std::vector<BlobData::Item>::const_iterator iter = 380 std::vector<BlobData::Item>::const_iterator iter =
186 src_blob_data->items().begin(); 381 src_blob_data->items().begin();
187 if (offset) { 382 if (offset) {
188 for (; iter != src_blob_data->items().end(); ++iter) { 383 for (; iter != src_blob_data->items().end(); ++iter) {
189 if (offset >= iter->length()) 384 if (offset >= iter->length())
190 offset -= iter->length(); 385 offset -= iter->length();
191 else 386 else
192 break; 387 break;
193 } 388 }
194 } 389 }
195 390
196 for (; iter != src_blob_data->items().end() && length > 0; ++iter) { 391 for (; iter != src_blob_data->items().end() && length > 0; ++iter) {
197 uint64 current_length = iter->length() - offset; 392 uint64 current_length = iter->length() - offset;
198 uint64 new_length = current_length > length ? length : current_length; 393 uint64 new_length = current_length > length ? length : current_length;
199 if (iter->type() == BlobData::Item::TYPE_BYTES) { 394 if (iter->type() == BlobData::Item::TYPE_BYTES) {
200 target_blob_data->AppendData( 395 if (!AppendBytesItem(
201 iter->bytes() + static_cast<size_t>(iter->offset() + offset), 396 target_blob_data,
202 static_cast<uint32>(new_length)); 397 iter->bytes() + static_cast<size_t>(iter->offset() + offset),
398 static_cast<int64>(new_length))) {
399 return false; // exceeded memory
400 }
203 } else if (iter->type() == BlobData::Item::TYPE_FILE) { 401 } else if (iter->type() == BlobData::Item::TYPE_FILE) {
204 AppendFileItem(target_blob_data, 402 AppendFileItem(target_blob_data,
205 iter->path(), 403 iter->path(),
206 iter->offset() + offset, 404 iter->offset() + offset,
207 new_length, 405 new_length,
208 iter->expected_modification_time()); 406 iter->expected_modification_time());
209 } else { 407 } else {
210 DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); 408 DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM);
211 AppendFileSystemFileItem(target_blob_data, 409 AppendFileSystemFileItem(target_blob_data,
212 iter->url(), 410 iter->filesystem_url(),
213 iter->offset() + offset, 411 iter->offset() + offset,
214 new_length, 412 new_length,
215 iter->expected_modification_time()); 413 iter->expected_modification_time());
216 } 414 }
217 length -= new_length; 415 length -= new_length;
218 offset = 0; 416 offset = 0;
219 } 417 }
418 return true;
220 } 419 }
221 420
222 void BlobStorageController::AppendFileItem( 421 bool BlobStorageContext::AppendBytesItem(
422 BlobData* target_blob_data, const char* bytes, int64 length) {
423 if (length < 0) {
424 DCHECK(false);
425 return false;
426 }
427 if (memory_usage_ + length > kMaxMemoryUsage)
428 return false;
429 target_blob_data->AppendData(bytes, static_cast<size_t>(length));
430 memory_usage_ += length;
431 return true;
432 }
433
434 void BlobStorageContext::AppendFileItem(
223 BlobData* target_blob_data, 435 BlobData* target_blob_data,
224 const base::FilePath& file_path, uint64 offset, uint64 length, 436 const base::FilePath& file_path, uint64 offset, uint64 length,
225 const base::Time& expected_modification_time) { 437 const base::Time& expected_modification_time) {
226 target_blob_data->AppendFile(file_path, offset, length, 438 target_blob_data->AppendFile(file_path, offset, length,
227 expected_modification_time); 439 expected_modification_time);
228 440
229 // It may be a temporary file that should be deleted when no longer needed. 441 // It may be a temporary file that should be deleted when no longer needed.
230 scoped_refptr<ShareableFileReference> shareable_file = 442 scoped_refptr<ShareableFileReference> shareable_file =
231 ShareableFileReference::Get(file_path); 443 ShareableFileReference::Get(file_path);
232 if (shareable_file) 444 if (shareable_file)
233 target_blob_data->AttachShareableFileReference(shareable_file); 445 target_blob_data->AttachShareableFileReference(shareable_file);
234 } 446 }
235 447
236 void BlobStorageController::AppendFileSystemFileItem( 448 void BlobStorageContext::AppendFileSystemFileItem(
237 BlobData* target_blob_data, 449 BlobData* target_blob_data,
238 const GURL& url, uint64 offset, uint64 length, 450 const GURL& filesystem_url, uint64 offset, uint64 length,
239 const base::Time& expected_modification_time) { 451 const base::Time& expected_modification_time) {
240 target_blob_data->AppendFileSystemFile(url, offset, length, 452 target_blob_data->AppendFileSystemFile(filesystem_url, offset, length,
241 expected_modification_time); 453 expected_modification_time);
242 } 454 }
243 455
244 void BlobStorageController::IncrementBlobDataUsage(BlobData* blob_data) { 456 bool BlobStorageContext::IsInUse(const std::string& uuid) {
245 blob_data_usage_count_[blob_data] += 1; 457 return blob_map_.find(uuid) != blob_map_.end();
246 } 458 }
247 459
248 bool BlobStorageController::DecrementBlobDataUsage(BlobData* blob_data) { 460 bool BlobStorageContext::IsBeingBuilt(const std::string& uuid) {
249 BlobDataUsageMap::iterator found = blob_data_usage_count_.find(blob_data); 461 BlobMap::iterator found = blob_map_.find(uuid);
250 DCHECK(found != blob_data_usage_count_.end()); 462 if (found == blob_map_.end())
251 if (--(found->second)) 463 return false;
252 return false; // Still in use 464 return found->second.flags & BEING_BUILT;
253 blob_data_usage_count_.erase(found); 465 }
254 return true; 466
467 bool BlobStorageContext::IsUrlRegistered(const GURL& blob_url) {
468 return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
255 } 469 }
256 470
257 } // namespace webkit_blob 471 } // namespace webkit_blob
OLDNEW
« no previous file with comments | « webkit/blob/blob_storage_context.h ('k') | webkit/blob/blob_storage_context_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698