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
#ifndef mozilla_dom_StorageIPC_h
8
#define mozilla_dom_StorageIPC_h
9
10
#include "mozilla/dom/PBackgroundLocalStorageCacheChild.h"
11
#include "mozilla/dom/PBackgroundLocalStorageCacheParent.h"
12
#include "mozilla/dom/PBackgroundStorageChild.h"
13
#include "mozilla/dom/PBackgroundStorageParent.h"
14
#include "mozilla/dom/PSessionStorageObserverChild.h"
15
#include "mozilla/dom/PSessionStorageObserverParent.h"
16
#include "StorageDBThread.h"
17
#include "LocalStorageCache.h"
18
#include "StorageObserver.h"
19
#include "mozilla/Mutex.h"
20
#include "nsAutoPtr.h"
21
22
namespace mozilla {
23
24
class OriginAttributesPattern;
25
26
namespace ipc {
27
28
class BackgroundChildImpl;
29
class PrincipalInfo;
30
31
} // namespace ipc
32
33
namespace dom {
34
35
class LocalStorageManager;
36
class PBackgroundStorageParent;
37
class PSessionStorageObserverParent;
38
class SessionStorageObserver;
39
40
class LocalStorageCacheChild final : public PBackgroundLocalStorageCacheChild {
41
friend class mozilla::ipc::BackgroundChildImpl;
42
friend class LocalStorageCache;
43
friend class LocalStorageManager;
44
45
// LocalStorageCache effectively owns this instance, although IPC handles its
46
// allocation/deallocation. When the LocalStorageCache destructor runs, it
47
// will invoke SendDeleteMeInternal() which will trigger both instances to
48
// drop their mutual references and cause IPC to destroy the actor after the
49
// DeleteMe round-trip.
50
LocalStorageCache* MOZ_NON_OWNING_REF mCache;
51
52
NS_DECL_OWNINGTHREAD
53
54
public:
55
void AssertIsOnOwningThread() const {
56
NS_ASSERT_OWNINGTHREAD(LocalStorageCacheChild);
57
}
58
59
private:
60
// Only created by LocalStorageManager.
61
explicit LocalStorageCacheChild(LocalStorageCache* aCache);
62
63
// Only destroyed by mozilla::ipc::BackgroundChildImpl.
64
~LocalStorageCacheChild();
65
66
// Only called by LocalStorageCache.
67
void SendDeleteMeInternal();
68
69
// IPDL methods are only called by IPDL.
70
void ActorDestroy(ActorDestroyReason aWhy) override;
71
72
mozilla::ipc::IPCResult RecvObserve(const PrincipalInfo& aPrincipalInfo,
73
const PrincipalInfo& aCachePrincipalInfo,
74
const uint32_t& aPrivateBrowsingId,
75
const nsString& aDocumentURI,
76
const nsString& aKey,
77
const nsString& aOldValue,
78
const nsString& aNewValue) override;
79
};
80
81
// Child side of the IPC protocol, exposes as DB interface but
82
// is responsible to send all requests to the parent process
83
// and expects asynchronous answers. Those are then transparently
84
// forwarded back to consumers on the child process.
85
class StorageDBChild final : public PBackgroundStorageChild {
86
class ShutdownObserver;
87
88
virtual ~StorageDBChild();
89
90
public:
91
explicit StorageDBChild(LocalStorageManager* aManager);
92
93
static StorageDBChild* Get();
94
95
static StorageDBChild* GetOrCreate();
96
97
NS_INLINE_DECL_REFCOUNTING(StorageDBChild);
98
99
void AddIPDLReference();
100
void ReleaseIPDLReference();
101
102
virtual nsresult Init();
103
virtual nsresult Shutdown();
104
105
virtual void AsyncPreload(LocalStorageCacheBridge* aCache,
106
bool aPriority = false);
107
virtual void AsyncGetUsage(StorageUsageBridge* aUsage);
108
109
virtual void SyncPreload(LocalStorageCacheBridge* aCache,
110
bool aForceSync = false);
111
112
virtual nsresult AsyncAddItem(LocalStorageCacheBridge* aCache,
113
const nsAString& aKey, const nsAString& aValue);
114
virtual nsresult AsyncUpdateItem(LocalStorageCacheBridge* aCache,
115
const nsAString& aKey,
116
const nsAString& aValue);
117
virtual nsresult AsyncRemoveItem(LocalStorageCacheBridge* aCache,
118
const nsAString& aKey);
119
virtual nsresult AsyncClear(LocalStorageCacheBridge* aCache);
120
121
virtual void AsyncClearAll() {
122
if (mOriginsHavingData) {
123
mOriginsHavingData->Clear(); /* NO-OP on the child process otherwise */
124
}
125
}
126
127
virtual void AsyncClearMatchingOrigin(const nsACString& aOriginNoSuffix) {
128
MOZ_CRASH("Shouldn't be called!");
129
}
130
131
virtual void AsyncClearMatchingOriginAttributes(
132
const OriginAttributesPattern& aPattern) {
133
MOZ_CRASH("Shouldn't be called!");
134
}
135
136
virtual void AsyncFlush() { MOZ_CRASH("Shouldn't be called!"); }
137
138
virtual bool ShouldPreloadOrigin(const nsACString& aOriginNoSuffix);
139
140
private:
141
mozilla::ipc::IPCResult RecvObserve(const nsCString& aTopic,
142
const nsString& aOriginAttributesPattern,
143
const nsCString& aOriginScope) override;
144
mozilla::ipc::IPCResult RecvLoadItem(const nsCString& aOriginSuffix,
145
const nsCString& aOriginNoSuffix,
146
const nsString& aKey,
147
const nsString& aValue) override;
148
mozilla::ipc::IPCResult RecvLoadDone(const nsCString& aOriginSuffix,
149
const nsCString& aOriginNoSuffix,
150
const nsresult& aRv) override;
151
mozilla::ipc::IPCResult RecvOriginsHavingData(
152
nsTArray<nsCString>&& aOrigins) override;
153
mozilla::ipc::IPCResult RecvLoadUsage(const nsCString& aOriginNoSuffix,
154
const int64_t& aUsage) override;
155
mozilla::ipc::IPCResult RecvError(const nsresult& aRv) override;
156
157
nsTHashtable<nsCStringHashKey>& OriginsHavingData();
158
159
// Held to get caches to forward answers to.
160
RefPtr<LocalStorageManager> mManager;
161
162
// Origins having data hash, for optimization purposes only
163
nsAutoPtr<nsTHashtable<nsCStringHashKey>> mOriginsHavingData;
164
165
// List of caches waiting for preload. This ensures the contract that
166
// AsyncPreload call references the cache for time of the preload.
167
nsTHashtable<nsRefPtrHashKey<LocalStorageCacheBridge>> mLoadingCaches;
168
169
// Status of the remote database
170
nsresult mStatus;
171
172
bool mIPCOpen;
173
};
174
175
class SessionStorageObserverChild final : public PSessionStorageObserverChild {
176
friend class SessionStorageManager;
177
friend class SessionStorageObserver;
178
179
// SessionStorageObserver effectively owns this instance, although IPC handles
180
// its allocation/deallocation. When the SessionStorageObserver destructor
181
// runs, it will invoke SendDeleteMeInternal() which will trigger both
182
// instances to drop their mutual references and cause IPC to destroy the
183
// actor after the DeleteMe round-trip.
184
SessionStorageObserver* MOZ_NON_OWNING_REF mObserver;
185
186
NS_DECL_OWNINGTHREAD
187
188
public:
189
void AssertIsOnOwningThread() const {
190
NS_ASSERT_OWNINGTHREAD(LocalStorageCacheChild);
191
}
192
193
private:
194
// Only created by SessionStorageManager.
195
explicit SessionStorageObserverChild(SessionStorageObserver* aObserver);
196
197
~SessionStorageObserverChild();
198
199
// Only called by SessionStorageObserver.
200
void SendDeleteMeInternal();
201
202
// IPDL methods are only called by IPDL.
203
void ActorDestroy(ActorDestroyReason aWhy) override;
204
205
mozilla::ipc::IPCResult RecvObserve(const nsCString& aTopic,
206
const nsString& aOriginAttributesPattern,
207
const nsCString& aOriginScope) override;
208
};
209
210
class LocalStorageCacheParent final
211
: public PBackgroundLocalStorageCacheParent {
212
const PrincipalInfo mPrincipalInfo;
213
const nsCString mOriginKey;
214
uint32_t mPrivateBrowsingId;
215
bool mActorDestroyed;
216
217
public:
218
// Created in AllocPBackgroundLocalStorageCacheParent.
219
LocalStorageCacheParent(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
220
const nsACString& aOriginKey,
221
uint32_t aPrivateBrowsingId);
222
223
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::LocalStorageCacheParent)
224
225
const PrincipalInfo& PrincipalInfo() const { return mPrincipalInfo; }
226
227
private:
228
// Reference counted.
229
~LocalStorageCacheParent();
230
231
// IPDL methods are only called by IPDL.
232
void ActorDestroy(ActorDestroyReason aWhy) override;
233
234
mozilla::ipc::IPCResult RecvDeleteMe() override;
235
236
mozilla::ipc::IPCResult RecvNotify(const nsString& aDocumentURI,
237
const nsString& aKey,
238
const nsString& aOldValue,
239
const nsString& aNewValue) override;
240
};
241
242
// Receives async requests from child processes and is responsible
243
// to send back responses from the DB thread. Exposes as a fake
244
// LocalStorageCache consumer.
245
// Also responsible for forwardning all chrome operation notifications
246
// such as cookie cleaning etc to the child process.
247
class StorageDBParent final : public PBackgroundStorageParent {
248
class ObserverSink;
249
250
virtual ~StorageDBParent();
251
252
public:
253
explicit StorageDBParent(const nsString& aProfilePath);
254
255
void Init();
256
257
NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
258
NS_IMETHOD_(MozExternalRefCountType) Release(void);
259
260
void AddIPDLReference();
261
void ReleaseIPDLReference();
262
263
bool IPCOpen() { return mIPCOpen; }
264
265
public:
266
// Fake cache class receiving async callbacks from DB thread, sending
267
// them back to appropriate cache object on the child process.
268
class CacheParentBridge : public LocalStorageCacheBridge {
269
public:
270
CacheParentBridge(StorageDBParent* aParentDB,
271
const nsACString& aOriginSuffix,
272
const nsACString& aOriginNoSuffix)
273
: mOwningEventTarget(GetCurrentThreadSerialEventTarget()),
274
mParent(aParentDB),
275
mOriginSuffix(aOriginSuffix),
276
mOriginNoSuffix(aOriginNoSuffix),
277
mLoaded(false),
278
mLoadedCount(0) {}
279
virtual ~CacheParentBridge() {}
280
281
// LocalStorageCacheBridge
282
virtual const nsCString Origin() const override;
283
virtual const nsCString& OriginNoSuffix() const override {
284
return mOriginNoSuffix;
285
}
286
virtual const nsCString& OriginSuffix() const override {
287
return mOriginSuffix;
288
}
289
virtual bool Loaded() override { return mLoaded; }
290
virtual uint32_t LoadedCount() override { return mLoadedCount; }
291
292
virtual bool LoadItem(const nsAString& aKey,
293
const nsString& aValue) override;
294
virtual void LoadDone(nsresult aRv) override;
295
virtual void LoadWait() override;
296
297
NS_IMETHOD_(void)
298
Release(void) override;
299
300
private:
301
void Destroy();
302
303
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
304
RefPtr<StorageDBParent> mParent;
305
nsCString mOriginSuffix, mOriginNoSuffix;
306
bool mLoaded;
307
uint32_t mLoadedCount;
308
};
309
310
// Fake usage class receiving async callbacks from DB thread
311
class UsageParentBridge : public StorageUsageBridge {
312
public:
313
UsageParentBridge(StorageDBParent* aParentDB,
314
const nsACString& aOriginScope)
315
: mOwningEventTarget(GetCurrentThreadSerialEventTarget()),
316
mParent(aParentDB),
317
mOriginScope(aOriginScope) {}
318
virtual ~UsageParentBridge() {}
319
320
// StorageUsageBridge
321
virtual const nsCString& OriginScope() override { return mOriginScope; }
322
virtual void LoadUsage(const int64_t usage) override;
323
324
NS_IMETHOD_(MozExternalRefCountType)
325
Release(void) override;
326
327
private:
328
void Destroy();
329
330
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
331
RefPtr<StorageDBParent> mParent;
332
nsCString mOriginScope;
333
};
334
335
private:
336
// IPC
337
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
338
mozilla::ipc::IPCResult RecvDeleteMe() override;
339
340
mozilla::ipc::IPCResult RecvAsyncPreload(const nsCString& aOriginSuffix,
341
const nsCString& aOriginNoSuffix,
342
const bool& aPriority) override;
343
mozilla::ipc::IPCResult RecvPreload(const nsCString& aOriginSuffix,
344
const nsCString& aOriginNoSuffix,
345
const uint32_t& aAlreadyLoadedCount,
346
nsTArray<nsString>* aKeys,
347
nsTArray<nsString>* aValues,
348
nsresult* aRv) override;
349
mozilla::ipc::IPCResult RecvAsyncGetUsage(
350
const nsCString& aOriginNoSuffix) override;
351
mozilla::ipc::IPCResult RecvAsyncAddItem(const nsCString& aOriginSuffix,
352
const nsCString& aOriginNoSuffix,
353
const nsString& aKey,
354
const nsString& aValue) override;
355
mozilla::ipc::IPCResult RecvAsyncUpdateItem(const nsCString& aOriginSuffix,
356
const nsCString& aOriginNoSuffix,
357
const nsString& aKey,
358
const nsString& aValue) override;
359
mozilla::ipc::IPCResult RecvAsyncRemoveItem(const nsCString& aOriginSuffix,
360
const nsCString& aOriginNoSuffix,
361
const nsString& aKey) override;
362
mozilla::ipc::IPCResult RecvAsyncClear(
363
const nsCString& aOriginSuffix,
364
const nsCString& aOriginNoSuffix) override;
365
mozilla::ipc::IPCResult RecvAsyncFlush() override;
366
367
mozilla::ipc::IPCResult RecvStartup() override;
368
mozilla::ipc::IPCResult RecvClearAll() override;
369
mozilla::ipc::IPCResult RecvClearMatchingOrigin(
370
const nsCString& aOriginNoSuffix) override;
371
mozilla::ipc::IPCResult RecvClearMatchingOriginAttributes(
372
const OriginAttributesPattern& aPattern) override;
373
374
void Observe(const nsCString& aTopic, const nsString& aOriginAttrPattern,
375
const nsCString& aOriginScope);
376
377
private:
378
CacheParentBridge* NewCache(const nsACString& aOriginSuffix,
379
const nsACString& aOriginNoSuffix);
380
381
RefPtr<ObserverSink> mObserverSink;
382
383
// A hack to deal with deadlock between the parent process main thread and
384
// background thread when invoking StorageDBThread::GetOrCreate because it
385
// cannot safely perform a synchronous dispatch back to the main thread
386
// (because we are already synchronously doing things on the stack).
387
// Populated for the same process actors, empty for other process actors.
388
nsString mProfilePath;
389
390
ThreadSafeAutoRefCnt mRefCnt;
391
NS_DECL_OWNINGTHREAD
392
393
// True when IPC channel is open and Send*() methods are OK to use.
394
bool mIPCOpen;
395
};
396
397
class SessionStorageObserverParent final : public PSessionStorageObserverParent,
398
public StorageObserverSink {
399
bool mActorDestroyed;
400
401
public:
402
// Created in AllocPSessionStorageObserverParent.
403
SessionStorageObserverParent();
404
405
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::SessionStorageObserverParent)
406
407
private:
408
// Reference counted.
409
~SessionStorageObserverParent();
410
411
// IPDL methods are only called by IPDL.
412
void ActorDestroy(ActorDestroyReason aWhy) override;
413
414
mozilla::ipc::IPCResult RecvDeleteMe() override;
415
416
// StorageObserverSink
417
nsresult Observe(const char* aTopic, const nsAString& aOriginAttrPattern,
418
const nsACString& aOriginScope) override;
419
};
420
421
PBackgroundLocalStorageCacheParent* AllocPBackgroundLocalStorageCacheParent(
422
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
423
const nsCString& aOriginKey, const uint32_t& aPrivateBrowsingId);
424
425
mozilla::ipc::IPCResult RecvPBackgroundLocalStorageCacheConstructor(
426
mozilla::ipc::PBackgroundParent* aBackgroundActor,
427
PBackgroundLocalStorageCacheParent* aActor,
428
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
429
const nsCString& aOriginKey, const uint32_t& aPrivateBrowsingId);
430
431
bool DeallocPBackgroundLocalStorageCacheParent(
432
PBackgroundLocalStorageCacheParent* aActor);
433
434
PBackgroundStorageParent* AllocPBackgroundStorageParent(
435
const nsString& aProfilePath);
436
437
mozilla::ipc::IPCResult RecvPBackgroundStorageConstructor(
438
PBackgroundStorageParent* aActor, const nsString& aProfilePath);
439
440
bool DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor);
441
442
PSessionStorageObserverParent* AllocPSessionStorageObserverParent();
443
444
bool RecvPSessionStorageObserverConstructor(
445
PSessionStorageObserverParent* aActor);
446
447
bool DeallocPSessionStorageObserverParent(
448
PSessionStorageObserverParent* aActor);
449
450
} // namespace dom
451
} // namespace mozilla
452
453
#endif // mozilla_dom_StorageIPC_h