Source code

Revision control

Other Tools

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 "LocalStorage.h"
8
#include "LocalStorageCache.h"
9
#include "LocalStorageManager.h"
10
#include "StorageUtils.h"
11
12
#include "nsIPrincipal.h"
13
14
#include "mozilla/dom/PermissionMessageUtils.h"
15
#include "mozilla/dom/StorageBinding.h"
16
#include "mozilla/dom/StorageEvent.h"
17
#include "mozilla/dom/StorageEventBinding.h"
18
#include "mozilla/ipc/BackgroundChild.h"
19
#include "mozilla/ipc/PBackgroundChild.h"
20
#include "mozilla/Preferences.h"
21
#include "mozilla/EnumSet.h"
22
#include "nsThreadUtils.h"
23
#include "nsContentUtils.h"
24
#include "nsServiceManagerUtils.h"
25
26
namespace mozilla {
27
28
using namespace ipc;
29
30
namespace dom {
31
32
NS_IMPL_CYCLE_COLLECTION_CLASS(LocalStorage)
33
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(LocalStorage, Storage)
34
NS_IMPL_CYCLE_COLLECTION_UNLINK(mManager)
35
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
36
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(LocalStorage, Storage)
37
CycleCollectionNoteChild(
38
cb, NS_ISUPPORTS_CAST(nsIDOMStorageManager*, tmp->mManager.get()),
39
"mManager");
40
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41
42
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStorage)
43
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
44
NS_INTERFACE_MAP_END_INHERITING(Storage)
45
46
NS_IMPL_ADDREF_INHERITED(LocalStorage, Storage)
47
NS_IMPL_RELEASE_INHERITED(LocalStorage, Storage)
48
49
LocalStorage::LocalStorage(nsPIDOMWindowInner* aWindow,
50
LocalStorageManager* aManager,
51
LocalStorageCache* aCache,
52
const nsAString& aDocumentURI,
53
nsIPrincipal* aPrincipal,
54
nsIPrincipal* aStoragePrincipal, bool aIsPrivate)
55
: Storage(aWindow, aPrincipal, aStoragePrincipal),
56
mManager(aManager),
57
mCache(aCache),
58
mDocumentURI(aDocumentURI),
59
mIsPrivate(aIsPrivate) {
60
mCache->Preload();
61
}
62
63
LocalStorage::~LocalStorage() {}
64
65
int64_t LocalStorage::GetOriginQuotaUsage() const {
66
return mCache->GetOriginQuotaUsage(this);
67
}
68
69
uint32_t LocalStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
70
ErrorResult& aRv) {
71
if (!CanUseStorage(aSubjectPrincipal)) {
72
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
73
return 0;
74
}
75
76
uint32_t length;
77
aRv = mCache->GetLength(this, &length);
78
return length;
79
}
80
81
void LocalStorage::Key(uint32_t aIndex, nsAString& aResult,
82
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
83
if (!CanUseStorage(aSubjectPrincipal)) {
84
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
85
return;
86
}
87
88
aRv = mCache->GetKey(this, aIndex, aResult);
89
}
90
91
void LocalStorage::GetItem(const nsAString& aKey, nsAString& aResult,
92
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
93
if (!CanUseStorage(aSubjectPrincipal)) {
94
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
95
return;
96
}
97
98
aRv = mCache->GetItem(this, aKey, aResult);
99
}
100
101
void LocalStorage::SetItem(const nsAString& aKey, const nsAString& aData,
102
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
103
if (!CanUseStorage(aSubjectPrincipal)) {
104
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
105
return;
106
}
107
108
nsString data;
109
bool ok = data.Assign(aData, fallible);
110
if (!ok) {
111
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
112
return;
113
}
114
115
nsString old;
116
aRv = mCache->SetItem(this, aKey, data, old);
117
if (aRv.Failed()) {
118
return;
119
}
120
121
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
122
OnChange(aKey, old, aData);
123
}
124
}
125
126
void LocalStorage::RemoveItem(const nsAString& aKey,
127
nsIPrincipal& aSubjectPrincipal,
128
ErrorResult& aRv) {
129
if (!CanUseStorage(aSubjectPrincipal)) {
130
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
131
return;
132
}
133
134
nsAutoString old;
135
aRv = mCache->RemoveItem(this, aKey, old);
136
if (aRv.Failed()) {
137
return;
138
}
139
140
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
141
OnChange(aKey, old, VoidString());
142
}
143
}
144
145
void LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
146
if (!CanUseStorage(aSubjectPrincipal)) {
147
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
148
return;
149
}
150
151
aRv = mCache->Clear(this);
152
if (NS_WARN_IF(aRv.Failed())) {
153
return;
154
}
155
156
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
157
OnChange(VoidString(), VoidString(), VoidString());
158
}
159
}
160
161
void LocalStorage::OnChange(const nsAString& aKey, const nsAString& aOldValue,
162
const nsAString& aNewValue) {
163
NotifyChange(/* aStorage */ this, StoragePrincipal(), aKey, aOldValue,
164
aNewValue, /* aStorageType */ u"localStorage", mDocumentURI,
165
mIsPrivate, /* aImmediateDispatch */ false);
166
}
167
168
void LocalStorage::ApplyEvent(StorageEvent* aStorageEvent) {
169
MOZ_ASSERT(aStorageEvent);
170
171
nsAutoString key;
172
nsAutoString old;
173
nsAutoString value;
174
175
aStorageEvent->GetKey(key);
176
aStorageEvent->GetNewValue(value);
177
178
// No key means clearing the full storage.
179
if (key.IsVoid()) {
180
MOZ_ASSERT(value.IsVoid());
181
mCache->Clear(this, LocalStorageCache::E10sPropagated);
182
return;
183
}
184
185
// No new value means removing the key.
186
if (value.IsVoid()) {
187
mCache->RemoveItem(this, key, old, LocalStorageCache::E10sPropagated);
188
return;
189
}
190
191
// Otherwise, we set the new value.
192
mCache->SetItem(this, key, value, old, LocalStorageCache::E10sPropagated);
193
}
194
195
void LocalStorage::GetSupportedNames(nsTArray<nsString>& aKeys) {
196
if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
197
// return just an empty array
198
aKeys.Clear();
199
return;
200
}
201
202
mCache->GetKeys(this, aKeys);
203
}
204
205
bool LocalStorage::IsForkOf(const Storage* aOther) const {
206
MOZ_ASSERT(aOther);
207
if (aOther->Type() != eLocalStorage) {
208
return false;
209
}
210
211
return mCache == static_cast<const LocalStorage*>(aOther)->mCache;
212
}
213
214
} // namespace dom
215
} // namespace mozilla