SimpleChannel.h (4989B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef SimpleChannel_h 7 #define SimpleChannel_h 8 9 #include "mozilla/ResultExtensions.h" 10 #include "mozilla/UniquePtr.h" 11 #include "nsBaseChannel.h" 12 #include "nsIChildChannel.h" 13 #include "nsCOMPtr.h" 14 15 class nsIChannel; 16 class nsIInputStream; 17 class nsILoadInfo; 18 class nsIRequest; 19 class nsIStreamListener; 20 class nsIURI; 21 22 //----------------------------------------------------------------------------- 23 24 namespace mozilla { 25 26 using InputStreamOrReason = Result<nsCOMPtr<nsIInputStream>, nsresult>; 27 using NotNullRequest = NotNull<nsCOMPtr<nsIRequest>>; 28 using NotNullCancelable = NotNull<nsCOMPtr<nsICancelable>>; 29 using RequestOrCancelable = Variant<NotNullRequest, NotNullCancelable>; 30 using RequestOrReason = Result<RequestOrCancelable, nsresult>; 31 32 namespace net { 33 34 class SimpleChannelCallbacks { 35 public: 36 virtual InputStreamOrReason OpenContentStream(bool async, 37 nsIChannel* channel) = 0; 38 39 virtual RequestOrReason StartAsyncRead(nsIStreamListener* stream, 40 nsIChannel* channel) = 0; 41 42 virtual ~SimpleChannelCallbacks() = default; 43 }; 44 45 template <typename F1, typename F2, typename T> 46 class SimpleChannelCallbacksImpl final : public SimpleChannelCallbacks { 47 public: 48 SimpleChannelCallbacksImpl(F1&& aStartAsyncRead, F2&& aOpenContentStream, 49 T* context) 50 : mStartAsyncRead(aStartAsyncRead), 51 mOpenContentStream(aOpenContentStream), 52 mContext(context) {} 53 54 virtual ~SimpleChannelCallbacksImpl() = default; 55 56 virtual InputStreamOrReason OpenContentStream(bool async, 57 nsIChannel* channel) override { 58 return mOpenContentStream(async, channel, mContext); 59 } 60 61 virtual RequestOrReason StartAsyncRead(nsIStreamListener* listener, 62 nsIChannel* channel) override { 63 return mStartAsyncRead(listener, channel, mContext); 64 } 65 66 private: 67 F1 mStartAsyncRead; 68 F2 mOpenContentStream; 69 RefPtr<T> mContext; 70 }; 71 72 class SimpleChannel : public nsBaseChannel, public nsIChildChannel { 73 public: 74 NS_DECL_ISUPPORTS_INHERITED 75 NS_DECL_NSICHILDCHANNEL 76 77 explicit SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks); 78 79 protected: 80 virtual ~SimpleChannel() = default; 81 82 virtual nsresult OpenContentStream(bool async, nsIInputStream** streamOut, 83 nsIChannel** channel) override; 84 85 virtual nsresult BeginAsyncRead(nsIStreamListener* listener, 86 nsIRequest** request, 87 nsICancelable** cancelableRequest) override; 88 89 private: 90 UniquePtr<SimpleChannelCallbacks> mCallbacks; 91 }; 92 93 already_AddRefed<nsIChannel> NS_NewSimpleChannelInternal( 94 nsIURI* aURI, nsILoadInfo* aLoadInfo, 95 UniquePtr<SimpleChannelCallbacks>&& aCallbacks); 96 97 } // namespace net 98 } // namespace mozilla 99 100 /** 101 * Creates a simple channel which wraps an input stream created by the given 102 * callbacks. The callbacks are not called until the underlying AsyncOpen or 103 * Open methods are called, and correspond to the nsBaseChannel::StartAsyncRead 104 * and nsBaseChannel::OpenContentStream methods of the same names. 105 * 106 * The last two arguments of each callback are the created channel instance, 107 * and the ref-counted context object passed to NS_NewSimpleChannel. A strong 108 * reference to that object is guaranteed to be kept alive until after a 109 * callback successfully completes. 110 */ 111 template <typename T, typename F1, typename F2> 112 inline already_AddRefed<nsIChannel> NS_NewSimpleChannel( 113 nsIURI* aURI, nsILoadInfo* aLoadInfo, T* context, F1&& aStartAsyncRead, 114 F2&& aOpenContentStream) { 115 using namespace mozilla; 116 117 auto callbacks = MakeUnique<net::SimpleChannelCallbacksImpl<F1, F2, T>>( 118 std::forward<F1>(aStartAsyncRead), std::forward<F2>(aOpenContentStream), 119 context); 120 121 return net::NS_NewSimpleChannelInternal(aURI, aLoadInfo, 122 std::move(callbacks)); 123 } 124 125 template <typename T, typename F1> 126 inline already_AddRefed<nsIChannel> NS_NewSimpleChannel(nsIURI* aURI, 127 nsILoadInfo* aLoadInfo, 128 T* context, 129 F1&& aStartAsyncRead) { 130 using namespace mozilla; 131 132 auto openContentStream = [](bool async, nsIChannel* channel, T* context) { 133 return Err(NS_ERROR_NOT_IMPLEMENTED); 134 }; 135 136 return NS_NewSimpleChannel(aURI, aLoadInfo, context, 137 std::forward<F1>(aStartAsyncRead), 138 std::move(openContentStream)); 139 } 140 141 #endif // SimpleChannel_h