Coverage Report

Created: 2018-09-25 14:53

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