summaryrefslogtreecommitdiffstats
path: root/netwerk/cache/nsCacheEntryDescriptor.h
blob: 2274150cff6d66b3fb5dff355e2818320a535519 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * 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 _nsCacheEntryDescriptor_h_
#define _nsCacheEntryDescriptor_h_

#include "nsICacheEntryDescriptor.h"
#include "nsCacheEntry.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsCacheService.h"
#include "zlib.h"
#include "mozilla/Mutex.h"

/******************************************************************************
 * nsCacheEntryDescriptor
 *******************************************************************************/
class nsCacheEntryDescriptor final : public PRCList,
                                     public nsICacheEntryDescriptor {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSICACHEENTRYDESCRIPTOR
  NS_DECL_NSICACHEENTRYINFO

  friend class nsAsyncDoomEvent;
  friend class nsCacheService;

  nsCacheEntryDescriptor(nsCacheEntry* entry, nsCacheAccessMode mode);

  /**
   * utility method to attempt changing data size of associated entry
   */
  nsresult RequestDataSizeChange(int32_t deltaSize);

  /**
   * methods callbacks for nsCacheService
   */
  nsCacheEntry* CacheEntry(void) { return mCacheEntry; }
  bool ClearCacheEntry(void) {
    NS_ASSERTION(mInputWrappers.IsEmpty(), "Bad state");
    NS_ASSERTION(!mOutputWrapper, "Bad state");

    bool doomEntry = false;
    bool asyncDoomPending;
    {
      mozilla::MutexAutoLock lock(mLock);
      asyncDoomPending = mAsyncDoomPending;
    }

    if (asyncDoomPending && mCacheEntry) {
      doomEntry = true;
      mDoomedOnClose = true;
    }
    mCacheEntry = nullptr;

    return doomEntry;
  }

 private:
  virtual ~nsCacheEntryDescriptor();

  /*************************************************************************
   * input stream wrapper class -
   *
   * The input stream wrapper references the descriptor, but the descriptor
   * doesn't need any references to the stream wrapper.
   *************************************************************************/
  class nsInputStreamWrapper : public nsIInputStream {
    friend class nsCacheEntryDescriptor;

   private:
    nsCacheEntryDescriptor* mDescriptor;
    nsCOMPtr<nsIInputStream> mInput;
    uint32_t mStartOffset;
    bool mInitialized;
    mozilla::Mutex mLock;

   public:
    NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSIINPUTSTREAM

    nsInputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off)
        : mDescriptor(desc),
          mStartOffset(off),
          mInitialized(false),
          mLock("nsInputStreamWrapper.mLock") {
      NS_ADDREF(mDescriptor);
    }

   private:
    virtual ~nsInputStreamWrapper() { NS_IF_RELEASE(mDescriptor); }

    nsresult LazyInit();
    nsresult EnsureInit();
    nsresult Read_Locked(char* buf, uint32_t count, uint32_t* countRead);
    nsresult Close_Locked();
    void CloseInternal();
  };

  class nsDecompressInputStreamWrapper : public nsInputStreamWrapper {
   private:
    unsigned char* mReadBuffer;
    uint32_t mReadBufferLen;
    z_stream mZstream;
    bool mStreamInitialized;
    bool mStreamEnded;

   public:
    NS_DECL_ISUPPORTS_INHERITED

    nsDecompressInputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off)
        : nsInputStreamWrapper(desc, off),
          mReadBuffer(nullptr),
          mReadBufferLen(0),
          mZstream{},
          mStreamInitialized(false),
          mStreamEnded(false) {}
    NS_IMETHOD Read(char* buf, uint32_t count, uint32_t* result) override;
    NS_IMETHOD Close() override;

   private:
    virtual ~nsDecompressInputStreamWrapper() { Close(); }
    nsresult InitZstream();
    nsresult EndZstream();
  };

  /*************************************************************************
   * output stream wrapper class -
   *
   * The output stream wrapper references the descriptor, but the descriptor
   * doesn't need any references to the stream wrapper.
   *************************************************************************/
  class nsOutputStreamWrapper : public nsIOutputStream {
    friend class nsCacheEntryDescriptor;

   protected:
    nsCacheEntryDescriptor* mDescriptor;
    nsCOMPtr<nsIOutputStream> mOutput;
    uint32_t mStartOffset;
    bool mInitialized;
    mozilla::Mutex mLock;

   public:
    NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSIOUTPUTSTREAM

    nsOutputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off)
        : mDescriptor(desc),
          mStartOffset(off),
          mInitialized(false),
          mLock("nsOutputStreamWrapper.mLock") {
      NS_ADDREF(mDescriptor);  // owning ref
    }

   private:
    virtual ~nsOutputStreamWrapper() {
      Close();

      NS_ASSERTION(!mOutput, "Bad state");
      NS_ASSERTION(!mDescriptor, "Bad state");
    }

    nsresult LazyInit();
    nsresult EnsureInit();
    nsresult OnWrite(uint32_t count);
    nsresult Write_Locked(const char* buf, uint32_t count, uint32_t* result);
    nsresult Close_Locked();
    void CloseInternal();
  };

  class nsCompressOutputStreamWrapper : public nsOutputStreamWrapper {
   private:
    unsigned char* mWriteBuffer;
    uint32_t mWriteBufferLen;
    z_stream mZstream;
    bool mStreamInitialized;
    bool mStreamEnded;
    uint32_t mUncompressedCount;

   public:
    NS_DECL_ISUPPORTS_INHERITED

    nsCompressOutputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off)
        : nsOutputStreamWrapper(desc, off),
          mWriteBuffer(nullptr),
          mWriteBufferLen(0),
          mZstream{},
          mStreamInitialized(false),
          mStreamEnded(false),
          mUncompressedCount(0) {}
    NS_IMETHOD Write(const char* buf, uint32_t count,
                     uint32_t* result) override;
    NS_IMETHOD Close() override;

   private:
    virtual ~nsCompressOutputStreamWrapper() { Close(); }
    nsresult InitZstream();
    nsresult WriteBuffer();
  };

 private:
  /**
   * nsCacheEntryDescriptor data members
   */

  nsCOMPtr<nsICacheServiceInternal> mCacheService;
  nsCacheEntry* mCacheEntry;  // we are a child of the entry
  nsCacheAccessMode mAccessGranted;
  nsTArray<nsInputStreamWrapper*> mInputWrappers;
  nsOutputStreamWrapper* mOutputWrapper;
  mozilla::Mutex mLock;
  bool mAsyncDoomPending;
  bool mDoomedOnClose;
  bool mClosingDescriptor;
};

#endif  // _nsCacheEntryDescriptor_h_