1 // Copyright 2013 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/common/dom_storage/dom_storage_map.h" 6 7 #include "base/logging.h" 8 9 namespace content { 10 11 namespace { 12 13 size_t size_of_item(const base::string16& key, const base::string16& value) { 14 return (key.length() + value.length()) * sizeof(char16); 15 } 16 17 size_t CountBytes(const DOMStorageValuesMap& values) { 18 if (values.size() == 0) 19 return 0; 20 21 size_t count = 0; 22 DOMStorageValuesMap::const_iterator it = values.begin(); 23 for (; it != values.end(); ++it) 24 count += size_of_item(it->first, it->second.string()); 25 return count; 26 } 27 28 } // namespace 29 30 DOMStorageMap::DOMStorageMap(size_t quota) 31 : bytes_used_(0), 32 quota_(quota) { 33 ResetKeyIterator(); 34 } 35 36 DOMStorageMap::~DOMStorageMap() {} 37 38 unsigned DOMStorageMap::Length() const { 39 return values_.size(); 40 } 41 42 base::NullableString16 DOMStorageMap::Key(unsigned index) { 43 if (index >= values_.size()) 44 return base::NullableString16(); 45 while (last_key_index_ != index) { 46 if (last_key_index_ > index) { 47 --key_iterator_; 48 --last_key_index_; 49 } else { 50 ++key_iterator_; 51 ++last_key_index_; 52 } 53 } 54 return base::NullableString16(key_iterator_->first, false); 55 } 56 57 base::NullableString16 DOMStorageMap::GetItem(const base::string16& key) const { 58 DOMStorageValuesMap::const_iterator found = values_.find(key); 59 if (found == values_.end()) 60 return base::NullableString16(); 61 return found->second; 62 } 63 64 bool DOMStorageMap::SetItem( 65 const base::string16& key, const base::string16& value, 66 base::NullableString16* old_value) { 67 DOMStorageValuesMap::const_iterator found = values_.find(key); 68 if (found == values_.end()) 69 *old_value = base::NullableString16(); 70 else 71 *old_value = found->second; 72 73 size_t old_item_size = old_value->is_null() ? 74 0 : size_of_item(key, old_value->string()); 75 size_t new_item_size = size_of_item(key, value); 76 size_t new_bytes_used = bytes_used_ - old_item_size + new_item_size; 77 78 // Only check quota if the size is increasing, this allows 79 // shrinking changes to pre-existing files that are over budget. 80 if (new_item_size > old_item_size && new_bytes_used > quota_) 81 return false; 82 83 values_[key] = base::NullableString16(value, false); 84 ResetKeyIterator(); 85 bytes_used_ = new_bytes_used; 86 return true; 87 } 88 89 bool DOMStorageMap::RemoveItem( 90 const base::string16& key, 91 base::string16* old_value) { 92 DOMStorageValuesMap::iterator found = values_.find(key); 93 if (found == values_.end()) 94 return false; 95 *old_value = found->second.string(); 96 values_.erase(found); 97 ResetKeyIterator(); 98 bytes_used_ -= size_of_item(key, *old_value); 99 return true; 100 } 101 102 void DOMStorageMap::SwapValues(DOMStorageValuesMap* values) { 103 // Note: A pre-existing file may be over the quota budget. 104 values_.swap(*values); 105 bytes_used_ = CountBytes(values_); 106 ResetKeyIterator(); 107 } 108 109 DOMStorageMap* DOMStorageMap::DeepCopy() const { 110 DOMStorageMap* copy = new DOMStorageMap(quota_); 111 copy->values_ = values_; 112 copy->bytes_used_ = bytes_used_; 113 copy->ResetKeyIterator(); 114 return copy; 115 } 116 117 void DOMStorageMap::ResetKeyIterator() { 118 key_iterator_ = values_.begin(); 119 last_key_index_ = 0; 120 } 121 122 } // namespace content 123