DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (25c4c2685699)

VCS Links

Line Code
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
/* -*- Mode: C++; tab-width: 2; 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 SimpleChannel_h
#define SimpleChannel_h

#include "mozilla/ResultExtensions.h"
#include "mozilla/UniquePtr.h"
#include "nsBaseChannel.h"
#include "nsIChildChannel.h"
#include "mozilla/net/PSimpleChannelChild.h"
#include "nsCOMPtr.h"

class nsIChannel;
class nsIInputStream;
class nsILoadInfo;
class nsIRequest;
class nsIStreamListener;
class nsIURI;

//-----------------------------------------------------------------------------

namespace mozilla {

using InputStreamOrReason = Result<nsCOMPtr<nsIInputStream>, nsresult>;
using RequestOrReason = Result<nsCOMPtr<nsIRequest>, nsresult>;

namespace net {

class SimpleChannelCallbacks {
 public:
  virtual InputStreamOrReason OpenContentStream(bool async,
                                                nsIChannel* channel) = 0;

  virtual RequestOrReason StartAsyncRead(nsIStreamListener* stream,
                                         nsIChannel* channel) = 0;

  virtual ~SimpleChannelCallbacks() = default;
};

template <typename F1, typename F2, typename T>
class SimpleChannelCallbacksImpl final : public SimpleChannelCallbacks {
 public:
  SimpleChannelCallbacksImpl(F1&& aStartAsyncRead, F2&& aOpenContentStream,
                             T* context)
      : mStartAsyncRead(aStartAsyncRead),
        mOpenContentStream(aOpenContentStream),
        mContext(context) {}

  virtual ~SimpleChannelCallbacksImpl() = default;

  virtual InputStreamOrReason OpenContentStream(bool async,
                                                nsIChannel* channel) override {
    return mOpenContentStream(async, channel, mContext);
  }

  virtual RequestOrReason StartAsyncRead(nsIStreamListener* listener,
                                         nsIChannel* channel) override {
    return mStartAsyncRead(listener, channel, mContext);
  }

 private:
  F1 mStartAsyncRead;
  F2 mOpenContentStream;
  RefPtr<T> mContext;
};

class SimpleChannel : public nsBaseChannel {
 public:
  explicit SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);

 protected:
  virtual ~SimpleChannel() = default;

  virtual nsresult OpenContentStream(bool async, nsIInputStream** streamOut,
                                     nsIChannel** channel) override;

  virtual nsresult BeginAsyncRead(nsIStreamListener* listener,
                                  nsIRequest** request) override;

 private:
  UniquePtr<SimpleChannelCallbacks> mCallbacks;
};

class SimpleChannelChild final : public SimpleChannel,
                                 public nsIChildChannel,
                                 public PSimpleChannelChild {
 public:
  explicit SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSICHILDCHANNEL

 private:
  virtual ~SimpleChannelChild() = default;
};

already_AddRefed<nsIChannel> NS_NewSimpleChannelInternal(
    nsIURI* aURI, nsILoadInfo* aLoadInfo,
    UniquePtr<SimpleChannelCallbacks>&& aCallbacks);

}  // namespace net
}  // namespace mozilla

/**
 * Creates a simple channel which wraps an input stream created by the given
 * callbacks. The callbacks are not called until the underlying AsyncOpen or
 * Open methods are called, and correspond to the nsBaseChannel::StartAsyncRead
 * and nsBaseChannel::OpenContentStream methods of the same names.
 *
 * The last two arguments of each callback are the created channel instance,
 * and the ref-counted context object passed to NS_NewSimpleChannel. A strong
 * reference to that object is guaranteed to be kept alive until after a
 * callback successfully completes.
 */
template <typename T, typename F1, typename F2>
inline already_AddRefed<nsIChannel> NS_NewSimpleChannel(
    nsIURI* aURI, nsILoadInfo* aLoadInfo, T* context, F1&& aStartAsyncRead,
    F2&& aOpenContentStream) {
  using namespace mozilla;

  auto callbacks = MakeUnique<net::SimpleChannelCallbacksImpl<F1, F2, T>>(
      std::move(aStartAsyncRead), std::move(aOpenContentStream), context);

  return net::NS_NewSimpleChannelInternal(aURI, aLoadInfo,
                                          std::move(callbacks));
}

template <typename T, typename F1>
inline already_AddRefed<nsIChannel> NS_NewSimpleChannel(nsIURI* aURI,
                                                        nsILoadInfo* aLoadInfo,
                                                        T* context,
                                                        F1&& aStartAsyncRead) {
  using namespace mozilla;

  auto openContentStream = [](bool async, nsIChannel* channel, T* context) {
    return Err(NS_ERROR_NOT_IMPLEMENTED);
  };

  return NS_NewSimpleChannel(aURI, aLoadInfo, context,
                             std::move(aStartAsyncRead),
                             std::move(openContentStream));
}

#endif  // SimpleChannel_h