https://github.com/mozilla/gecko-dev
Raw File
Tip revision: 6787a82def57b8e2ec25dc0300231d97bc5ea593 authored by Jeff Walden on 19 November 2019, 04:55:39 UTC
Bug 1596544 - intl_ValidateAndCanonicalizeUnicodeExtensionType should ignore the second |option| argument until it's needed to report an error. r=anba
Tip revision: 6787a82
nsCacheEntryDescriptor.h
/* -*- 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_
back to top