Bug 1660051 [wpt PR 25111] - Origin isolation: expand getter test coverage, a=testonly
[gecko.git] / dom / storage / SessionStorageCache.cpp
blob306f474c4515fd7bd30a5b9c4660003942ea872f
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"
11 namespace mozilla {
12 namespace dom {
14 SessionStorageCache::SessionStorageCache() = default;
16 SessionStorageCache::DataSet* SessionStorageCache::Set(
17 DataSetType aDataSetType) {
18 if (aDataSetType == eDefaultSetType) {
19 return &mDefaultSet;
22 MOZ_ASSERT(aDataSetType == eSessionSetType);
24 return &mSessionSet;
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,
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;
43 aIndex--;
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);
54 aResult = 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) {
68 int64_t delta = 0;
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));
91 return NS_OK;
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);
108 return NS_OK;
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));
143 return data;
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);
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;
162 // Update size in our data set
163 mOriginQuotaUsage = newOriginUsage;
164 return true;
167 } // namespace dom
168 } // namespace mozilla