Line data Source code
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 "SessionStorage.h"
8 : #include "SessionStorageCache.h"
9 : #include "SessionStorageManager.h"
10 :
11 : #include "mozilla/dom/StorageBinding.h"
12 : #include "mozilla/Preferences.h"
13 : #include "nsContentUtils.h"
14 : #include "nsIPrincipal.h"
15 : #include "nsPIDOMWindow.h"
16 :
17 : #define DATASET IsSessionOnly() \
18 : ? SessionStorageCache::eSessionSetType \
19 : : SessionStorageCache::eDefaultSetType
20 :
21 : namespace mozilla {
22 : namespace dom {
23 :
24 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(SessionStorage, Storage, mManager);
25 :
26 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStorage)
27 0 : NS_INTERFACE_MAP_END_INHERITING(Storage)
28 :
29 0 : NS_IMPL_ADDREF_INHERITED(SessionStorage, Storage)
30 0 : NS_IMPL_RELEASE_INHERITED(SessionStorage, Storage)
31 :
32 0 : SessionStorage::SessionStorage(nsPIDOMWindowInner* aWindow,
33 : nsIPrincipal* aPrincipal,
34 : SessionStorageCache* aCache,
35 : SessionStorageManager* aManager,
36 : const nsAString& aDocumentURI,
37 0 : bool aIsPrivate)
38 : : Storage(aWindow, aPrincipal)
39 : , mCache(aCache)
40 : , mManager(aManager)
41 : , mDocumentURI(aDocumentURI)
42 0 : , mIsPrivate(aIsPrivate)
43 : {
44 0 : MOZ_ASSERT(aCache);
45 0 : }
46 :
47 0 : SessionStorage::~SessionStorage()
48 : {
49 0 : }
50 :
51 : already_AddRefed<SessionStorage>
52 0 : SessionStorage::Clone() const
53 : {
54 : RefPtr<SessionStorage> storage =
55 0 : new SessionStorage(GetParentObject(), Principal(), mCache, mManager,
56 0 : mDocumentURI, mIsPrivate);
57 0 : return storage.forget();
58 : }
59 :
60 : int64_t
61 0 : SessionStorage::GetOriginQuotaUsage() const
62 : {
63 0 : return mCache->GetOriginQuotaUsage(DATASET);
64 : }
65 :
66 : uint32_t
67 0 : SessionStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
68 : ErrorResult& aRv)
69 : {
70 0 : if (!CanUseStorage(aSubjectPrincipal)) {
71 0 : aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
72 0 : return 0;
73 : }
74 :
75 0 : return mCache->Length(DATASET);
76 : }
77 :
78 : void
79 0 : SessionStorage::Key(uint32_t aIndex, nsAString& aResult,
80 : nsIPrincipal& aSubjectPrincipal,
81 : ErrorResult& aRv)
82 : {
83 0 : if (!CanUseStorage(aSubjectPrincipal)) {
84 0 : aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
85 0 : return;
86 : }
87 :
88 0 : mCache->Key(DATASET, aIndex, aResult);
89 : }
90 :
91 : void
92 0 : SessionStorage::GetItem(const nsAString& aKey, nsAString& aResult,
93 : nsIPrincipal& aSubjectPrincipal,
94 : ErrorResult& aRv)
95 : {
96 0 : if (!CanUseStorage(aSubjectPrincipal)) {
97 0 : aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
98 0 : return;
99 : }
100 :
101 0 : mCache->GetItem(DATASET, aKey, aResult);
102 : }
103 :
104 : void
105 0 : SessionStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
106 : {
107 0 : if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
108 : // return just an empty array
109 0 : aKeys.Clear();
110 0 : return;
111 : }
112 :
113 0 : mCache->GetKeys(DATASET, aKeys);
114 : }
115 :
116 : void
117 0 : SessionStorage::SetItem(const nsAString& aKey, const nsAString& aValue,
118 : nsIPrincipal& aSubjectPrincipal,
119 : ErrorResult& aRv)
120 : {
121 0 : if (!CanUseStorage(aSubjectPrincipal)) {
122 0 : aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
123 0 : return;
124 : }
125 :
126 0 : nsString oldValue;
127 0 : nsresult rv = mCache->SetItem(DATASET, aKey, aValue, oldValue);
128 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
129 0 : aRv.Throw(rv);
130 0 : return;
131 : }
132 :
133 0 : if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
134 0 : return;
135 : }
136 :
137 0 : BroadcastChangeNotification(aKey, oldValue, aValue);
138 : }
139 :
140 : void
141 0 : SessionStorage::RemoveItem(const nsAString& aKey,
142 : nsIPrincipal& aSubjectPrincipal,
143 : ErrorResult& aRv)
144 : {
145 0 : if (!CanUseStorage(aSubjectPrincipal)) {
146 0 : aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
147 0 : return;
148 : }
149 :
150 0 : nsString oldValue;
151 0 : nsresult rv = mCache->RemoveItem(DATASET, aKey, oldValue);
152 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
153 :
154 0 : if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
155 0 : return;
156 : }
157 :
158 0 : BroadcastChangeNotification(aKey, oldValue, NullString());
159 : }
160 :
161 : void
162 0 : SessionStorage::Clear(nsIPrincipal& aSubjectPrincipal,
163 : ErrorResult& aRv)
164 : {
165 0 : uint32_t length = GetLength(aSubjectPrincipal, aRv);
166 0 : if (!length) {
167 0 : return;
168 : }
169 :
170 0 : mCache->Clear(DATASET);
171 0 : BroadcastChangeNotification(NullString(), NullString(), NullString());
172 : }
173 :
174 : void
175 0 : SessionStorage::BroadcastChangeNotification(const nsAString& aKey,
176 : const nsAString& aOldValue,
177 : const nsAString& aNewValue)
178 : {
179 0 : NotifyChange(this, Principal(), aKey, aOldValue, aNewValue, u"sessionStorage",
180 0 : mDocumentURI, mIsPrivate, false);
181 0 : }
182 :
183 : bool
184 0 : SessionStorage::IsForkOf(const Storage* aOther) const
185 : {
186 0 : MOZ_ASSERT(aOther);
187 0 : if (aOther->Type() != eSessionStorage) {
188 0 : return false;
189 : }
190 :
191 0 : return mCache == static_cast<const SessionStorage*>(aOther)->mCache;
192 : }
193 :
194 : } // dom namespace
195 : } // mozilla namespace
|