nsBaseContentStream.cpp (3765B)
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 #include "nsBaseContentStream.h" 7 #include "nsStreamUtils.h" 8 9 //----------------------------------------------------------------------------- 10 11 void nsBaseContentStream::DispatchCallback(bool async) { 12 if (!mCallback) return; 13 14 // It's important to clear mCallback and mCallbackTarget up-front because the 15 // OnInputStreamReady implementation may call our AsyncWait method. 16 17 nsCOMPtr<nsIInputStreamCallback> callback; 18 if (async) { 19 callback = NS_NewInputStreamReadyEvent( 20 "nsBaseContentStream::DispatchCallback", mCallback, mCallbackTarget); 21 mCallback = nullptr; 22 } else { 23 callback.swap(mCallback); 24 } 25 mCallbackTarget = nullptr; 26 27 callback->OnInputStreamReady(this); 28 } 29 30 //----------------------------------------------------------------------------- 31 // nsBaseContentStream::nsISupports 32 33 NS_IMPL_ADDREF(nsBaseContentStream) 34 NS_IMPL_RELEASE(nsBaseContentStream) 35 36 // We only support nsIAsyncInputStream when we are in non-blocking mode. 37 NS_INTERFACE_MAP_BEGIN(nsBaseContentStream) 38 NS_INTERFACE_MAP_ENTRY(nsIInputStream) 39 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mNonBlocking) 40 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) 41 NS_INTERFACE_MAP_END 42 43 //----------------------------------------------------------------------------- 44 // nsBaseContentStream::nsIInputStream 45 46 NS_IMETHODIMP 47 nsBaseContentStream::Close() { 48 return IsClosed() ? NS_OK : CloseWithStatus(NS_BASE_STREAM_CLOSED); 49 } 50 51 NS_IMETHODIMP 52 nsBaseContentStream::Available(uint64_t* result) { 53 *result = 0; 54 return mStatus; 55 } 56 57 NS_IMETHODIMP 58 nsBaseContentStream::StreamStatus() { return mStatus; } 59 60 NS_IMETHODIMP 61 nsBaseContentStream::Read(char* buf, uint32_t count, uint32_t* result) { 62 return ReadSegments(NS_CopySegmentToBuffer, buf, count, result); 63 } 64 65 NS_IMETHODIMP 66 nsBaseContentStream::ReadSegments(nsWriteSegmentFun fun, void* closure, 67 uint32_t count, uint32_t* result) { 68 *result = 0; 69 70 if (mStatus == NS_BASE_STREAM_CLOSED) return NS_OK; 71 72 // No data yet 73 if (!IsClosed() && IsNonBlocking()) return NS_BASE_STREAM_WOULD_BLOCK; 74 75 return mStatus; 76 } 77 78 NS_IMETHODIMP 79 nsBaseContentStream::IsNonBlocking(bool* result) { 80 *result = mNonBlocking; 81 return NS_OK; 82 } 83 84 //----------------------------------------------------------------------------- 85 // nsBaseContentStream::nsIAsyncInputStream 86 87 NS_IMETHODIMP 88 nsBaseContentStream::CloseWithStatus(nsresult status) { 89 if (IsClosed()) return NS_OK; 90 91 NS_ENSURE_ARG(NS_FAILED(status)); 92 mStatus = status; 93 94 DispatchCallback(); 95 return NS_OK; 96 } 97 98 NS_IMETHODIMP 99 nsBaseContentStream::AsyncWait(nsIInputStreamCallback* callback, uint32_t flags, 100 uint32_t requestedCount, 101 nsIEventTarget* target) { 102 // Our _only_ consumer is nsInputStreamPump, so we simplify things here by 103 // making assumptions about how we will be called. 104 NS_ASSERTION(target, "unexpected parameter"); 105 NS_ASSERTION(flags == 0, "unexpected parameter"); 106 NS_ASSERTION(requestedCount == 0, "unexpected parameter"); 107 108 #ifdef DEBUG 109 bool correctThread; 110 target->IsOnCurrentThread(&correctThread); 111 NS_ASSERTION(correctThread, "event target must be on the current thread"); 112 #endif 113 114 mCallback = callback; 115 mCallbackTarget = target; 116 117 if (!mCallback) return NS_OK; 118 119 // If we're already closed, then dispatch this callback immediately. 120 if (IsClosed()) { 121 DispatchCallback(); 122 return NS_OK; 123 } 124 125 OnCallbackPending(); 126 return NS_OK; 127 }