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 "SessionStorageManager.h"
8 :
9 : #include "SessionStorage.h"
10 : #include "SessionStorageCache.h"
11 : #include "StorageUtils.h"
12 :
13 : namespace mozilla {
14 : namespace dom {
15 :
16 : using namespace StorageUtils;
17 :
18 7 : NS_IMPL_ISUPPORTS(SessionStorageManager, nsIDOMStorageManager)
19 :
20 1 : SessionStorageManager::SessionStorageManager()
21 : {
22 1 : StorageObserver* observer = StorageObserver::Self();
23 1 : NS_ASSERTION(observer, "No StorageObserver, cannot observe private data delete notifications!");
24 :
25 1 : if (observer) {
26 1 : observer->AddSink(this);
27 : }
28 1 : }
29 :
30 0 : SessionStorageManager::~SessionStorageManager()
31 : {
32 0 : StorageObserver* observer = StorageObserver::Self();
33 0 : if (observer) {
34 0 : observer->RemoveSink(this);
35 : }
36 0 : }
37 :
38 : NS_IMETHODIMP
39 0 : SessionStorageManager::PrecacheStorage(nsIPrincipal* aPrincipal,
40 : nsIDOMStorage** aRetval)
41 : {
42 : // Nothing to preload.
43 0 : return NS_OK;
44 : }
45 :
46 : NS_IMETHODIMP
47 0 : SessionStorageManager::CreateStorage(mozIDOMWindow* aWindow,
48 : nsIPrincipal* aPrincipal,
49 : const nsAString& aDocumentURI,
50 : bool aPrivate,
51 : nsIDOMStorage** aRetval)
52 : {
53 0 : nsAutoCString originKey;
54 0 : nsAutoCString originAttributes;
55 0 : nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
56 0 : if (NS_FAILED(rv)) {
57 0 : return NS_ERROR_NOT_AVAILABLE;
58 : }
59 :
60 : OriginKeyHashTable* table;
61 0 : if (!mOATable.Get(originAttributes, &table)) {
62 0 : table = new OriginKeyHashTable();
63 0 : mOATable.Put(originAttributes, table);
64 : }
65 :
66 0 : RefPtr<SessionStorageCache> cache;
67 0 : if (!table->Get(originKey, getter_AddRefs(cache))) {
68 0 : cache = new SessionStorageCache();
69 0 : table->Put(originKey, cache);
70 : }
71 :
72 0 : nsCOMPtr<nsPIDOMWindowInner> inner = nsPIDOMWindowInner::From(aWindow);
73 :
74 : RefPtr<SessionStorage> storage =
75 0 : new SessionStorage(inner, aPrincipal, cache, this, aDocumentURI, aPrivate);
76 :
77 0 : storage.forget(aRetval);
78 0 : return NS_OK;
79 : }
80 :
81 : NS_IMETHODIMP
82 1 : SessionStorageManager::GetStorage(mozIDOMWindow* aWindow,
83 : nsIPrincipal* aPrincipal,
84 : bool aPrivate,
85 : nsIDOMStorage** aRetval)
86 : {
87 1 : *aRetval = nullptr;
88 :
89 2 : nsAutoCString originKey;
90 2 : nsAutoCString originAttributes;
91 1 : nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
92 1 : if (NS_FAILED(rv)) {
93 0 : return rv;
94 : }
95 :
96 : OriginKeyHashTable* table;
97 1 : if (!mOATable.Get(originAttributes, &table)) {
98 1 : return NS_OK;
99 : }
100 :
101 0 : RefPtr<SessionStorageCache> cache;
102 0 : if (!table->Get(originKey, getter_AddRefs(cache))) {
103 0 : return NS_OK;
104 : }
105 :
106 0 : nsCOMPtr<nsPIDOMWindowInner> inner = nsPIDOMWindowInner::From(aWindow);
107 :
108 : RefPtr<SessionStorage> storage =
109 0 : new SessionStorage(inner, aPrincipal, cache, this, EmptyString(), aPrivate);
110 :
111 0 : storage.forget(aRetval);
112 0 : return NS_OK;
113 : }
114 :
115 : NS_IMETHODIMP
116 0 : SessionStorageManager::CloneStorage(nsIDOMStorage* aStorage)
117 : {
118 0 : if (NS_WARN_IF(!aStorage)) {
119 0 : return NS_ERROR_UNEXPECTED;
120 : }
121 :
122 0 : RefPtr<Storage> storage = static_cast<Storage*>(aStorage);
123 0 : if (storage->Type() != Storage::eSessionStorage) {
124 0 : return NS_ERROR_UNEXPECTED;
125 : }
126 :
127 0 : nsAutoCString originKey;
128 0 : nsAutoCString originAttributes;
129 0 : nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes,
130 0 : originKey);
131 0 : if (NS_FAILED(rv)) {
132 0 : return rv;
133 : }
134 :
135 : OriginKeyHashTable* table;
136 0 : if (!mOATable.Get(originAttributes, &table)) {
137 0 : table = new OriginKeyHashTable();
138 0 : mOATable.Put(originAttributes, table);
139 : }
140 :
141 0 : RefPtr<SessionStorageCache> cache;
142 0 : if (table->Get(originKey, getter_AddRefs(cache))) {
143 : // Do not replace an existing sessionStorage.
144 0 : return NS_OK;
145 : }
146 :
147 0 : cache = static_cast<SessionStorage*>(aStorage)->Cache()->Clone();
148 0 : MOZ_ASSERT(cache);
149 :
150 0 : table->Put(originKey, cache);
151 0 : return NS_OK;
152 : }
153 :
154 : NS_IMETHODIMP
155 0 : SessionStorageManager::CheckStorage(nsIPrincipal* aPrincipal,
156 : nsIDOMStorage* aStorage,
157 : bool* aRetval)
158 : {
159 0 : if (NS_WARN_IF(!aStorage)) {
160 0 : return NS_ERROR_UNEXPECTED;
161 : }
162 :
163 0 : if (!aPrincipal) {
164 0 : return NS_ERROR_NOT_AVAILABLE;
165 : }
166 :
167 0 : nsAutoCString originKey;
168 0 : nsAutoCString originAttributes;
169 0 : nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
170 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
171 0 : return rv;
172 : }
173 :
174 0 : *aRetval = false;
175 :
176 : OriginKeyHashTable* table;
177 0 : if (!mOATable.Get(originAttributes, &table)) {
178 0 : return NS_OK;
179 : }
180 :
181 0 : RefPtr<SessionStorageCache> cache;
182 0 : if (!table->Get(originKey, getter_AddRefs(cache))) {
183 0 : return NS_OK;
184 : }
185 :
186 0 : RefPtr<Storage> storage = static_cast<Storage*>(aStorage);
187 0 : if (storage->Type() != Storage::eSessionStorage) {
188 0 : return NS_OK;
189 : }
190 :
191 : RefPtr<SessionStorage> sessionStorage =
192 0 : static_cast<SessionStorage*>(aStorage);
193 0 : if (sessionStorage->Cache() != cache) {
194 0 : return NS_OK;
195 : }
196 :
197 0 : if (!StorageUtils::PrincipalsEqual(storage->Principal(), aPrincipal)) {
198 0 : return NS_OK;
199 : }
200 :
201 0 : *aRetval = true;
202 0 : return NS_OK;
203 : }
204 :
205 : NS_IMETHODIMP
206 0 : SessionStorageManager::GetLocalStorageForPrincipal(nsIPrincipal* aPrincipal,
207 : const nsAString& aDocumentURI,
208 : bool aPrivate,
209 : nsIDOMStorage** aRetval)
210 : {
211 0 : return NS_ERROR_UNEXPECTED;
212 : }
213 :
214 : void
215 0 : SessionStorageManager::ClearStorages(ClearStorageType aType,
216 : const OriginAttributesPattern& aPattern,
217 : const nsACString& aOriginScope)
218 : {
219 0 : for (auto iter1 = mOATable.Iter(); !iter1.Done(); iter1.Next()) {
220 0 : OriginAttributes oa;
221 0 : DebugOnly<bool> ok = oa.PopulateFromSuffix(iter1.Key());
222 0 : MOZ_ASSERT(ok);
223 0 : if (!aPattern.Matches(oa)) {
224 : // This table doesn't match the given origin attributes pattern
225 0 : continue;
226 : }
227 :
228 0 : OriginKeyHashTable* table = iter1.Data();
229 0 : for (auto iter2 = table->Iter(); !iter2.Done(); iter2.Next()) {
230 0 : if (aOriginScope.IsEmpty() ||
231 0 : StringBeginsWith(iter2.Key(), aOriginScope)) {
232 0 : if (aType == eAll) {
233 0 : iter2.Data()->Clear(SessionStorageCache::eDefaultSetType, false);
234 0 : iter2.Data()->Clear(SessionStorageCache::eSessionSetType, false);
235 : } else {
236 0 : MOZ_ASSERT(aType == eSessionOnly);
237 0 : iter2.Data()->Clear(SessionStorageCache::eSessionSetType, false);
238 : }
239 : }
240 : }
241 : }
242 0 : }
243 :
244 : nsresult
245 0 : SessionStorageManager::Observe(const char* aTopic,
246 : const nsAString& aOriginAttributesPattern,
247 : const nsACString& aOriginScope)
248 : {
249 0 : OriginAttributesPattern pattern;
250 0 : if (!pattern.Init(aOriginAttributesPattern)) {
251 0 : NS_ERROR("Cannot parse origin attributes pattern");
252 0 : return NS_ERROR_FAILURE;
253 : }
254 :
255 : // Clear everything, caches + database
256 0 : if (!strcmp(aTopic, "cookie-cleared")) {
257 0 : ClearStorages(eAll, pattern, EmptyCString());
258 0 : return NS_OK;
259 : }
260 :
261 : // Clear from caches everything that has been stored
262 : // while in session-only mode
263 0 : if (!strcmp(aTopic, "session-only-cleared")) {
264 0 : ClearStorages(eSessionOnly, pattern, aOriginScope);
265 0 : return NS_OK;
266 : }
267 :
268 : // Clear everything (including so and pb data) from caches and database
269 : // for the gived domain and subdomains.
270 0 : if (!strcmp(aTopic, "domain-data-cleared")) {
271 0 : ClearStorages(eAll, pattern, aOriginScope);
272 0 : return NS_OK;
273 : }
274 :
275 0 : if (!strcmp(aTopic, "profile-change")) {
276 : // For case caches are still referenced - clear them completely
277 0 : ClearStorages(eAll, pattern, EmptyCString());
278 0 : mOATable.Clear();
279 0 : return NS_OK;
280 : }
281 :
282 0 : return NS_OK;
283 : }
284 :
285 : } // dom namespace
286 : } // mozilla namespace
|