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/. */
7 #include "SessionStorageCache.h"
9 #include "mozilla/dom/PContent.h"
14 SessionStorageCache::SessionStorageCache() = default;
16 SessionStorageCache::DataSet
* SessionStorageCache::Set(
17 DataSetType aDataSetType
) {
18 if (aDataSetType
== eDefaultSetType
) {
22 MOZ_ASSERT(aDataSetType
== eSessionSetType
);
27 int64_t SessionStorageCache::GetOriginQuotaUsage(DataSetType aDataSetType
) {
28 return Set(aDataSetType
)->mOriginQuotaUsage
;
31 uint32_t SessionStorageCache::Length(DataSetType aDataSetType
) {
32 return Set(aDataSetType
)->mKeys
.Count();
35 void SessionStorageCache::Key(DataSetType aDataSetType
, uint32_t aIndex
,
37 aResult
.SetIsVoid(true);
38 for (auto iter
= Set(aDataSetType
)->mKeys
.Iter(); !iter
.Done(); iter
.Next()) {
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
51 if (!Set(aDataSetType
)->mKeys
.Get(aKey
, &value
)) {
52 SetDOMStringToNull(value
);
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());
64 nsresult
SessionStorageCache::SetItem(DataSetType aDataSetType
,
65 const nsAString
& aKey
,
66 const nsAString
& aValue
,
67 nsString
& aOldValue
) {
69 DataSet
* dataSet
= Set(aDataSetType
);
71 if (!dataSet
->mKeys
.Get(aKey
, &aOldValue
)) {
72 SetDOMStringToNull(aOldValue
);
74 // We only consider key size if the key doesn't exist before.
75 delta
= static_cast<int64_t>(aKey
.Length());
78 delta
+= static_cast<int64_t>(aValue
.Length()) -
79 static_cast<int64_t>(aOldValue
.Length());
81 if (aValue
== aOldValue
&&
82 DOMStringIsNull(aValue
) == DOMStringIsNull(aOldValue
)) {
83 return NS_SUCCESS_DOM_NO_OPERATION
;
86 if (!dataSet
->ProcessUsageDelta(delta
)) {
87 return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR
;
90 dataSet
->mKeys
.Put(aKey
, nsString(aValue
));
94 nsresult
SessionStorageCache::RemoveItem(DataSetType aDataSetType
,
95 const nsAString
& aKey
,
96 nsString
& aOldValue
) {
97 DataSet
* dataSet
= Set(aDataSetType
);
99 if (!dataSet
->mKeys
.Get(aKey
, &aOldValue
)) {
100 return NS_SUCCESS_DOM_NO_OPERATION
;
103 // Recalculate the cached data size
104 dataSet
->ProcessUsageDelta(-(static_cast<int64_t>(aOldValue
.Length()) +
105 static_cast<int64_t>(aKey
.Length())));
107 dataSet
->mKeys
.Remove(aKey
);
111 void SessionStorageCache::Clear(DataSetType aDataSetType
,
112 bool aByUserInteraction
) {
113 DataSet
* dataSet
= Set(aDataSetType
);
114 dataSet
->ProcessUsageDelta(-dataSet
->mOriginQuotaUsage
);
115 dataSet
->mKeys
.Clear();
118 already_AddRefed
<SessionStorageCache
> SessionStorageCache::Clone() const {
119 RefPtr
<SessionStorageCache
> cache
= new SessionStorageCache();
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());
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());
131 return cache
.forget();
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
));
146 void SessionStorageCache::DeserializeData(DataSetType aDataSetType
,
147 const nsTArray
<KeyValuePair
>& aData
) {
148 Clear(aDataSetType
, false);
149 for (const auto& keyValuePair
: aData
) {
151 SetItem(aDataSetType
, keyValuePair
.key(), keyValuePair
.value(), oldValue
);
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()) {
162 // Update size in our data set
163 mOriginQuotaUsage
= newOriginUsage
;
168 } // namespace mozilla