Bug 1231213 - Correctly choose nsBufferedStream's underlying nsIInputStream after initialization. r=asuth

Differential Revision: https://phabricator.services.mozilla.com/D26159

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Perry Jiang 2019-08-13 04:03:12 +00:00
Родитель 931915402d
Коммит 166ecc9374
3 изменённых файлов: 48 добавлений и 3 удалений

Просмотреть файл

@ -9,6 +9,7 @@
#include "nsStreamUtils.h"
#include "nsNetCID.h"
#include "nsIClassInfoImpl.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include <algorithm>
@ -38,6 +39,7 @@ static struct {
#endif
using namespace mozilla::ipc;
using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::MutexAutoLock;
using mozilla::Nothing;
@ -276,7 +278,16 @@ NS_IMPL_CLASSINFO(nsBufferedInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_BUFFEREDINPUTSTREAM_CID)
NS_INTERFACE_MAP_BEGIN(nsBufferedInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIBufferedInputStream)
// Unfortunately there isn't a macro that combines ambiguous and conditional,
// and as far as I can tell, no other class would need such a macro.
if (mIsAsyncInputStream && aIID.Equals(NS_GET_IID(nsIInputStream))) {
foundInterface =
static_cast<nsIInputStream*>(static_cast<nsIAsyncInputStream*>(this));
} else if (!mIsAsyncInputStream && aIID.Equals(NS_GET_IID(nsIInputStream))) {
foundInterface = static_cast<nsIInputStream*>(
static_cast<nsIBufferedInputStream*>(this));
} else
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBufferedInputStream)
NS_INTERFACE_MAP_ENTRY(nsIBufferedInputStream)
NS_INTERFACE_MAP_ENTRY(nsIStreamBufferAccess)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
@ -348,6 +359,19 @@ nsBufferedInputStream::Init(nsIInputStream* stream, uint32_t bufferSize) {
return NS_OK;
}
already_AddRefed<nsIInputStream> nsBufferedInputStream::GetInputStream() {
// A non-null mStream implies Init() has been called.
MOZ_ASSERT(mStream);
nsIInputStream* out = nullptr;
DebugOnly<nsresult> rv = QueryInterface(NS_GET_IID(nsIInputStream),
reinterpret_cast<void**>(&out));
MOZ_ASSERT(NS_SUCCEEDED(rv));
MOZ_ASSERT(out);
return already_AddRefed<nsIInputStream>(out);
}
NS_IMETHODIMP
nsBufferedInputStream::Close() {
nsresult rv1 = NS_OK, rv2;
@ -764,7 +788,9 @@ nsBufferedInputStream::Clone(nsIInputStream** aResult) {
rv = bis->Init(clonedStream, mBufferSize);
NS_ENSURE_SUCCESS(rv, rv);
bis.forget(aResult);
*aResult =
static_cast<nsBufferedInputStream*>(bis.get())->GetInputStream().take();
return NS_OK;
}

Просмотреть файл

@ -92,6 +92,22 @@ class nsBufferedInputStream final : public nsBufferedStream,
nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); }
/**
* If there's a reference/pointer to an nsBufferedInputStream BEFORE calling
* Init() AND the intent is to ultimately convert/assign that
* reference/pointer to an nsIInputStream, DO NOT use that initial
* reference/pointer. Instead, use the value of QueryInterface-ing to an
* nsIInputStream (and, again, the QueryInterface must be performed after
* Init()). This is because nsBufferedInputStream has multiple underlying
* nsIInputStreams (one from nsIBufferedInputStream and one from
* nsIAsyncInputStream), and the correct base nsIInputStream to use will be
* unknown until the final value of mIsAsyncInputStream is set in Init().
*
* This method, however, does just that but also hides the QI details and
* will assert if called before Init().
*/
already_AddRefed<nsIInputStream> GetInputStream();
protected:
virtual ~nsBufferedInputStream() = default;

Просмотреть файл

@ -30,6 +30,7 @@
#include "nsIAuthPrompt2.h"
#include "nsIAuthPromptAdapterFactory.h"
#include "nsIBufferedStreams.h"
#include "nsBufferedStreams.h"
#include "nsIChannelEventSink.h"
#include "nsIContentSniffer.h"
#include "mozilla/dom/Document.h"
@ -1269,7 +1270,9 @@ MOZ_MUST_USE nsresult NS_NewBufferedInputStream(
if (NS_SUCCEEDED(rv)) {
rv = in->Init(inputStream, aBufferSize);
if (NS_SUCCEEDED(rv)) {
in.forget(aResult);
*aResult = static_cast<nsBufferedInputStream*>(in.get())
->GetInputStream()
.take();
}
}
return rv;