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