GeckoViewInputStream.cpp (3771B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cin: */ 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 #include "GeckoViewInputStream.h" 8 9 #include "nsIURI.h" 10 #include "nsStreamUtils.h" 11 12 using namespace mozilla; 13 14 NS_IMPL_ISUPPORTS(GeckoViewInputStream, nsIInputStream, 15 nsIAndroidContentInputStream); 16 17 NS_IMETHODIMP 18 GeckoViewInputStream::Init(nsIURI* aUri) { 19 nsAutoCString scheme; 20 aUri->GetScheme(scheme); 21 22 if (!scheme.EqualsLiteral("content")) { 23 return NS_ERROR_FILE_INVALID_PATH; 24 } 25 26 nsAutoCString spec; 27 aUri->GetSpec(spec); 28 29 if (!java::ContentInputStream::IsReadable(jni::StringParam(spec))) { 30 return NS_ERROR_FILE_ACCESS_DENIED; 31 } 32 33 mInstance = 34 java::ContentInputStream::GetInstance(jni::StringParam(spec), false); 35 36 return NS_OK; 37 } 38 39 NS_IMETHODIMP 40 GeckoViewInputStream::Close() { 41 mClosed = true; 42 mInstance->Close(); 43 44 return NS_OK; 45 } 46 47 NS_IMETHODIMP 48 GeckoViewInputStream::Available(uint64_t* aCount) { 49 if (mClosed) { 50 return NS_BASE_STREAM_CLOSED; 51 } 52 53 if (!mInstance) { 54 return NS_ERROR_NOT_INITIALIZED; 55 } 56 57 *aCount = static_cast<uint64_t>(mInstance->Available()); 58 return NS_OK; 59 } 60 61 NS_IMETHODIMP 62 GeckoViewInputStream::StreamStatus() { 63 return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK; 64 } 65 66 NS_IMETHODIMP 67 GeckoViewInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aReadCount) { 68 return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount); 69 } 70 71 NS_IMETHODIMP 72 GeckoViewInputStream::ReadSegments(nsWriteSegmentFun writer, void* aClosure, 73 uint32_t aCount, uint32_t* result) { 74 NS_ASSERTION(result, "null ptr"); 75 76 if (mClosed) { 77 return NS_BASE_STREAM_CLOSED; 78 } 79 80 if (!mInstance) { 81 return NS_ERROR_NOT_INITIALIZED; 82 } 83 84 auto bufferAddress = 85 static_cast<const char*>(mInstance->MBuffer()->Address()); 86 uint32_t segmentPos = static_cast<uint32_t>(mInstance->MPos()); 87 int32_t dataLength = 0; 88 nsresult rv; 89 90 *result = 0; 91 while (aCount) { 92 rv = mInstance->Read(static_cast<int64_t>(aCount), &dataLength); 93 if (NS_FAILED(rv)) { 94 return NS_BASE_STREAM_OSERROR; 95 } 96 97 if (dataLength == -1) { 98 break; 99 } 100 101 uint32_t uDataLength = static_cast<uint32_t>(dataLength); 102 uint32_t written; 103 rv = writer(this, aClosure, bufferAddress + segmentPos, *result, 104 uDataLength, &written); 105 106 if (NS_FAILED(rv)) { 107 // InputStreams do not propagate errors to caller. 108 break; 109 } 110 111 NS_ASSERTION(written > 0, "Must have written something"); 112 113 *result += written; 114 aCount -= written; 115 116 segmentPos = static_cast<uint32_t>(mInstance->ConsumedData(written)); 117 } 118 119 return NS_OK; 120 } 121 122 NS_IMETHODIMP 123 GeckoViewInputStream::IsNonBlocking(bool* aNonBlocking) { 124 *aNonBlocking = true; 125 return NS_OK; 126 } 127 128 bool GeckoViewInputStream::IsClosed() const { 129 if (!mInstance) { 130 return true; 131 } 132 133 return mInstance->IsClosed(); 134 } 135 136 bool GeckoViewContentInputStream::isReadable(const nsAutoCString& aUri) { 137 return mozilla::java::ContentInputStream::IsReadable( 138 mozilla::jni::StringParam(aUri)); 139 } 140 141 nsresult GeckoViewContentInputStream::GetInstance(const nsAutoCString& aUri, 142 Allow aAllow, 143 nsIInputStream** aInstance) { 144 RefPtr<GeckoViewContentInputStream> instance = 145 new GeckoViewContentInputStream(aUri, aAllow == Allow::PDFOnly); 146 if (instance->IsClosed()) { 147 return NS_ERROR_FILE_NOT_FOUND; 148 } 149 *aInstance = instance.forget().take(); 150 151 return NS_OK; 152 }