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 "PartitionedLocalStorage.h"
8 #include "SessionStorageCache.h"
9 #include "nsContentUtils.h"
10
11 #include "mozilla/dom/StorageBinding.h"
12
13 namespace mozilla {
14 namespace dom {
15
16 NS_IMPL_CYCLE_COLLECTION_INHERITED(PartitionedLocalStorage, Storage);
17
18 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PartitionedLocalStorage)
NS_INTERFACE_MAP_END_INHERITING(Storage)19 NS_INTERFACE_MAP_END_INHERITING(Storage)
20
21 NS_IMPL_ADDREF_INHERITED(PartitionedLocalStorage, Storage)
22 NS_IMPL_RELEASE_INHERITED(PartitionedLocalStorage, Storage)
23
24 PartitionedLocalStorage::PartitionedLocalStorage(
25 nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
26 nsIPrincipal* aStoragePrincipal, SessionStorageCache* aCache)
27 : Storage(aWindow, aPrincipal, aStoragePrincipal), mCache(aCache) {}
28
29 PartitionedLocalStorage::~PartitionedLocalStorage() = default;
30
GetOriginQuotaUsage() const31 int64_t PartitionedLocalStorage::GetOriginQuotaUsage() const {
32 return mCache->GetOriginQuotaUsage();
33 }
34
GetLength(nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)35 uint32_t PartitionedLocalStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
36 ErrorResult& aRv) {
37 if (!CanUseStorage(aSubjectPrincipal)) {
38 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
39 return 0;
40 }
41
42 return mCache->Length();
43 }
44
Key(uint32_t aIndex,nsAString & aResult,nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)45 void PartitionedLocalStorage::Key(uint32_t aIndex, nsAString& aResult,
46 nsIPrincipal& aSubjectPrincipal,
47 ErrorResult& aRv) {
48 if (!CanUseStorage(aSubjectPrincipal)) {
49 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
50 return;
51 }
52
53 mCache->Key(aIndex, aResult);
54 }
55
GetItem(const nsAString & aKey,nsAString & aResult,nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)56 void PartitionedLocalStorage::GetItem(const nsAString& aKey, nsAString& aResult,
57 nsIPrincipal& aSubjectPrincipal,
58 ErrorResult& aRv) {
59 if (!CanUseStorage(aSubjectPrincipal)) {
60 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
61 return;
62 }
63
64 mCache->GetItem(aKey, aResult);
65 }
66
GetSupportedNames(nsTArray<nsString> & aKeys)67 void PartitionedLocalStorage::GetSupportedNames(nsTArray<nsString>& aKeys) {
68 if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
69 // return just an empty array
70 aKeys.Clear();
71 return;
72 }
73
74 mCache->GetKeys(aKeys);
75 }
76
SetItem(const nsAString & aKey,const nsAString & aValue,nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)77 void PartitionedLocalStorage::SetItem(const nsAString& aKey,
78 const nsAString& aValue,
79 nsIPrincipal& aSubjectPrincipal,
80 ErrorResult& aRv) {
81 if (!CanUseStorage(aSubjectPrincipal)) {
82 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
83 return;
84 }
85
86 nsString oldValue;
87 nsresult rv = mCache->SetItem(aKey, aValue, oldValue);
88 if (NS_WARN_IF(NS_FAILED(rv))) {
89 aRv.Throw(rv);
90 return;
91 }
92
93 if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
94 return;
95 }
96 }
97
RemoveItem(const nsAString & aKey,nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)98 void PartitionedLocalStorage::RemoveItem(const nsAString& aKey,
99 nsIPrincipal& aSubjectPrincipal,
100 ErrorResult& aRv) {
101 if (!CanUseStorage(aSubjectPrincipal)) {
102 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
103 return;
104 }
105
106 nsString oldValue;
107 nsresult rv = mCache->RemoveItem(aKey, oldValue);
108 MOZ_ASSERT(NS_SUCCEEDED(rv));
109
110 if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
111 return;
112 }
113 }
114
Clear(nsIPrincipal & aSubjectPrincipal,ErrorResult & aRv)115 void PartitionedLocalStorage::Clear(nsIPrincipal& aSubjectPrincipal,
116 ErrorResult& aRv) {
117 uint32_t length = GetLength(aSubjectPrincipal, aRv);
118 if (!length) {
119 return;
120 }
121
122 mCache->Clear();
123 }
124
IsForkOf(const Storage * aOther) const125 bool PartitionedLocalStorage::IsForkOf(const Storage* aOther) const {
126 MOZ_ASSERT(aOther);
127 if (aOther->Type() != eLocalStorage) {
128 return false;
129 }
130
131 return mCache == static_cast<const PartitionedLocalStorage*>(aOther)->mCache;
132 }
133
134 } // namespace dom
135 } // namespace mozilla
136