Coverage Report

Created: 2018-09-25 14:53

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