Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/file/MemoryBlobImpl.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_MemoryBlobImpl_h
8
#define mozilla_dom_MemoryBlobImpl_h
9
10
#include "mozilla/dom/BaseBlobImpl.h"
11
#include "mozilla/LinkedList.h"
12
#include "mozilla/StaticMutex.h"
13
#include "mozilla/StaticPtr.h"
14
#include "nsICloneableInputStream.h"
15
#include "nsIInputStream.h"
16
#include "nsIIPCSerializableInputStream.h"
17
#include "nsIMemoryReporter.h"
18
#include "nsISeekableStream.h"
19
20
namespace mozilla {
21
namespace dom {
22
23
class MemoryBlobImpl final : public BaseBlobImpl
24
{
25
public:
26
  NS_INLINE_DECL_REFCOUNTING_INHERITED(MemoryBlobImpl, BaseBlobImpl)
27
28
  MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
29
                 const nsAString& aContentType, int64_t aLastModifiedDate)
30
    : BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate)
31
    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
32
0
  {
33
0
    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
34
0
  }
35
36
  MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength,
37
                 const nsAString& aContentType)
38
    : BaseBlobImpl(aContentType, aLength)
39
    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
40
0
  {
41
0
    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
42
0
  }
43
44
  virtual void CreateInputStream(nsIInputStream** aStream,
45
                                 ErrorResult& aRv) override;
46
47
  virtual already_AddRefed<BlobImpl>
48
  CreateSlice(uint64_t aStart, uint64_t aLength,
49
              const nsAString& aContentType, ErrorResult& aRv) override;
50
51
  virtual bool IsMemoryFile() const override
52
0
  {
53
0
    return true;
54
0
  }
55
56
  size_t GetAllocationSize() const override
57
0
  {
58
0
    return mLength;
59
0
  }
60
61
  size_t GetAllocationSize(FallibleTArray<BlobImpl*>& aVisitedBlobImpls) const override
62
0
  {
63
0
    return GetAllocationSize();
64
0
  }
65
66
  class DataOwner final : public mozilla::LinkedListElement<DataOwner>
67
  {
68
  public:
69
    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
70
    DataOwner(void* aMemoryBuffer, uint64_t aLength)
71
      : mData(aMemoryBuffer)
72
      , mLength(aLength)
73
0
    {
74
0
      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
75
0
76
0
      if (!sDataOwners) {
77
0
        sDataOwners = new mozilla::LinkedList<DataOwner>();
78
0
        EnsureMemoryReporterRegistered();
79
0
      }
80
0
      sDataOwners->insertBack(this);
81
0
    }
82
83
  private:
84
    // Private destructor, to discourage deletion outside of Release():
85
0
    ~DataOwner() {
86
0
      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
87
0
88
0
      remove();
89
0
      if (sDataOwners->isEmpty()) {
90
0
        // Free the linked list if it's empty.
91
0
        sDataOwners = nullptr;
92
0
      }
93
0
94
0
      free(mData);
95
0
    }
96
97
  public:
98
    static void EnsureMemoryReporterRegistered();
99
100
    // sDataOwners and sMemoryReporterRegistered may only be accessed while
101
    // holding sDataOwnerMutex!  You also must hold the mutex while touching
102
    // elements of the linked list that DataOwner inherits from.
103
    static mozilla::StaticMutex sDataOwnerMutex;
104
    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
105
    static bool sMemoryReporterRegistered;
106
107
    void* mData;
108
    uint64_t mLength;
109
  };
110
111
  class DataOwnerAdapter final : public nsIInputStream
112
                               , public nsISeekableStream
113
                               , public nsIIPCSerializableInputStream
114
                               , public nsICloneableInputStream
115
  {
116
    typedef MemoryBlobImpl::DataOwner DataOwner;
117
  public:
118
    static nsresult Create(DataOwner* aDataOwner,
119
                           uint32_t aStart,
120
                           uint32_t aLength,
121
                           nsIInputStream** _retval);
122
123
    NS_DECL_THREADSAFE_ISUPPORTS
124
125
    // These are mandatory.
126
    NS_FORWARD_NSIINPUTSTREAM(mStream->)
127
    NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
128
    NS_FORWARD_NSICLONEABLEINPUTSTREAM(mCloneableInputStream->)
129
130
    // This is optional. We use a conditional QI to keep it from being called
131
    // if the underlying stream doesn't support it.
132
    NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
133
134
  private:
135
0
    ~DataOwnerAdapter() {}
136
137
    DataOwnerAdapter(DataOwner* aDataOwner,
138
                     nsIInputStream* aStream)
139
      : mDataOwner(aDataOwner)
140
      , mStream(aStream)
141
      , mSeekableStream(do_QueryInterface(aStream))
142
      , mSerializableInputStream(do_QueryInterface(aStream))
143
      , mCloneableInputStream(do_QueryInterface(aStream))
144
0
    {
145
0
      MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
146
0
    }
147
148
    RefPtr<DataOwner> mDataOwner;
149
    nsCOMPtr<nsIInputStream> mStream;
150
    nsCOMPtr<nsISeekableStream> mSeekableStream;
151
    nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
152
    nsCOMPtr<nsICloneableInputStream> mCloneableInputStream;
153
  };
154
155
private:
156
  // Create slice
157
  MemoryBlobImpl(const MemoryBlobImpl* aOther, uint64_t aStart,
158
                 uint64_t aLength, const nsAString& aContentType)
159
    : BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength)
160
    , mDataOwner(aOther->mDataOwner)
161
0
  {
162
0
    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
163
0
    mImmutable = aOther->mImmutable;
164
0
  }
165
166
0
  ~MemoryBlobImpl() {}
167
168
  // Used when backed by a memory store
169
  RefPtr<DataOwner> mDataOwner;
170
};
171
172
} // namespace dom
173
} // namespace mozilla
174
175
#endif // mozilla_dom_MemoryBlobImpl_h