2018-11-30 22:52:05 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2018-01-31 18:45:20 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef NonBlockingAsyncInputStream_h
|
|
|
|
#define NonBlockingAsyncInputStream_h
|
|
|
|
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/Maybe.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIAsyncInputStream.h"
|
|
|
|
#include "nsICloneableInputStream.h"
|
|
|
|
#include "nsIIPCSerializableInputStream.h"
|
|
|
|
#include "nsISeekableStream.h"
|
|
|
|
|
|
|
|
// This class aims to wrap a non-blocking and non-async inputStream and expose
|
|
|
|
// it as nsIAsyncInputStream.
|
|
|
|
// Probably you don't want to use this class directly. Instead use
|
|
|
|
// NS_MakeAsyncNonBlockingInputStream() as it will handle different stream
|
|
|
|
// variants without requiring you to special-case them yourself.
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
class NonBlockingAsyncInputStream final : public nsIAsyncInputStream,
|
|
|
|
public nsICloneableInputStream,
|
|
|
|
public nsIIPCSerializableInputStream,
|
|
|
|
public nsISeekableStream {
|
|
|
|
public:
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
|
NS_DECL_NSIINPUTSTREAM
|
|
|
|
NS_DECL_NSIASYNCINPUTSTREAM
|
|
|
|
NS_DECL_NSICLONEABLEINPUTSTREAM
|
|
|
|
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
|
|
|
|
NS_DECL_NSISEEKABLESTREAM
|
Bug 1496581 - Split nsISeekableStream in 2 classes: nsISeekableStream and nsITellableStream, f=mayhemer, r=froydnj
In the current code there are 3 main issues:
1. nsFileStream is not really thread-safe. There is nothing to protect the
internal members and we see crashes.
2. nsPipeInputStream doesn't implement ::Seek() method and that caused issues
in devtools when a nsHttpChannel sends POST data using a pipe. In order to fix
this, bug 1494176 added a check in nsHttpChannel: if the stream doesn't
implement ::Seek(), let's clone it. This was an hack around nsPipeInputStream,
and it's bad.
3. When nsHttpChannel sends POST data using a file stream, nsFileStream does
I/O on main-thread because of the issue 2. Plus, ::Seek() is called on the
main-thread causing issue 1.
Note that nsPipeInputStream implements only ::Tell(), of the nsISeekableStream
methods. It doesn't implement ::Seek() and it doesn't implement ::SetEOF().
With this patch I want to fix point 2 and point 3 (and consequentially issue 1
- but we need a separate fix for it - follow up). The patch does:
1. it splits nsISeekableStream in 2 interfaces: nsITellableStream and
nsISeekableStream.
2. nsPipeInputStream implements only nsITellableStream. Doing this, we don't
need the ::Seek() check for point 2 in nsHttpChannel: a simple QI check is
enough.
3. Because we don't call ::Seek() in nsHttpChannel, nsFileStream doesn't do I/O
on the main-thread, and we don't crash doing so.
2018-10-18 14:35:35 +03:00
|
|
|
NS_DECL_NSITELLABLESTREAM
|
2018-01-31 18:45:20 +03:00
|
|
|
|
|
|
|
// |aInputStream| must be a non-blocking, non-async inputSteam.
|
2018-01-31 18:45:20 +03:00
|
|
|
static nsresult Create(already_AddRefed<nsIInputStream> aInputStream,
|
2018-01-31 18:45:20 +03:00
|
|
|
nsIAsyncInputStream** aAsyncInputStream);
|
|
|
|
|
|
|
|
private:
|
2018-01-31 18:45:20 +03:00
|
|
|
explicit NonBlockingAsyncInputStream(
|
|
|
|
already_AddRefed<nsIInputStream> aInputStream);
|
2018-01-31 18:45:20 +03:00
|
|
|
~NonBlockingAsyncInputStream();
|
|
|
|
|
2019-01-28 12:48:35 +03:00
|
|
|
template <typename M>
|
|
|
|
void SerializeInternal(mozilla::ipc::InputStreamParams& aParams,
|
|
|
|
FileDescriptorArray& aFileDescriptors,
|
2019-02-05 01:50:51 +03:00
|
|
|
bool aDelayedStart, uint32_t aMaxSize,
|
|
|
|
uint32_t* aSizeUsed, M* aManager);
|
2019-01-28 12:48:35 +03:00
|
|
|
|
2018-01-31 18:45:21 +03:00
|
|
|
class AsyncWaitRunnable;
|
|
|
|
|
|
|
|
void RunAsyncWaitCallback(AsyncWaitRunnable* aRunnable,
|
|
|
|
already_AddRefed<nsIInputStreamCallback> aCallback);
|
|
|
|
|
2018-01-31 18:45:20 +03:00
|
|
|
nsCOMPtr<nsIInputStream> mInputStream;
|
|
|
|
|
|
|
|
// Raw pointers because these are just QI of mInputStream.
|
|
|
|
nsICloneableInputStream* MOZ_NON_OWNING_REF mWeakCloneableInputStream;
|
|
|
|
nsIIPCSerializableInputStream* MOZ_NON_OWNING_REF
|
|
|
|
mWeakIPCSerializableInputStream;
|
|
|
|
nsISeekableStream* MOZ_NON_OWNING_REF mWeakSeekableInputStream;
|
Bug 1496581 - Split nsISeekableStream in 2 classes: nsISeekableStream and nsITellableStream, f=mayhemer, r=froydnj
In the current code there are 3 main issues:
1. nsFileStream is not really thread-safe. There is nothing to protect the
internal members and we see crashes.
2. nsPipeInputStream doesn't implement ::Seek() method and that caused issues
in devtools when a nsHttpChannel sends POST data using a pipe. In order to fix
this, bug 1494176 added a check in nsHttpChannel: if the stream doesn't
implement ::Seek(), let's clone it. This was an hack around nsPipeInputStream,
and it's bad.
3. When nsHttpChannel sends POST data using a file stream, nsFileStream does
I/O on main-thread because of the issue 2. Plus, ::Seek() is called on the
main-thread causing issue 1.
Note that nsPipeInputStream implements only ::Tell(), of the nsISeekableStream
methods. It doesn't implement ::Seek() and it doesn't implement ::SetEOF().
With this patch I want to fix point 2 and point 3 (and consequentially issue 1
- but we need a separate fix for it - follow up). The patch does:
1. it splits nsISeekableStream in 2 interfaces: nsITellableStream and
nsISeekableStream.
2. nsPipeInputStream implements only nsITellableStream. Doing this, we don't
need the ::Seek() check for point 2 in nsHttpChannel: a simple QI check is
enough.
3. Because we don't call ::Seek() in nsHttpChannel, nsFileStream doesn't do I/O
on the main-thread, and we don't crash doing so.
2018-10-18 14:35:35 +03:00
|
|
|
nsITellableStream* MOZ_NON_OWNING_REF mWeakTellableInputStream;
|
2018-01-31 18:45:20 +03:00
|
|
|
|
2018-01-31 18:45:21 +03:00
|
|
|
Mutex mLock;
|
|
|
|
|
2018-01-31 18:45:20 +03:00
|
|
|
struct WaitClosureOnly {
|
2018-01-31 18:45:21 +03:00
|
|
|
WaitClosureOnly(AsyncWaitRunnable* aRunnable, nsIEventTarget* aEventTarget);
|
2018-01-31 18:45:20 +03:00
|
|
|
|
2018-01-31 18:45:21 +03:00
|
|
|
RefPtr<AsyncWaitRunnable> mRunnable;
|
2018-01-31 18:45:20 +03:00
|
|
|
nsCOMPtr<nsIEventTarget> mEventTarget;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This is set when AsyncWait is called with a callback and with
|
|
|
|
// WAIT_CLOSURE_ONLY as flag.
|
2018-01-31 18:45:21 +03:00
|
|
|
// This is protected by mLock.
|
2018-01-31 18:45:20 +03:00
|
|
|
Maybe<WaitClosureOnly> mWaitClosureOnly;
|
|
|
|
|
2018-01-31 18:45:21 +03:00
|
|
|
// This is protected by mLock.
|
|
|
|
RefPtr<AsyncWaitRunnable> mAsyncWaitCallback;
|
|
|
|
|
|
|
|
// This is protected by mLock.
|
2018-01-31 18:45:20 +03:00
|
|
|
bool mClosed;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // NonBlockingAsyncInputStream_h
|