Source code

Revision control

Other Tools

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
#include "mozilla/dom/PContent.h"
10
11
namespace mozilla {
12
namespace dom {
13
14
SessionStorageCache::SessionStorageCache() = default;
15
16
SessionStorageCache::DataSet* SessionStorageCache::Set(
17
DataSetType aDataSetType) {
18
if (aDataSetType == eDefaultSetType) {
19
return &mDefaultSet;
20
}
21
22
MOZ_ASSERT(aDataSetType == eSessionSetType);
23
24
return &mSessionSet;
25
}
26
27
int64_t SessionStorageCache::GetOriginQuotaUsage(DataSetType aDataSetType) {
28
return Set(aDataSetType)->mOriginQuotaUsage;
29
}
30
31
uint32_t SessionStorageCache::Length(DataSetType aDataSetType) {
32
return Set(aDataSetType)->mKeys.Count();
33
}
34
35
void SessionStorageCache::Key(DataSetType aDataSetType, uint32_t aIndex,
36
nsAString& aResult) {
37
aResult.SetIsVoid(true);
38
for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
39
if (aIndex == 0) {
40
aResult = iter.Key();
41
return;
42
}
43
aIndex--;
44
}
45
}
46
47
void SessionStorageCache::GetItem(DataSetType aDataSetType,
48
const nsAString& aKey, nsAString& aResult) {
49
// not using AutoString since we don't want to copy buffer to result
50
nsString value;
51
if (!Set(aDataSetType)->mKeys.Get(aKey, &value)) {
52
SetDOMStringToNull(value);
53
}
54
aResult = value;
55
}
56
57
void SessionStorageCache::GetKeys(DataSetType aDataSetType,
58
nsTArray<nsString>& aKeys) {
59
for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
60
aKeys.AppendElement(iter.Key());
61
}
62
}
63
64
nsresult SessionStorageCache::SetItem(DataSetType aDataSetType,
65
const nsAString& aKey,
66
const nsAString& aValue,
67
nsString& aOldValue) {
68
int64_t delta = 0;
69
DataSet* dataSet = Set(aDataSetType);
70
71
if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
72
SetDOMStringToNull(aOldValue);
73
74
// We only consider key size if the key doesn't exist before.
75
delta = static_cast<int64_t>(aKey.Length());
76
}
77
78
delta += static_cast<int64_t>(aValue.Length()) -
79
static_cast<int64_t>(aOldValue.Length());
80
81
if (aValue == aOldValue &&
82
DOMStringIsNull(aValue) == DOMStringIsNull(aOldValue)) {
83
return NS_SUCCESS_DOM_NO_OPERATION;
84
}
85
86
if (!dataSet->ProcessUsageDelta(delta)) {
87
return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
88
}
89
90
dataSet->mKeys.Put(aKey, nsString(aValue));
91
return NS_OK;
92
}
93
94
nsresult SessionStorageCache::RemoveItem(DataSetType aDataSetType,
95
const nsAString& aKey,
96
nsString& aOldValue) {
97
DataSet* dataSet = Set(aDataSetType);
98
99
if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
100
return NS_SUCCESS_DOM_NO_OPERATION;
101
}
102
103
// Recalculate the cached data size
104
dataSet->ProcessUsageDelta(-(static_cast<int64_t>(aOldValue.Length()) +
105
static_cast<int64_t>(aKey.Length())));
106
107
dataSet->mKeys.Remove(aKey);
108
return NS_OK;
109
}
110
111
void SessionStorageCache::Clear(DataSetType aDataSetType,
112
bool aByUserInteraction) {
113
DataSet* dataSet = Set(aDataSetType);
114
dataSet->ProcessUsageDelta(-dataSet->mOriginQuotaUsage);
115
dataSet->mKeys.Clear();
116
}
117
118
already_AddRefed<SessionStorageCache> SessionStorageCache::Clone() const {
119
RefPtr<SessionStorageCache> cache = new SessionStorageCache();
120
121
cache->mDefaultSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
122
for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
123
cache->mDefaultSet.mKeys.Put(iter.Key(), iter.Data());
124
}
125
126
cache->mSessionSet.mOriginQuotaUsage = mSessionSet.mOriginQuotaUsage;
127
for (auto iter = mSessionSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
128
cache->mSessionSet.mKeys.Put(iter.Key(), iter.Data());
129
}
130
131
return cache.forget();
132
}
133
134
nsTArray<KeyValuePair> SessionStorageCache::SerializeData(
135
DataSetType aDataSetType) {
136
nsTArray<KeyValuePair> data;
137
for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
138
KeyValuePair keyValuePair;
139
keyValuePair.key() = iter.Key();
140
keyValuePair.value() = iter.Data();
141
data.EmplaceBack(std::move(keyValuePair));
142
}
143
return data;
144
}
145
146
void SessionStorageCache::DeserializeData(DataSetType aDataSetType,
147
const nsTArray<KeyValuePair>& aData) {
148
Clear(aDataSetType, false);
149
for (const auto& keyValuePair : aData) {
150
nsString oldValue;
151
SetItem(aDataSetType, keyValuePair.key(), keyValuePair.value(), oldValue);
152
}
153
}
154
155
bool SessionStorageCache::DataSet::ProcessUsageDelta(int64_t aDelta) {
156
// Check limit per this origin
157
uint64_t newOriginUsage = mOriginQuotaUsage + aDelta;
158
if (aDelta > 0 && newOriginUsage > LocalStorageManager::GetQuota()) {
159
return false;
160
}
161
162
// Update size in our data set
163
mOriginQuotaUsage = newOriginUsage;
164
return true;
165
}
166
167
} // namespace dom
168
} // namespace mozilla