FetchStreamReader.h (4330B)
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_FetchStreamReader_h 8 #define mozilla_dom_FetchStreamReader_h 9 10 #include "js/RootingAPI.h" 11 #include "js/TypeDecls.h" 12 #include "mozilla/Attributes.h" 13 #include "mozilla/WeakPtr.h" 14 #include "mozilla/dom/FetchBinding.h" 15 #include "mozilla/dom/PromiseNativeHandler.h" 16 #include "nsIAsyncOutputStream.h" 17 #include "nsIGlobalObject.h" 18 19 namespace mozilla::dom { 20 21 class ReadableStream; 22 class ReadableStreamDefaultReader; 23 class StrongWorkerRef; 24 25 class FetchStreamReader; 26 27 class OutputStreamHolder final : public nsIOutputStreamCallback { 28 public: 29 NS_DECL_ISUPPORTS 30 NS_DECL_NSIOUTPUTSTREAMCALLBACK 31 32 OutputStreamHolder(FetchStreamReader* aReader, nsIAsyncOutputStream* aOutput); 33 34 nsresult Init(JSContext* aCx); 35 36 void Shutdown(); 37 38 // These just proxy the calls to the nsIAsyncOutputStream 39 nsresult AsyncWait(uint32_t aFlags, uint32_t aRequestedCount, 40 nsIEventTarget* aEventTarget); 41 nsresult Write(char* aBuffer, uint32_t aLength, uint32_t* aWritten) { 42 return mOutput->Write(aBuffer, aLength, aWritten); 43 } 44 nsresult CloseWithStatus(nsresult aStatus) { 45 return mOutput->CloseWithStatus(aStatus); 46 } 47 nsresult StreamStatus() { return mOutput->StreamStatus(); } 48 49 nsIAsyncOutputStream* GetOutputStream() { return mOutput; } 50 51 private: 52 ~OutputStreamHolder(); 53 54 RefPtr<FetchStreamReader> mAsyncWaitReader; 55 // WeakPtr to avoid cycles 56 WeakPtr<FetchStreamReader> mReader; 57 // To ensure the worker sticks around 58 RefPtr<StrongWorkerRef> mAsyncWaitWorkerRef; 59 RefPtr<StrongWorkerRef> mWorkerRef; 60 nsCOMPtr<nsIAsyncOutputStream> mOutput; 61 }; 62 63 class FetchStreamReader final : public nsISupports, public SupportsWeakPtr { 64 public: 65 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 66 NS_DECL_CYCLE_COLLECTION_CLASS(FetchStreamReader) 67 68 // This creates a nsIInputStream able to retrieve data from the ReadableStream 69 // object. The reading starts when StartConsuming() is called. 70 static nsresult Create(JSContext* aCx, nsIGlobalObject* aGlobal, 71 FetchStreamReader** aStreamReader, 72 nsIInputStream** aInputStream); 73 74 bool OnOutputStreamReady(); 75 76 MOZ_CAN_RUN_SCRIPT 77 void ChunkSteps(JSContext* aCx, JS::Handle<JS::Value> aChunk, 78 ErrorResult& aRv); 79 MOZ_CAN_RUN_SCRIPT 80 void CloseSteps(JSContext* aCx, ErrorResult& aRv); 81 MOZ_CAN_RUN_SCRIPT 82 void ErrorSteps(JSContext* aCx, JS::Handle<JS::Value> aError, 83 ErrorResult& aRv); 84 85 // Idempotently close the output stream and null out all state. If aCx is 86 // provided, the reader will also be canceled. aStatus must be a DOM error 87 // as understood by DOMException because it will be provided as the 88 // cancellation reason. 89 // 90 // This is a script boundary minimize annotation changes required while 91 // we figure out how to handle some more tricky annotation cases (for 92 // example, the destructor of this class. Tracking under Bug 1750656) 93 MOZ_CAN_RUN_SCRIPT_BOUNDARY 94 void CloseAndRelease(JSContext* aCx, nsresult aStatus); 95 96 void StartConsuming(JSContext* aCx, ReadableStream* aStream, 97 ErrorResult& aRv); 98 99 private: 100 explicit FetchStreamReader(nsIGlobalObject* aGlobal); 101 ~FetchStreamReader(); 102 103 nsresult WriteBuffer(); 104 105 // Attempt to copy data from mBuffer into mPipeOut. Returns `true` if data was 106 // written, and AsyncWait callbacks or FetchReadRequest calls have been set up 107 // to write more data in the future, and `false` otherwise. 108 MOZ_CAN_RUN_SCRIPT 109 bool Process(JSContext* aCx); 110 111 void ReportErrorToConsole(JSContext* aCx, JS::Handle<JS::Value> aValue); 112 113 nsCOMPtr<nsIGlobalObject> mGlobal; 114 nsCOMPtr<nsIEventTarget> mOwningEventTarget; 115 116 RefPtr<OutputStreamHolder> mOutput; 117 118 RefPtr<ReadableStreamDefaultReader> mReader; 119 120 nsTArray<uint8_t> mBuffer; 121 uint32_t mBufferRemaining = 0; 122 uint32_t mBufferOffset = 0; 123 124 bool mHasOutstandingReadRequest = false; 125 bool mStreamClosed = false; 126 }; 127 128 } // namespace mozilla::dom 129 130 #endif // mozilla_dom_FetchStreamReader_h