Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/storage/SessionStorageCache.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "SessionStorageCache.h"
8
9
namespace mozilla {
10
namespace dom {
11
12
SessionStorageCache::SessionStorageCache()
13
  : mSessionDataSetActive(false)
14
0
{}
15
16
SessionStorageCache::DataSet*
17
SessionStorageCache::Set(DataSetType aDataSetType)
18
0
{
19
0
  if (aDataSetType == eDefaultSetType) {
20
0
    return &mDefaultSet;
21
0
  }
22
0
23
0
  MOZ_ASSERT(aDataSetType == eSessionSetType);
24
0
25
0
  if (!mSessionDataSetActive) {
26
0
    mSessionSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
27
0
28
0
    for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
29
0
      mSessionSet.mKeys.Put(iter.Key(), iter.Data());
30
0
    }
31
0
32
0
    mSessionDataSetActive = true;
33
0
  }
34
0
35
0
  return &mSessionSet;
36
0
}
37
38
int64_t
39
SessionStorageCache::GetOriginQuotaUsage(DataSetType aDataSetType)
40
0
{
41
0
  return Set(aDataSetType)->mOriginQuotaUsage;
42
0
}
43
44
uint32_t
45
SessionStorageCache::Length(DataSetType aDataSetType)
46
0
{
47
0
  return Set(aDataSetType)->mKeys.Count();
48
0
}
49
50
void
51
SessionStorageCache::Key(DataSetType aDataSetType, uint32_t aIndex,
52
                         nsAString& aResult)
53
0
{
54
0
  aResult.SetIsVoid(true);
55
0
  for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
56
0
    if (aIndex == 0) {
57
0
      aResult = iter.Key();
58
0
      return;
59
0
    }
60
0
    aIndex--;
61
0
  }
62
0
}
63
64
void
65
SessionStorageCache::GetItem(DataSetType aDataSetType, const nsAString& aKey,
66
                             nsAString& aResult)
67
0
{
68
0
  // not using AutoString since we don't want to copy buffer to result
69
0
  nsString value;
70
0
  if (!Set(aDataSetType)->mKeys.Get(aKey, &value)) {
71
0
    SetDOMStringToNull(value);
72
0
  }
73
0
  aResult = value;
74
0
}
75
76
void
77
SessionStorageCache::GetKeys(DataSetType aDataSetType, nsTArray<nsString>& aKeys)
78
0
{
79
0
  for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
80
0
    aKeys.AppendElement(iter.Key());
81
0
  }
82
0
}
83
84
nsresult
85
SessionStorageCache::SetItem(DataSetType aDataSetType, const nsAString& aKey,
86
                             const nsAString& aValue, nsString& aOldValue)
87
0
{
88
0
  int64_t delta = 0;
89
0
  DataSet* dataSet = Set(aDataSetType);
90
0
91
0
  if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
92
0
    SetDOMStringToNull(aOldValue);
93
0
94
0
    // We only consider key size if the key doesn't exist before.
95
0
    delta = static_cast<int64_t>(aKey.Length());
96
0
  }
97
0
98
0
  delta += static_cast<int64_t>(aValue.Length()) -
99
0
           static_cast<int64_t>(aOldValue.Length());
100
0
101
0
  if (aValue == aOldValue &&
102
0
      DOMStringIsNull(aValue) == DOMStringIsNull(aOldValue)) {
103
0
    return NS_SUCCESS_DOM_NO_OPERATION;
104
0
  }
105
0
106
0
  if (!dataSet->ProcessUsageDelta(delta)) {
107
0
    return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
108
0
  }
109
0
110
0
  dataSet->mKeys.Put(aKey, nsString(aValue));
111
0
  return NS_OK;
112
0
}
113
114
nsresult
115
SessionStorageCache::RemoveItem(DataSetType aDataSetType, const nsAString& aKey,
116
                                nsString& aOldValue)
117
0
{
118
0
  DataSet* dataSet = Set(aDataSetType);
119
0
120
0
  if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
121
0
    return NS_SUCCESS_DOM_NO_OPERATION;
122
0
  }
123
0
124
0
  // Recalculate the cached data size
125
0
  dataSet->ProcessUsageDelta(-(static_cast<int64_t>(aOldValue.Length()) +
126
0
                               static_cast<int64_t>(aKey.Length())));
127
0
128
0
  dataSet->mKeys.Remove(aKey);
129
0
  return NS_OK;
130
0
}
131
132
void
133
SessionStorageCache::Clear(DataSetType aDataSetType, bool aByUserInteraction)
134
0
{
135
0
  DataSet* dataSet = Set(aDataSetType);
136
0
  dataSet->ProcessUsageDelta(-dataSet->mOriginQuotaUsage);
137
0
  dataSet->mKeys.Clear();
138
0
139
0
  if (!aByUserInteraction && aDataSetType == eSessionSetType) {
140
0
    mSessionDataSetActive = false;
141
0
  }
142
0
}
143
144
already_AddRefed<SessionStorageCache>
145
SessionStorageCache::Clone() const
146
0
{
147
0
  RefPtr<SessionStorageCache> cache = new SessionStorageCache();
148
0
149
0
  cache->mSessionDataSetActive = mSessionDataSetActive;
150
0
151
0
  cache->mDefaultSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
152
0
  for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
153
0
    cache->mDefaultSet.mKeys.Put(iter.Key(), iter.Data());
154
0
  }
155
0
156
0
  cache->mSessionSet.mOriginQuotaUsage = mSessionSet.mOriginQuotaUsage;
157
0
  for (auto iter = mSessionSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
158
0
    cache->mSessionSet.mKeys.Put(iter.Key(), iter.Data());
159
0
  }
160
0
161
0
  return cache.forget();
162
0
}
163
164
bool
165
SessionStorageCache::DataSet::ProcessUsageDelta(int64_t aDelta)
166
0
{
167
0
  // Check limit per this origin
168
0
  uint64_t newOriginUsage = mOriginQuotaUsage + aDelta;
169
0
  if (aDelta > 0 && newOriginUsage > LocalStorageManager::GetQuota()) {
170
0
    return false;
171
0
  }
172
0
173
0
  // Update size in our data set
174
0
  mOriginQuotaUsage = newOriginUsage;
175
0
  return true;
176
0
}
177
178
} // dom namespace
179
} // mozilla namespace