summaryrefslogtreecommitdiffstats
path: root/dom/file/MutableBlobStorage.h
blob: aa0d42c75ecd21e5a1ca6b1bbfee9f8bd69fd176 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_MutableBlobStorage_h
#define mozilla_dom_MutableBlobStorage_h

#include "mozilla/RefPtr.h"
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "prio.h"

class nsIEventTarget;
class nsIRunnable;

namespace mozilla {

class TaskQueue;

namespace dom {

class Blob;
class BlobImpl;
class MutableBlobStorage;
class TemporaryIPCBlobChild;
class TemporaryIPCBlobChildCallback;

class MutableBlobStorageCallback {
 public:
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING

  virtual void BlobStoreCompleted(MutableBlobStorage* aBlobStorage,
                                  BlobImpl* aBlob, nsresult aRv) = 0;
};

// This class is must be created and used on main-thread, except for Append()
// that can be called on any thread.
class MutableBlobStorage final {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MutableBlobStorage)

  enum MutableBlobStorageType {
    eOnlyInMemory,
    eCouldBeInTemporaryFile,
  };

  explicit MutableBlobStorage(MutableBlobStorageType aType,
                              nsIEventTarget* aEventTarget = nullptr,
                              uint32_t aMaxMemory = 0);

  nsresult Append(const void* aData, uint32_t aLength);

  // This method can be called just once.
  // The callback will be called when the BlobImpl is ready.
  void GetBlobImplWhenReady(const nsACString& aContentType,
                            MutableBlobStorageCallback* aCallback);

  void TemporaryFileCreated(PRFileDesc* aFD);

  void AskForBlob(TemporaryIPCBlobChildCallback* aCallback,
                  const nsACString& aContentType);

  void ErrorPropagated(nsresult aRv);

  nsIEventTarget* EventTarget() {
    MOZ_ASSERT(mEventTarget);
    return mEventTarget;
  }

  // Returns the heap size in bytes of our internal buffers.
  // Note that this intentionally ignores the data in the temp file.
  size_t SizeOfCurrentMemoryBuffer();

  PRFileDesc* GetFD();

  void CloseFD();

 private:
  ~MutableBlobStorage();

  bool ExpandBufferSize(const MutexAutoLock& aProofOfLock, uint64_t aSize);

  bool ShouldBeTemporaryStorage(const MutexAutoLock& aProofOfLock,
                                uint64_t aSize) const;

  bool MaybeCreateTemporaryFile(const MutexAutoLock& aProofOfLock);
  void MaybeCreateTemporaryFileOnMainThread(const MutexAutoLock& aProofOfLock);

  [[nodiscard]] nsresult DispatchToIOThread(
      already_AddRefed<nsIRunnable> aRunnable);

  Mutex mMutex MOZ_UNANNOTATED;

  // All these variables are touched on the main thread only or in the
  // retargeted thread when used by Append(). They are protected by mMutex.

  void* mData;
  uint64_t mDataLen;
  uint64_t mDataBufferLen;

  enum StorageState {
    eKeepInMemory,
    eInMemory,
    eWaitingForTemporaryFile,
    eInTemporaryFile,
    eClosed
  };

  StorageState mStorageState;

  PRFileDesc* mFD;

  nsresult mErrorResult;

  RefPtr<TaskQueue> mTaskQueue;
  nsCOMPtr<nsIEventTarget> mEventTarget;

  nsCString mPendingContentType;
  RefPtr<MutableBlobStorageCallback> mPendingCallback;

  RefPtr<TemporaryIPCBlobChild> mActor;

  // This value is used when we go from eInMemory to eWaitingForTemporaryFile
  // and eventually eInTemporaryFile. If the size of the buffer is >=
  // mMaxMemory, the creation of the temporary file will start.
  // It's not used if mStorageState is eKeepInMemory.
  uint32_t mMaxMemory;
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_MutableBlobStorage_h