Home | History | Annotate | Download | only in dom_storage
      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(base::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