Line data Source code
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 0 : SessionStorageCache::SessionStorageCache()
13 0 : : mSessionDataSetActive(false)
14 0 : {}
15 :
16 : SessionStorageCache::DataSet*
17 0 : SessionStorageCache::Set(DataSetType aDataSetType)
18 : {
19 0 : if (aDataSetType == eDefaultSetType) {
20 0 : return &mDefaultSet;
21 : }
22 :
23 0 : MOZ_ASSERT(aDataSetType == eSessionSetType);
24 :
25 0 : if (!mSessionDataSetActive) {
26 0 : mSessionSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
27 :
28 0 : for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
29 0 : mSessionSet.mKeys.Put(iter.Key(), iter.Data());
30 : }
31 :
32 0 : mSessionDataSetActive = true;
33 : }
34 :
35 0 : return &mSessionSet;
36 : }
37 :
38 : int64_t
39 0 : SessionStorageCache::GetOriginQuotaUsage(DataSetType aDataSetType)
40 : {
41 0 : return Set(aDataSetType)->mOriginQuotaUsage;
42 : }
43 :
44 : uint32_t
45 0 : SessionStorageCache::Length(DataSetType aDataSetType)
46 : {
47 0 : return Set(aDataSetType)->mKeys.Count();
48 : }
49 :
50 : void
51 0 : SessionStorageCache::Key(DataSetType aDataSetType, uint32_t aIndex,
52 : nsAString& aResult)
53 : {
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 : }
60 0 : aIndex--;
61 : }
62 : }
63 :
64 : void
65 0 : SessionStorageCache::GetItem(DataSetType aDataSetType, const nsAString& aKey,
66 : nsAString& aResult)
67 : {
68 : // 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 : }
73 0 : aResult = value;
74 0 : }
75 :
76 : void
77 0 : SessionStorageCache::GetKeys(DataSetType aDataSetType, nsTArray<nsString>& aKeys)
78 : {
79 0 : for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
80 0 : aKeys.AppendElement(iter.Key());
81 : }
82 0 : }
83 :
84 : nsresult
85 0 : SessionStorageCache::SetItem(DataSetType aDataSetType, const nsAString& aKey,
86 : const nsAString& aValue, nsString& aOldValue)
87 : {
88 0 : int64_t delta = 0;
89 0 : DataSet* dataSet = Set(aDataSetType);
90 :
91 0 : if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
92 0 : SetDOMStringToNull(aOldValue);
93 :
94 : // We only consider key size if the key doesn't exist before.
95 0 : delta = static_cast<int64_t>(aKey.Length());
96 : }
97 :
98 0 : delta += static_cast<int64_t>(aValue.Length()) -
99 0 : static_cast<int64_t>(aOldValue.Length());
100 :
101 0 : if (aValue == aOldValue &&
102 0 : DOMStringIsNull(aValue) == DOMStringIsNull(aOldValue)) {
103 0 : return NS_SUCCESS_DOM_NO_OPERATION;
104 : }
105 :
106 0 : if (!dataSet->ProcessUsageDelta(delta)) {
107 0 : return NS_ERROR_DOM_QUOTA_REACHED;
108 : }
109 :
110 0 : dataSet->mKeys.Put(aKey, nsString(aValue));
111 0 : return NS_OK;
112 : }
113 :
114 : nsresult
115 0 : SessionStorageCache::RemoveItem(DataSetType aDataSetType, const nsAString& aKey,
116 : nsString& aOldValue)
117 : {
118 0 : DataSet* dataSet = Set(aDataSetType);
119 :
120 0 : if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
121 0 : return NS_SUCCESS_DOM_NO_OPERATION;
122 : }
123 :
124 : // Recalculate the cached data size
125 0 : dataSet->ProcessUsageDelta(-(static_cast<int64_t>(aOldValue.Length()) +
126 0 : static_cast<int64_t>(aKey.Length())));
127 :
128 0 : dataSet->mKeys.Remove(aKey);
129 0 : return NS_OK;
130 : }
131 :
132 : void
133 0 : SessionStorageCache::Clear(DataSetType aDataSetType, bool aByUserInteraction)
134 : {
135 0 : DataSet* dataSet = Set(aDataSetType);
136 0 : dataSet->ProcessUsageDelta(-dataSet->mOriginQuotaUsage);
137 0 : dataSet->mKeys.Clear();
138 :
139 0 : if (!aByUserInteraction && aDataSetType == eSessionSetType) {
140 0 : mSessionDataSetActive = false;
141 : }
142 0 : }
143 :
144 : already_AddRefed<SessionStorageCache>
145 0 : SessionStorageCache::Clone() const
146 : {
147 0 : RefPtr<SessionStorageCache> cache = new SessionStorageCache();
148 :
149 0 : cache->mSessionDataSetActive = mSessionDataSetActive;
150 :
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 : }
155 :
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 : }
160 :
161 0 : return cache.forget();
162 : }
163 :
164 : bool
165 0 : SessionStorageCache::DataSet::ProcessUsageDelta(int64_t aDelta)
166 : {
167 : // 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 : }
172 :
173 : // Update size in our data set
174 0 : mOriginQuotaUsage = newOriginUsage;
175 0 : return true;
176 : }
177 :
178 : } // dom namespace
179 : } // mozilla namespace
|