Bug 781256 - 'Share FileDescriptors across processes in preparation for OS-level sandbox'. r=khuey+cjones.

--HG--
rename : netwerk/base/public/nsIIPCSerializable.idl => netwerk/base/public/nsIIPCSerializableObsolete.idl
extra : transplant_source : %EB%18%9D%E6%B1%C6%26%A2%16%F3%85g%1A%25%B1%8E%A1%E72e
This commit is contained in:
Ben Turner 2012-08-16 00:02:32 -04:00
parent 2c43844d19
commit 4b09919a18
40 changed files with 1102 additions and 125 deletions

View File

@ -17,7 +17,8 @@
#include "nsIDocument.h"
#include "nsIFileStreams.h"
#include "nsIInputStream.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsIMIMEService.h"
#include "nsIPlatformCharset.h"
#include "nsISeekableStream.h"
@ -47,8 +48,9 @@ using namespace mozilla::dom;
// stream is. We do that by passing back this class instead.
class DataOwnerAdapter MOZ_FINAL : public nsIInputStream,
public nsISeekableStream,
public nsIIPCSerializable,
public nsIClassInfo
public nsIIPCSerializableObsolete,
public nsIClassInfo,
public nsIIPCSerializableInputStream
{
typedef nsDOMMemoryFile::DataOwner DataOwner;
public:
@ -65,16 +67,18 @@ public:
// These are optional. We use a conditional QI to keep them from being called
// if the underlying stream doesn't QI to either interface.
NS_FORWARD_NSIIPCSERIALIZABLE(mSerializable->)
NS_FORWARD_NSIIPCSERIALIZABLEOBSOLETE(mSerializableObsolete->)
NS_FORWARD_NSICLASSINFO(mClassInfo->)
NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
private:
DataOwnerAdapter(DataOwner* aDataOwner,
nsIInputStream* aStream)
: mDataOwner(aDataOwner), mStream(aStream),
mSeekableStream(do_QueryInterface(aStream)),
mSerializable(do_QueryInterface(aStream)),
mClassInfo(do_QueryInterface(aStream))
mSerializableObsolete(do_QueryInterface(aStream)),
mClassInfo(do_QueryInterface(aStream)),
mSerializableInputStream(do_QueryInterface(aStream))
{
NS_ASSERTION(mSeekableStream, "Somebody gave us the wrong stream!");
}
@ -82,8 +86,9 @@ private:
nsRefPtr<DataOwner> mDataOwner;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsISeekableStream> mSeekableStream;
nsCOMPtr<nsIIPCSerializable> mSerializable;
nsCOMPtr<nsIIPCSerializableObsolete> mSerializableObsolete;
nsCOMPtr<nsIClassInfo> mClassInfo;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
};
NS_IMPL_THREADSAFE_ADDREF(DataOwnerAdapter)
@ -92,8 +97,11 @@ NS_IMPL_THREADSAFE_RELEASE(DataOwnerAdapter)
NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializable, mSerializable)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableObsolete,
mSerializableObsolete)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIClassInfo, mClassInfo)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END

View File

@ -9,7 +9,6 @@
#include "base/basictypes.h"
#include "IPC/IPCMessageUtils.h"
#include "nsIIPCSerializable.h"
#include "nsILoadContext.h"
/*

View File

@ -10,13 +10,14 @@
#include "nsIDOMFile.h"
#include "nsIInputStream.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIRemoteBlob.h"
#include "nsISeekableStream.h"
#include "mozilla/Assertions.h"
#include "mozilla/Monitor.h"
#include "mozilla/unused.h"
#include "mozilla/net/NeckoMessageUtils.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsDOMFile.h"
#include "nsThreadUtils.h"
@ -25,6 +26,7 @@
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
using namespace mozilla::ipc;
namespace {
@ -227,10 +229,18 @@ private:
}
};
NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
template <ActorFlavorEnum ActorFlavor>
class InputStreamActor : public BlobTraits<ActorFlavor>::StreamType
{
typedef typename BlobTraits<ActorFlavor>::StreamType::InputStream InputStream;
nsRefPtr<RemoteInputStream> mRemoteStream;
public:
@ -249,12 +259,17 @@ public:
private:
// This method is only called by the IPDL message machinery.
virtual bool
Recv__delete__(const InputStream& aStream) MOZ_OVERRIDE
Recv__delete__(const InputStreamParams& aParams) MOZ_OVERRIDE
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mRemoteStream);
mRemoteStream->SetStream(aStream);
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams);
if (!stream) {
return false;
}
mRemoteStream->SetStream(stream);
return true;
}
};
@ -605,14 +620,10 @@ public:
virtual void*
GetPBlob() MOZ_OVERRIDE
{
return static_cast<typename ActorType::BaseType*>(mActor);
return static_cast<typename ActorType::ProtocolType*>(mActor);
}
};
} // namespace ipc
} // namespace dom
} // namespace mozilla
template <ActorFlavorEnum ActorFlavor>
Blob<ActorFlavor>::Blob(nsIDOMBlob* aBlob)
: mBlob(aBlob), mRemoteBlob(nullptr), mOwnsBlob(true), mBlobIsFile(false)
@ -740,7 +751,7 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(const nsString& aName,
ToConcreteBlob(mBlob)->SetLazyData(aName, aContentType, aLength);
FileBlobConstructorParams params(aName, aContentType, aLength);
return BaseType::SendResolveMystery(params);
return ProtocolType::SendResolveMystery(params);
}
template <ActorFlavorEnum ActorFlavor>
@ -759,7 +770,7 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(const nsString& aContentType,
ToConcreteBlob(mBlob)->SetLazyData(voidString, aContentType, aLength);
NormalBlobConstructorParams params(aContentType, aLength);
return BaseType::SendResolveMystery(params);
return ProtocolType::SendResolveMystery(params);
}
template <ActorFlavorEnum ActorFlavor>
@ -809,7 +820,7 @@ Blob<ActorFlavor>::NoteDyingRemoteBlob()
// access a dangling pointer.
mRemoteBlob = nullptr;
mozilla::unused << BaseType::Send__delete__(this);
mozilla::unused << ProtocolType::Send__delete__(this);
}
template <ActorFlavorEnum ActorFlavor>
@ -868,9 +879,9 @@ Blob<ActorFlavor>::RecvResolveMystery(const ResolveMysteryParams& aParams)
return true;
}
template <ActorFlavorEnum ActorFlavor>
template <>
bool
Blob<ActorFlavor>::RecvPBlobStreamConstructor(StreamType* aActor)
Blob<Parent>::RecvPBlobStreamConstructor(StreamType* aActor)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBlob);
@ -880,7 +891,55 @@ Blob<ActorFlavor>::RecvPBlobStreamConstructor(StreamType* aActor)
nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, false);
return aActor->Send__delete__(aActor, stream.get());
nsCOMPtr<nsIIPCSerializableInputStream> serializable =
do_QueryInterface(stream);
if (!serializable) {
MOZ_ASSERT(false, "Must be serializable!");
return false;
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ENSURE_TRUE(target, false);
nsRefPtr<BaseType::OpenStreamRunnable> runnable =
new BaseType::OpenStreamRunnable(this, aActor, stream, serializable,
target);
rv = target->Dispatch(runnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, false);
nsRevocableEventPtr<BaseType::OpenStreamRunnable>* arrayMember =
mOpenStreamRunnables.AppendElement();
*arrayMember = runnable;
return true;
}
template <>
bool
Blob<Child>::RecvPBlobStreamConstructor(StreamType* aActor)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBlob);
MOZ_ASSERT(!mRemoteBlob);
nsCOMPtr<nsIInputStream> stream;
nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsIIPCSerializableInputStream> serializable =
do_QueryInterface(stream);
if (!serializable) {
MOZ_ASSERT(false, "Must be serializable!");
return false;
}
InputStreamParams params;
serializable->Serialize(params);
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
return aActor->Send__delete__(aActor, params);
}
template <ActorFlavorEnum ActorFlavor>
@ -910,18 +969,127 @@ template <ActorFlavorEnum ActorFlavor>
NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteBlob<ActorFlavor>, nsDOMFile,
nsIRemoteBlob)
NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
void
BlobTraits<Parent>::BaseType::NoteRunnableCompleted(
BlobTraits<Parent>::BaseType::OpenStreamRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
for (PRUint32 index = 0; index < mOpenStreamRunnables.Length(); index++) {
nsRevocableEventPtr<BaseType::OpenStreamRunnable>& runnable =
mOpenStreamRunnables[index];
namespace mozilla {
namespace dom {
namespace ipc {
if (runnable.get() == aRunnable) {
runnable.Forget();
mOpenStreamRunnables.RemoveElementAt(index);
return;
}
}
MOZ_NOT_REACHED("Runnable not in our array!");
}
BlobTraits<Parent>::BaseType::
OpenStreamRunnable::OpenStreamRunnable(
BlobTraits<Parent>::BaseType* aOwner,
BlobTraits<Parent>::StreamType* aActor,
nsIInputStream* aStream,
nsIIPCSerializableInputStream* aSerializable,
nsIEventTarget* aTarget)
: mOwner(aOwner), mActor(aActor), mStream(aStream),
mSerializable(aSerializable), mTarget(aTarget), mRevoked(false),
mClosing(false)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aOwner);
MOZ_ASSERT(aActor);
MOZ_ASSERT(aStream);
MOZ_ASSERT(aSerializable);
MOZ_ASSERT(aTarget);
}
NS_IMETHODIMP
BlobTraits<Parent>::BaseType::OpenStreamRunnable::Run()
{
MOZ_ASSERT(mStream);
nsresult rv;
if (NS_IsMainThread()) {
MOZ_ASSERT(mTarget);
MOZ_ASSERT(!mClosing);
if (mRevoked) {
MOZ_ASSERT(!mOwner);
MOZ_ASSERT(!mActor);
}
else {
MOZ_ASSERT(mOwner);
MOZ_ASSERT(mActor);
nsCOMPtr<nsIIPCSerializableInputStream> serializable;
mSerializable.swap(serializable);
InputStreamParams params;
serializable->Serialize(params);
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
unused << mActor->Send__delete__(mActor, params);
mOwner->NoteRunnableCompleted(this);
#ifdef DEBUG
mOwner = nullptr;
mActor = nullptr;
#endif
}
mClosing = true;
nsCOMPtr<nsIEventTarget> target;
mTarget.swap(target);
rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
if (!mClosing) {
// To force the stream open we call Available(). We don't actually care how
// much data is available.
PRUint64 available;
if (NS_FAILED(mStream->Available(&available))) {
NS_WARNING("Available failed on this stream!");
}
rv = NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Going to always release here.
nsCOMPtr<nsIInputStream> stream;
mStream.swap(stream);
rv = stream->Close();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
#ifdef DEBUG
void
BlobTraits<Parent>::BaseType::OpenStreamRunnable::Revoke()
{
MOZ_ASSERT(NS_IsMainThread());
mOwner = nullptr;
mActor = nullptr;
mRevoked = true;
}
#endif
// Explicit instantiation of both classes.
template class Blob<Parent>;

View File

@ -12,12 +12,16 @@
#include "mozilla/dom/PBlobParent.h"
#include "mozilla/dom/PBlobStreamChild.h"
#include "mozilla/dom/PBlobStreamParent.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/PContentParent.h"
#include "mozilla/dom/PContent.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
class nsIDOMBlob;
class nsIIPCSerializableInputStream;
class nsIInputStream;
namespace mozilla {
namespace dom {
@ -36,17 +40,92 @@ struct BlobTraits
template <>
struct BlobTraits<Parent>
{
typedef mozilla::dom::PBlobParent BaseType;
typedef mozilla::dom::PBlobParent ProtocolType;
typedef mozilla::dom::PBlobStreamParent StreamType;
typedef mozilla::dom::PContentParent ManagerType;
// BaseType on the parent side is a bit more complicated than for the child
// side. In the case of nsIInputStreams backed by files we need to ensure that
// the files are actually opened and closed on a background thread before we
// can send their file handles across to the child. The child process could
// crash during this process so we need to make sure we cancel the intended
// response in such a case. We do that by holding an array of
// nsRevocableEventPtr. If the child crashes then this actor will be destroyed
// and the nsRevocableEventPtr destructor will cancel any stream events that
// are currently in flight.
class BaseType : public ProtocolType
{
protected:
BaseType()
{ }
virtual ~BaseType()
{ }
// Each instance of this class will be dispatched to the network stream
// thread pool to run the first time where it will open the file input
// stream. It will then dispatch itself back to the main thread to send the
// child process its response (assuming that the child has not crashed). The
// runnable will then dispatch itself to the thread pool again in order to
// close the file input stream.
class OpenStreamRunnable : public nsRunnable
{
friend class nsRevocableEventPtr<OpenStreamRunnable>;
public:
NS_DECL_NSIRUNNABLE
OpenStreamRunnable(BaseType* aOwner, StreamType* aActor,
nsIInputStream* aStream,
nsIIPCSerializableInputStream* aSerializable,
nsIEventTarget* aTarget);
private:
#ifdef DEBUG
void
Revoke();
#else
void
Revoke()
{
mRevoked = true;
}
#endif
// Only safe to access these two pointers if mRevoked is false!
BaseType* mOwner;
StreamType* mActor;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializable;
nsCOMPtr<nsIEventTarget> mTarget;
bool mRevoked;
bool mClosing;
};
friend class OpenStreamRunnable;
void
NoteRunnableCompleted(OpenStreamRunnable* aRunnable);
nsTArray<nsRevocableEventPtr<OpenStreamRunnable> > mOpenStreamRunnables;
};
};
template <>
struct BlobTraits<Child>
{
typedef mozilla::dom::PBlobChild BaseType;
typedef mozilla::dom::PBlobChild ProtocolType;
typedef mozilla::dom::PBlobStreamChild StreamType;
typedef mozilla::dom::PContentChild ManagerType;
class BaseType : public ProtocolType
{
protected:
BaseType()
{ }
virtual ~BaseType()
{ }
};
};
template <ActorFlavorEnum>
@ -58,9 +137,9 @@ class Blob : public BlobTraits<ActorFlavor>::BaseType
friend class RemoteBlob<ActorFlavor>;
public:
typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
typedef typename BlobTraits<ActorFlavor>::ProtocolType ProtocolType;
typedef typename BlobTraits<ActorFlavor>::StreamType StreamType;
typedef typename BlobTraits<ActorFlavor>::ManagerType ManagerType;
typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
typedef RemoteBlob<ActorFlavor> RemoteBlobType;
typedef mozilla::ipc::IProtocolManager<
mozilla::ipc::RPCChannel::RPCListener>::ActorDestroyReason

View File

@ -3,10 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include "mozilla/net/NeckoMessageUtils.h";
using IPC::InputStream;
include IPCSerializableParams;
namespace mozilla {
namespace dom {
@ -16,7 +13,7 @@ protocol PBlobStream
manager PBlob;
both:
__delete__(InputStream stream);
__delete__(InputStreamParams params);
};
} // namespace dom

View File

@ -14,7 +14,6 @@ include "mozilla/dom/TabMessageUtils.h";
using NPError;
using NPNVariable;
using base::FileDescriptor;
using mozilla::dom::NativeThreadId;
using mac_plugin_interposing::NSCursorInfo;
using nsID;

View File

@ -1850,10 +1850,10 @@ PluginModuleChild::AnswerNP_Initialize(const uint32_t& aFlags, NPError* _retval)
#endif
#ifdef MOZ_X11
// Send the parent a dup of our X socket, to act as a proxy
// reference for our X resources
// Send the parent our X socket to act as a proxy reference for our X
// resources.
int xSocketFd = ConnectionNumber(DefaultXDisplay());
SendBackUpXResources(FileDescriptor(xSocketFd, false/*don't close*/));
SendBackUpXResources(FileDescriptor(xSocketFd));
#endif
#if defined(OS_LINUX)

View File

@ -689,9 +689,8 @@ PluginModuleParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
#else
NS_ABORT_IF_FALSE(0 > mPluginXSocketFdDup.get(),
"Already backed up X resources??");
int fd = aXSocketFd.fd; // Copy to discard |const| qualifier
mPluginXSocketFdDup.forget();
mPluginXSocketFdDup.reset(fd);
mPluginXSocketFdDup.reset(aXSocketFd.PlatformHandle());
#endif
return true;
}

View File

@ -0,0 +1,65 @@
/* 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/. */
#include "FileDescriptor.h"
#include "mozilla/Assertions.h"
#include "nsDebug.h"
#ifdef XP_WIN
#include <windows.h>
#define INVALID_HANDLE INVALID_HANDLE_VALUE
#else
#include <unistd.h>
#define INVALID_HANDLE -1
#endif
using mozilla::ipc::FileDescriptor;
FileDescriptor::FileDescriptor()
: mHandle(INVALID_HANDLE)
{ }
FileDescriptor::PickleType
FileDescriptor::ShareTo(const FileDescriptor::IPDLPrivate&,
FileDescriptor::ProcessHandle aOtherProcess) const
{
#ifdef XP_WIN
if (mHandle == INVALID_HANDLE) {
return INVALID_HANDLE;
}
PlatformHandleType newHandle;
if (!DuplicateHandle(GetCurrentProcess(), mHandle, aOtherProcess, &newHandle,
0, FALSE, DUPLICATE_SAME_ACCESS)) {
NS_WARNING("Failed to duplicate file handle!");
return INVALID_HANDLE;
}
return newHandle;
#else // XP_WIN
if (mHandle == INVALID_HANDLE) {
return base::FileDescriptor();
}
PlatformHandleType newHandle = dup(mHandle);
if (newHandle < 0) {
NS_WARNING("Failed to duplicate file descriptor!");
return base::FileDescriptor();
}
// This file descriptor must be closed once the caller is done using it, so
// pass true here for the 'auto_close' argument.
return base::FileDescriptor(newHandle, true);
#endif
MOZ_NOT_REACHED("Must not get here!");
return PickleType();
}
bool
FileDescriptor::IsValid() const
{
return mHandle != INVALID_HANDLE;
}

95
ipc/glue/FileDescriptor.h Normal file
View File

@ -0,0 +1,95 @@
/* 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 mozilla_ipc_FileDescriptor_h
#define mozilla_ipc_FileDescriptor_h
#include "base/basictypes.h"
#include "base/process.h"
#include "nscore.h"
#ifdef XP_WIN
// Need the HANDLE typedef.
#include <winnt.h>
#else
#include "base/file_descriptor_posix.h"
#endif
namespace mozilla {
namespace ipc {
// This class is used by IPDL to share file descriptors across processes. When
// sending a FileDescriptor IPDL will first duplicate a platform-specific file
// handle type ('PlatformHandleType') into a handle that is valid in the other
// process. Then IPDL will convert the duplicated handle into a type suitable
// for pickling ('PickleType') and then send that through the IPC pipe. In the
// receiving process the pickled data is converted into a platform-specific file
// handle and then returned to the receiver.
//
// To use this class add 'FileDescriptor' as an argument in the IPDL protocol
// and then pass a file descriptor from C++ to the Call/Send method. The
// Answer/Recv method will receive a FileDescriptor& on which PlatformHandle()
// can be called to return the platform file handle.
class FileDescriptor
{
public:
typedef base::ProcessHandle ProcessHandle;
#ifdef XP_WIN
typedef HANDLE PlatformHandleType;
typedef HANDLE PickleType;
#else
typedef int PlatformHandleType;
typedef base::FileDescriptor PickleType;
#endif
// This should only ever be created by IPDL.
struct IPDLPrivate
{};
FileDescriptor();
FileDescriptor(PlatformHandleType aHandle)
: mHandle(aHandle)
{ }
FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
#ifdef XP_WIN
: mHandle(aPickle)
#else
: mHandle(aPickle.fd)
#endif
{ }
// Performs platform-specific actions to duplicate mHandle in the other
// process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
// pickled value that can be passed to the other process via IPC.
PickleType
ShareTo(const IPDLPrivate&, ProcessHandle aOtherProcess) const;
// Tests mHandle against a well-known invalid platform-specific file handle
// (e.g. -1 on POSIX, INVALID_HANDLE_VALUE on Windows).
bool
IsValid() const;
PlatformHandleType
PlatformHandle() const
{
return mHandle;
}
bool
operator==(const FileDescriptor& aOther) const
{
return mHandle == aOther.mHandle;
}
private:
PlatformHandleType mHandle;
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_FileDescriptor_h

View File

@ -0,0 +1,44 @@
/* 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/. */
namespace mozilla {
namespace ipc {
struct StringInputStreamParams
{
nsCString data;
};
struct FileInputStreamParams
{
FileDescriptor file;
int32_t behaviorFlags;
int32_t ioFlags;
};
struct PartialFileInputStreamParams
{
FileInputStreamParams fileStreamParams;
uint64_t begin;
uint64_t length;
};
struct MultiplexInputStreamParams
{
InputStreamParams[] streams;
uint32_t currentStream;
nsresult status;
bool startedReadingCurrent;
};
union InputStreamParams
{
StringInputStreamParams;
FileInputStreamParams;
PartialFileInputStreamParams;
MultiplexInputStreamParams;
};
} // namespace ipc
} // namespace mozilla

View File

@ -0,0 +1,79 @@
/* 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/. */
#include "InputStreamUtils.h"
#include "nsIIPCSerializableInputStream.h"
#include "mozilla/Assertions.h"
#include "nsComponentManagerUtils.h"
#include "nsDebug.h"
#include "nsID.h"
#include "nsMultiplexInputStream.h"
#include "nsNetCID.h"
#include "nsStringStream.h"
#include "nsThreadUtils.h"
using namespace mozilla::ipc;
namespace {
NS_DEFINE_CID(kStringInputStreamCID, NS_STRINGINPUTSTREAM_CID);
NS_DEFINE_CID(kFileInputStreamCID, NS_LOCALFILEINPUTSTREAM_CID);
NS_DEFINE_CID(kPartialFileInputStreamCID, NS_PARTIALLOCALFILEINPUTSTREAM_CID);
NS_DEFINE_CID(kMultiplexInputStreamCID, NS_MULTIPLEXINPUTSTREAM_CID);
} // anonymous namespace
namespace mozilla {
namespace ipc {
already_AddRefed<nsIInputStream>
DeserializeInputStream(const InputStreamParams& aParams)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIIPCSerializableInputStream> serializable;
switch (aParams.type()) {
case InputStreamParams::T__None:
NS_WARNING("This union has no type!");
return nullptr;
case InputStreamParams::TStringInputStreamParams:
serializable = do_CreateInstance(kStringInputStreamCID);
break;
case InputStreamParams::TFileInputStreamParams:
serializable = do_CreateInstance(kFileInputStreamCID);
break;
case InputStreamParams::TPartialFileInputStreamParams:
serializable = do_CreateInstance(kPartialFileInputStreamCID);
break;
case InputStreamParams::TMultiplexInputStreamParams:
serializable = do_CreateInstance(kMultiplexInputStreamCID);
break;
default:
NS_WARNING("Unknown params!");
return nullptr;
}
MOZ_ASSERT(serializable);
if (!serializable->Deserialize(aParams)) {
NS_WARNING("Deserialize failed!");
return nullptr;
}
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(serializable);
MOZ_ASSERT(stream);
return stream.forget();
}
} // namespace ipc
} // namespace mozilla

View File

@ -0,0 +1,21 @@
/* 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 mozilla_ipc_InputStreamUtils_h
#define mozilla_ipc_InputStreamUtils_h
#include "mozilla/ipc/IPCSerializableParams.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace ipc {
already_AddRefed<nsIInputStream>
DeserializeInputStream(const InputStreamParams& aParams);
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_InputStreamUtils_h

View File

@ -25,7 +25,9 @@ EXPORTS_mozilla/ipc = \
AsyncChannel.h \
BrowserProcessSubThread.h \
CrossProcessMutex.h \
FileDescriptor.h \
GeckoChildProcessHost.h \
InputStreamUtils.h \
IOThreadChild.h \
ProcessChild.h \
ProtocolUtils.h \
@ -40,6 +42,8 @@ EXPORTS_mozilla/ipc = \
Transport.h \
$(NULL)
EXPORTS = nsIIPCSerializableInputStream.h
ifeq ($(OS_ARCH),WINNT) #{
EXPORTS_mozilla/ipc += \
Transport_win.h \
@ -63,7 +67,9 @@ endif #}
CPPSRCS += \
AsyncChannel.cpp \
BrowserProcessSubThread.cpp \
FileDescriptor.cpp \
GeckoChildProcessHost.cpp \
InputStreamUtils.cpp \
MessagePump.cpp \
ProcessChild.cpp \
ProtocolUtils.cpp \

View File

@ -15,6 +15,7 @@
#include "prenv.h"
#include "IPCMessageStart.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ipc/Transport.h"

5
ipc/glue/ipdl.mk Normal file
View File

@ -0,0 +1,5 @@
# 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/.
IPDLSRCS = IPCSerializableParams.ipdlh

View File

@ -0,0 +1,57 @@
/* 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 mozilla_ipc_nsIIPCSerializableInputStream_h
#define mozilla_ipc_nsIIPCSerializableInputStream_h
#include "nsISupports.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace ipc {
class InputStreamParams;
}
}
#define NS_IIPCSERIALIZABLEINPUTSTREAM_IID \
{0x1f56a3f8, 0xc413, 0x4274, {0x88, 0xe6, 0x68, 0x50, 0x9d, 0xf8, 0x85, 0x2d}}
class NS_NO_VTABLE nsIIPCSerializableInputStream : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IIPCSERIALIZABLEINPUTSTREAM_IID)
virtual void
Serialize(mozilla::ipc::InputStreamParams& aParams) = 0;
virtual bool
Deserialize(const mozilla::ipc::InputStreamParams& aParams) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCSerializableInputStream,
NS_IIPCSERIALIZABLEINPUTSTREAM_IID)
#define NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM \
virtual void \
Serialize(mozilla::ipc::InputStreamParams&) MOZ_OVERRIDE; \
virtual bool \
Deserialize(const mozilla::ipc::InputStreamParams&) MOZ_OVERRIDE;
#define NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(_to) \
virtual void \
Serialize(mozilla::ipc::InputStreamParams& aParams) MOZ_OVERRIDE \
{ _to Serialize(aParams); } \
virtual bool \
Deserialize(const mozilla::ipc::InputStreamParams& aParams) MOZ_OVERRIDE \
{ return _to Deserialize(aParams); }
#define NS_FORWARD_SAFE_NSIIPCSERIALIZABLEINPUTSTREAM(_to) \
virtual void \
Serialize(mozilla::ipc::InputStreamParams& aParams) MOZ_OVERRIDE \
{ if (_to) { _to->Serialize(aParams); } } \
virtual bool \
Deserialize(const mozilla::ipc::InputStreamParams& aParams) MOZ_OVERRIDE \
{ if (_to) { return _to->Deserialize(aParams); } return false; }
#endif // mozilla_ipc_nsIIPCSerializableInputStream_h

View File

@ -32,6 +32,7 @@ IPDLDIRS = \
dom/src/storage \
gfx/layers/ipc \
hal/sandbox \
ipc/glue \
ipc/testshell \
js/ipc \
layout/ipc \

View File

@ -48,6 +48,7 @@ Types = (
'nsString',
'nsCString',
'mozilla::ipc::Shmem',
'mozilla::ipc::FileDescriptor',
# quasi-stdint types used by "public" Gecko headers
'int8',

View File

@ -233,7 +233,6 @@ def _shmemRevokeRights(shmemexpr):
def _lookupShmem(idexpr):
return ExprCall(ExprVar('LookupSharedMemory'), args=[ idexpr ])
def _makeForwardDeclForQClass(clsname, quals):
fd = ForwardDecl(clsname, cls=1)
if 0 == len(quals):
@ -492,6 +491,9 @@ class _ConvertToCxxType(TypeVisitor):
def visitShmemType(self, s):
return Type(self.typename(s))
def visitFDType(self, s):
return Type(self.typename(s))
def visitProtocolType(self, p): assert 0
def visitMessageType(self, m): assert 0
def visitVoidType(self, v): assert 0
@ -668,6 +670,8 @@ class _StructField(_CompoundTypeComponent):
refexpr = self.refExpr(thisexpr)
if 'Shmem' == self.ipdltype.name():
refexpr = ExprCast(refexpr, Type('Shmem', ref=1), const=1)
if 'FileDescriptor' == self.ipdltype.name():
refexpr = ExprCast(refexpr, Type('FileDescriptor', ref=1), const=1)
return refexpr
def argVar(self):
@ -826,6 +830,8 @@ IPDL union type."""
# sigh
if 'Shmem' == self.ipdltype.name():
v = ExprCast(v, Type('Shmem', ref=1), const=1)
if 'FileDescriptor' == self.ipdltype.name():
v = ExprCast(v, Type('FileDescriptor', ref=1), const=1)
return v
##--------------------------------------------------
@ -990,7 +996,6 @@ def _subtreeUsesShmem(p):
return True
return False
class Protocol(ipdl.ast.Protocol):
def cxxTypedefs(self):
return self.decl.cxxtypedefs
@ -1867,6 +1872,11 @@ stmt. Some types generate both kinds.'''
self.visited.add(s)
self.maybeTypedef('mozilla::ipc::Shmem', 'Shmem')
def visitFDType(self, s):
if s in self.visited: return
self.visited.add(s)
self.maybeTypedef('mozilla::ipc::FileDescriptor', 'FileDescriptor')
def visitVoidType(self, v): assert 0
def visitMessageType(self, v): assert 0
def visitProtocolType(self, v): assert 0
@ -3379,11 +3389,11 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
p = self.protocol
routedvar = ExprVar('aRouted')
idvar = ExprVar('aId')
shmemvar = ExprVar('aShmem')
shmemvar = ExprVar('shmem')
rawvar = ExprVar('segment')
sizevar = ExprVar('aSize')
typevar = ExprVar('type')
unsafevar = ExprVar('unsafe')
typevar = ExprVar('aType')
unsafevar = ExprVar('aUnsafe')
listenertype = Type('ChannelListener', ptr=1)
register = MethodDefn(MethodDecl(
@ -3978,8 +3988,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
# pickling for IPDL types
specialtypes = set()
class findSpecialTypes(TypeVisitor):
def visitActorType(self, a): specialtypes.add(a)
def visitShmemType(self, s): specialtypes.add(s)
def visitActorType(self, a): specialtypes.add(a)
def visitShmemType(self, s): specialtypes.add(s)
def visitFDType(self, s): specialtypes.add(s)
def visitStructType(self, s):
specialtypes.add(s)
return TypeVisitor.visitStructType(self, s)
@ -4006,6 +4017,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
if t.isActor(): self.implementActorPickling(t)
elif t.isArray(): self.implementSpecialArrayPickling(t)
elif t.isShmem(): self.implementShmemPickling(t)
elif t.isFD(): self.implementFDPickling(t)
elif t.isStruct(): self.implementStructPickling(t)
elif t.isUnion(): self.implementUnionPickling(t)
else:
@ -4225,6 +4237,57 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
self.cls.addstmts([ write, Whitespace.NL, read, Whitespace.NL ])
def implementFDPickling(self, fdtype):
msgvar = self.msgvar
itervar = self.itervar
var = self.var
tmpvar = ExprVar('fd')
picklevar = ExprVar('pfd')
intype = _cxxConstRefType(fdtype, self.side)
outtype = _cxxPtrToType(fdtype, self.side)
def _fdType():
return Type('FileDescriptor')
def _fdPickleType():
return Type('FileDescriptor::PickleType')
def _fdBackstagePass():
return ExprCall(ExprVar('FileDescriptor::IPDLPrivate'))
write = MethodDefn(self.writeMethodDecl(intype, var))
write.addstmts([
StmtDecl(Decl(_fdPickleType(), picklevar.name),
init=ExprCall(ExprSelect(var, '.', 'ShareTo'),
args=[ _fdBackstagePass(),
self.protocol.callOtherProcess() ])),
StmtExpr(ExprCall(ExprVar('IPC::WriteParam'),
args=[ msgvar, picklevar ])),
])
read = MethodDefn(self.readMethodDecl(outtype, var))
ifread = StmtIf(ExprNot(ExprCall(ExprVar('IPC::ReadParam'),
args=[ msgvar, itervar,
ExprAddrOf(picklevar) ])))
ifread.addifstmt(StmtReturn.FALSE)
ifnvalid = StmtIf(ExprNot(ExprCall(ExprSelect(tmpvar, '.', 'IsValid'))))
ifnvalid.addifstmt(StmtReturn.FALSE)
read.addstmts([
StmtDecl(Decl(_fdPickleType(), picklevar.name)),
ifread,
Whitespace.NL,
StmtDecl(Decl(_fdType(), tmpvar.name),
init=ExprCall(ExprVar('FileDescriptor'),
args=[ _fdBackstagePass(), picklevar ])),
ifnvalid,
Whitespace.NL,
StmtExpr(ExprAssn(ExprDeref(var), tmpvar)),
StmtReturn.TRUE
])
self.cls.addstmts([ write, Whitespace.NL, read, Whitespace.NL ])
def implementStructPickling(self, structtype):
msgvar = self.msgvar

View File

@ -89,6 +89,9 @@ class TypeVisitor:
def visitShmemChmodType(self, c, *args):
c.shmem.accept(self)
def visitFDType(self, s, *args):
pass
class Type:
def __cmp__(self, o):
@ -196,6 +199,7 @@ class IPDLType(Type):
def isCompound(self): return False
def isShmem(self): return False
def isChmod(self): return False
def isFD(self): return False
def isAsync(self): return self.sendSemantics is ASYNC
def isSync(self): return self.sendSemantics is SYNC
@ -417,6 +421,16 @@ class ShmemType(IPDLType):
def fullname(self):
return str(self.qname)
class FDType(IPDLType):
def __init__(self, qname):
self.qname = qname
def isFD(self): return True
def name(self):
return self.qname.baseid
def fullname(self):
return str(self.qname)
def iteractortypes(t, visited=None):
"""Iterate over any actor(s) buried in |type|."""
if visited is None:
@ -452,6 +466,17 @@ def hasshmem(type):
return True
return False
def hasfd(type):
"""Return true iff |type| is fd or has it buried within."""
class found: pass
class findFD(TypeVisitor):
def visitFDType(self, s): raise found()
try:
type.accept(findFD())
except found:
return True
return False
##--------------------
_builtinloc = Loc('<builtin>', 0)
def makeBuiltinUsing(tname):
@ -775,6 +800,8 @@ class GatherDecls(TcheckVisitor):
fullname = None
if fullname == 'mozilla::ipc::Shmem':
ipdltype = ShmemType(using.type.spec)
elif fullname == 'mozilla::ipc::FileDescriptor':
ipdltype = FDType(using.type.spec)
else:
ipdltype = ImportedCxxType(using.type.spec)
using.decl = self.declare(

View File

@ -52,7 +52,7 @@ XPIDLSRCS = \
nsIInputStreamPump.idl \
nsIInputStreamChannel.idl \
nsIIOService2.idl \
nsIIPCSerializable.idl \
nsIIPCSerializableObsolete.idl \
nsIMIMEInputStream.idl \
nsINetAddr.idl \
nsINetworkLinkService.idl \

View File

@ -17,7 +17,7 @@ class Message;
[ptr] native Iterator(void*);
[noscript, uuid(1f605ac7-666b-471f-9864-1a21a95f11c4)]
interface nsIIPCSerializable : nsISupports
interface nsIIPCSerializableObsolete : nsISupports
{
[notxpcom] boolean read(in ConstMessage msg, in Iterator iter);
[notxpcom] void write(in Message msg);

View File

@ -252,7 +252,7 @@ NS_INTERFACE_MAP_BEGIN(nsBufferedInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIBufferedInputStream)
NS_INTERFACE_MAP_ENTRY(nsIStreamBufferAccess)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableObsolete)
NS_IMPL_QUERY_CLASSINFO(nsBufferedInputStream)
NS_INTERFACE_MAP_END_INHERITING(nsBufferedStream)
@ -261,7 +261,7 @@ NS_IMPL_CI_INTERFACE_GETTER5(nsBufferedInputStream,
nsIBufferedInputStream,
nsISeekableStream,
nsIStreamBufferAccess,
nsIIPCSerializable)
nsIIPCSerializableObsolete)
nsresult
nsBufferedInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)

View File

@ -13,7 +13,7 @@
#include "nsISeekableStream.h"
#include "nsIStreamBufferAccess.h"
#include "nsCOMPtr.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
////////////////////////////////////////////////////////////////////////////////
@ -60,14 +60,14 @@ protected:
class nsBufferedInputStream : public nsBufferedStream,
public nsIBufferedInputStream,
public nsIStreamBufferAccess,
public nsIIPCSerializable
public nsIIPCSerializableObsolete
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIBUFFEREDINPUTSTREAM
NS_DECL_NSISTREAMBUFFERACCESS
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
nsBufferedInputStream() : nsBufferedStream() {}
virtual ~nsBufferedInputStream() {}

View File

@ -28,9 +28,14 @@
#include "nsReadLine.h"
#include "nsNetUtil.h"
#include "nsIClassInfoImpl.h"
#include "mozilla/ipc/IPCSerializableParams.h"
#define NS_NO_INPUT_BUFFERING 1 // see http://bugzilla.mozilla.org/show_bug.cgi?id=41067
typedef mozilla::ipc::FileDescriptor::PlatformHandleType FileHandleType;
using namespace mozilla::ipc;
////////////////////////////////////////////////////////////////////////////////
// nsFileStreamBase
@ -286,12 +291,16 @@ nsFileStreamBase::CleanUpOpen()
nsresult
nsFileStreamBase::DoOpen()
{
NS_PRECONDITION(mOpenParams.localFile, "Must have a file to open");
NS_ASSERTION(!mFD, "Already have a file descriptor!");
NS_ASSERTION(mOpenParams.localFile, "Must have a file to open");
PRFileDesc* fd;
nsresult rv = mOpenParams.localFile->OpenNSPRFileDesc(mOpenParams.ioFlags, mOpenParams.perm, &fd);
nsresult rv = mOpenParams.localFile->OpenNSPRFileDesc(mOpenParams.ioFlags,
mOpenParams.perm,
&fd);
CleanUpOpen();
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return rv;
mFD = fd;
return NS_OK;
@ -320,16 +329,16 @@ NS_INTERFACE_MAP_BEGIN(nsFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsILineInputStream)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableObsolete)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
NS_IMPL_QUERY_CLASSINFO(nsFileInputStream)
NS_INTERFACE_MAP_END_INHERITING(nsFileStreamBase)
NS_IMPL_CI_INTERFACE_GETTER5(nsFileInputStream,
NS_IMPL_CI_INTERFACE_GETTER4(nsFileInputStream,
nsIInputStream,
nsIFileInputStream,
nsISeekableStream,
nsILineInputStream,
nsIIPCSerializable)
nsILineInputStream)
nsresult
nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
@ -505,6 +514,76 @@ nsFileInputStream::Write(IPC::Message *aMsg)
WriteParam(aMsg, mBehaviorFlags);
}
void
nsFileInputStream::Serialize(InputStreamParams& aParams)
{
FileInputStreamParams params;
if (mFD) {
FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFD));
NS_ASSERTION(fd, "This should never be null!");
params.file() = FileDescriptor(fd);
NS_ASSERTION(params.file().IsValid(),
"Sending an invalid file descriptor!");
} else {
NS_WARNING("This file has not been opened (or could not be opened). "
"Sending an invalid file descriptor to the other process!");
}
PRInt32 behaviorFlags = mBehaviorFlags;
// The other process shouldn't close when it reads the end because it will
// not be able to reopen the file later.
behaviorFlags &= ~nsIFileInputStream::CLOSE_ON_EOF;
// The other process will not be able to reopen the file so transferring
// this flag is meaningless.
behaviorFlags &= ~nsIFileInputStream::REOPEN_ON_REWIND;
// The other process is going to have an open file descriptor automatically
// so transferring this flag is meaningless.
behaviorFlags &= ~nsIFileInputStream::DEFER_OPEN;
params.behaviorFlags() = behaviorFlags;
params.ioFlags() = mIOFlags;
aParams = params;
}
bool
nsFileInputStream::Deserialize(const InputStreamParams& aParams)
{
NS_ASSERTION(!mFD, "Already have a file descriptor?!");
NS_ASSERTION(!mDeferredOpen, "Deferring open?!");
NS_ASSERTION(!mFile, "Should never have a file here!");
NS_ASSERTION(!mPerm, "This should always be 0!");
if (aParams.type() != InputStreamParams::TFileInputStreamParams) {
NS_WARNING("Received unknown parameters from the other process!");
return false;
}
const FileInputStreamParams& params = aParams.get_FileInputStreamParams();
const FileDescriptor& fd = params.file();
NS_WARN_IF_FALSE(fd.IsValid(), "Received an invalid file descriptor!");
if (fd.IsValid()) {
PRFileDesc* fileDesc = PR_ImportFile(PROsfd(fd.PlatformHandle()));
if (!fileDesc) {
NS_WARNING("Failed to import file handle!");
return false;
}
mFD = fileDesc;
}
mBehaviorFlags = params.behaviorFlags();
mIOFlags = params.ioFlags();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// nsPartialFileInputStream
@ -520,16 +599,16 @@ NS_INTERFACE_MAP_BEGIN(nsPartialFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIPartialFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsILineInputStream)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableObsolete)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
NS_IMPL_QUERY_CLASSINFO(nsPartialFileInputStream)
NS_INTERFACE_MAP_END_INHERITING(nsFileStreamBase)
NS_IMPL_CI_INTERFACE_GETTER5(nsPartialFileInputStream,
NS_IMPL_CI_INTERFACE_GETTER4(nsPartialFileInputStream,
nsIInputStream,
nsIPartialFileInputStream,
nsISeekableStream,
nsILineInputStream,
nsIIPCSerializable)
nsILineInputStream)
nsresult
nsPartialFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID,
@ -680,6 +759,64 @@ nsPartialFileInputStream::Write(IPC::Message *aMsg)
nsFileInputStream::Write(aMsg);
}
void
nsPartialFileInputStream::Serialize(InputStreamParams& aParams)
{
// Serialize the base class first.
InputStreamParams fileParams;
nsFileInputStream::Serialize(fileParams);
if (fileParams.type() != InputStreamParams::TFileInputStreamParams) {
NS_ERROR("Base class serialize failed!");
return;
}
PartialFileInputStreamParams params;
params.fileStreamParams() = fileParams.get_FileInputStreamParams();
params.begin() = mStart;
params.length() = mLength;
aParams = params;
}
bool
nsPartialFileInputStream::Deserialize(const InputStreamParams& aParams)
{
NS_ASSERTION(!mFD, "Already have a file descriptor?!");
NS_ASSERTION(!mStart, "Already have a start?!");
NS_ASSERTION(!mLength, "Already have a length?!");
NS_ASSERTION(!mPosition, "Already have a position?!");
if (aParams.type() != InputStreamParams::TPartialFileInputStreamParams) {
NS_ERROR("Received unknown parameters from the other process!");
return false;
}
const PartialFileInputStreamParams& params =
aParams.get_PartialFileInputStreamParams();
// Deserialize the base class first.
InputStreamParams fileParams(params.fileStreamParams());
if (!nsFileInputStream::Deserialize(fileParams)) {
NS_ERROR("Base class deserialize failed!");
return false;
}
NS_ASSERTION(mFD, "Must have a file descriptor now!");
mStart = params.begin();
mLength = params.length();
mPosition = 0;
if (!mStart) {
return true;
}
// XXX This is so broken. Main thread IO alert.
return NS_SUCCEEDED(nsFileInputStream::Seek(NS_SEEK_SET, mStart));
}
////////////////////////////////////////////////////////////////////////////////
// nsFileOutputStream

View File

@ -17,7 +17,8 @@
#include "nsCOMPtr.h"
#include "prlog.h"
#include "prio.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIIPCSerializableObsolete.h"
template<class CharType> class nsLineBuffer;
@ -102,13 +103,15 @@ protected:
class nsFileInputStream : public nsFileStreamBase,
public nsIFileInputStream,
public nsILineInputStream,
public nsIIPCSerializable
public nsIIPCSerializableObsolete,
public nsIIPCSerializableInputStream
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIFILEINPUTSTREAM
NS_DECL_NSILINEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_IMETHOD Close();
NS_IMETHOD Available(PRUint64* _retval)
@ -131,9 +134,11 @@ public:
NS_IMETHOD Seek(PRInt32 aWhence, PRInt64 aOffset);
nsFileInputStream()
: mIOFlags(0), mPerm(0)
{
mLineBuffer = nullptr;
}
virtual ~nsFileInputStream()
{
Close();
@ -179,7 +184,12 @@ public:
using nsFileInputStream::Init;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPARTIALFILEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
nsPartialFileInputStream()
: mStart(0), mLength(0), mPosition(0)
{ }
NS_IMETHOD Tell(PRInt64 *aResult);
NS_IMETHOD Available(PRUint64 *aResult);

View File

@ -19,12 +19,12 @@
#include "nsIStringStream.h"
#include "nsString.h"
#include "nsMIMEInputStream.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsIClassInfoImpl.h"
class nsMIMEInputStream : public nsIMIMEInputStream,
public nsISeekableStream,
public nsIIPCSerializable
public nsIIPCSerializableObsolete
{
public:
nsMIMEInputStream();
@ -34,7 +34,7 @@ public:
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMIMEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_METHOD Init();
@ -73,12 +73,12 @@ NS_IMPL_QUERY_INTERFACE4_CI(nsMIMEInputStream,
nsIMIMEInputStream,
nsIInputStream,
nsISeekableStream,
nsIIPCSerializable)
nsIIPCSerializableObsolete)
NS_IMPL_CI_INTERFACE_GETTER4(nsMIMEInputStream,
nsIMIMEInputStream,
nsIInputStream,
nsISeekableStream,
nsIIPCSerializable)
nsIIPCSerializableObsolete)
nsMIMEInputStream::nsMIMEInputStream() : mAddContentLength(false),
mStartedReading(false)

View File

@ -55,7 +55,7 @@ nsSimpleNestedURI::Write(nsIObjectOutputStream* aStream)
return rv;
}
// nsIIPCSerializable
// nsIIPCSerializableObsolete
bool
nsSimpleNestedURI::Read(const IPC::Message *aMsg, void **aIter)

View File

@ -36,7 +36,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSINESTEDURI
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
// Overrides for various methods nsSimpleURI implements follow.

View File

@ -41,7 +41,8 @@ nsSimpleURI::~nsSimpleURI()
NS_IMPL_ADDREF(nsSimpleURI)
NS_IMPL_RELEASE(nsSimpleURI)
NS_INTERFACE_TABLE_HEAD(nsSimpleURI)
NS_INTERFACE_TABLE5(nsSimpleURI, nsIURI, nsISerializable, nsIIPCSerializable, nsIClassInfo, nsIMutable)
NS_INTERFACE_TABLE5(nsSimpleURI, nsIURI, nsISerializable,
nsIIPCSerializableObsolete, nsIClassInfo, nsIMutable)
NS_INTERFACE_TABLE_TO_MAP_SEGUE
if (aIID.Equals(kThisSimpleURIImplementationCID))
foundInterface = static_cast<nsIURI*>(this);
@ -117,7 +118,7 @@ nsSimpleURI::Write(nsIObjectOutputStream* aStream)
}
////////////////////////////////////////////////////////////////////////////////
// nsIIPCSerializable methods:
// nsIIPCSerializableObsolete methods:
bool
nsSimpleURI::Read(const IPC::Message *aMsg, void **aIter)

View File

@ -9,7 +9,7 @@
#include "nsIURL.h"
#include "nsAgg.h"
#include "nsISerializable.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsString.h"
#include "nsIClassInfo.h"
#include "nsIMutable.h"
@ -25,7 +25,7 @@
class nsSimpleURI : public nsIURI,
public nsISerializable,
public nsIIPCSerializable,
public nsIIPCSerializableObsolete,
public nsIClassInfo,
public nsIMutable,
public nsISizeOf
@ -34,7 +34,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURI
NS_DECL_NSISERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSICLASSINFO
NS_DECL_NSIMUTABLE

View File

@ -937,7 +937,7 @@ NS_INTERFACE_MAP_BEGIN(nsStandardURL)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileURL, mSupportsFileURL)
NS_INTERFACE_MAP_ENTRY(nsIStandardURL)
NS_INTERFACE_MAP_ENTRY(nsISerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableObsolete)
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
// see nsStandardURL::Equals
@ -2876,7 +2876,7 @@ nsStandardURL::Write(nsIObjectOutputStream *stream)
}
//---------------------------------------------------------------------------
// nsStandardURL::nsIIPCSerializable
// nsStandardURL::nsIIPCSerializableObsolete
//---------------------------------------------------------------------------
bool

View File

@ -10,7 +10,7 @@
#include "nsDependentString.h"
#include "nsDependentSubstring.h"
#include "nsISerializable.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsIFileURL.h"
#include "nsIStandardURL.h"
#include "nsIFile.h"
@ -42,7 +42,7 @@ class nsIPrefBranch;
class nsStandardURL : public nsIFileURL
, public nsIStandardURL
, public nsISerializable
, public nsIIPCSerializable
, public nsIIPCSerializableObsolete
, public nsIClassInfo
, public nsISizeOf
{
@ -53,7 +53,7 @@ public:
NS_DECL_NSIFILEURL
NS_DECL_NSISTANDARDURL
NS_DECL_NSISERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSICLASSINFO
NS_DECL_NSIMUTABLE

View File

@ -9,7 +9,7 @@
#include "IPC/IPCMessageUtils.h"
#include "nsStringGlue.h"
#include "nsIURI.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsIClassInfo.h"
#include "nsComponentManagerUtils.h"
#include "nsNetUtil.h"
@ -51,7 +51,8 @@ struct ParamTraits<URI>
if (isNull)
return;
nsCOMPtr<nsIIPCSerializable> serializable = do_QueryInterface(aParam.mURI);
nsCOMPtr<nsIIPCSerializableObsolete> serializable =
do_QueryInterface(aParam.mURI);
if (!serializable) {
nsCString scheme;
aParam.mURI->GetScheme(scheme);
@ -120,7 +121,7 @@ struct ParamTraits<URI>
nsCOMPtr<nsIURI> uri = do_CreateInstance(cid);
if (!uri)
return false;
nsCOMPtr<nsIIPCSerializable> serializable = do_QueryInterface(uri);
nsCOMPtr<nsIIPCSerializableObsolete> serializable = do_QueryInterface(uri);
if (!serializable || !serializable->Read(aMsg, aIter))
return false;
@ -170,12 +171,14 @@ struct ParamTraits<InputStream>
if (isNull)
return;
nsCOMPtr<nsIIPCSerializable> serializable = do_QueryInterface(aParam.mStream);
nsCOMPtr<nsIIPCSerializableObsolete> serializable =
do_QueryInterface(aParam.mStream);
bool isSerializable = !!serializable;
WriteParam(aMsg, isSerializable);
if (!serializable) {
NS_WARNING("nsIInputStream implementation doesn't support nsIIPCSerializable; falling back to copying data");
NS_WARNING("nsIInputStream implementation doesn't support "
"nsIIPCSerializableObsolete; falling back to copying data");
nsCString streamString;
PRUint64 bytes;
@ -241,7 +244,8 @@ struct ParamTraits<InputStream>
stream = do_CreateInstance(cid);
if (!stream)
return false;
nsCOMPtr<nsIIPCSerializable> serializable = do_QueryInterface(stream);
nsCOMPtr<nsIIPCSerializableObsolete> serializable =
do_QueryInterface(stream);
if (!serializable || !serializable->Read(aMsg, aIter))
return false;
}

View File

@ -292,7 +292,7 @@ nsNestedAboutURI::Write(nsIObjectOutputStream* aStream)
return NS_OK;
}
// nsIIPCSerializable
// nsIIPCSerializableObsolete
bool
nsNestedAboutURI::Read(const IPC::Message *aMsg, void **aIter)
{

View File

@ -45,7 +45,7 @@ private:
// Class to allow us to propagate the base URI to about:blank correctly
class nsNestedAboutURI : public nsSimpleNestedURI {
public:
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
nsNestedAboutURI(nsIURI* aInnerURI, nsIURI* aBaseURI)
: nsSimpleNestedURI(aInnerURI)

View File

@ -15,7 +15,6 @@
#include "nsHttpHeaderArray.h"
#include "nsHttpResponseHead.h"
#include "nsIIPCSerializable.h"
#include "nsIClassInfo.h"
#include "nsNetUtil.h"

View File

@ -17,12 +17,18 @@
#include "nsISeekableStream.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "nsIClassInfoImpl.h"
#include "nsIIPCSerializableInputStream.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/IPCSerializableParams.h"
using namespace mozilla::ipc;
class nsMultiplexInputStream MOZ_FINAL : public nsIMultiplexInputStream,
public nsISeekableStream,
public nsIIPCSerializable
public nsIIPCSerializableObsolete,
public nsIIPCSerializableInputStream
{
public:
nsMultiplexInputStream();
@ -31,7 +37,8 @@ public:
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMULTIPLEXINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
private:
~nsMultiplexInputStream() {}
@ -60,16 +67,16 @@ NS_IMPL_THREADSAFE_RELEASE(nsMultiplexInputStream)
NS_IMPL_CLASSINFO(nsMultiplexInputStream, NULL, nsIClassInfo::THREADSAFE,
NS_MULTIPLEXINPUTSTREAM_CID)
NS_IMPL_QUERY_INTERFACE4_CI(nsMultiplexInputStream,
NS_IMPL_QUERY_INTERFACE5_CI(nsMultiplexInputStream,
nsIMultiplexInputStream,
nsIInputStream,
nsISeekableStream,
nsIIPCSerializable)
NS_IMPL_CI_INTERFACE_GETTER4(nsMultiplexInputStream,
nsIIPCSerializableObsolete,
nsIIPCSerializableInputStream)
NS_IMPL_CI_INTERFACE_GETTER3(nsMultiplexInputStream,
nsIMultiplexInputStream,
nsIInputStream,
nsISeekableStream,
nsIIPCSerializable)
nsISeekableStream)
nsMultiplexInputStream::nsMultiplexInputStream()
: mCurrentStream(0),
@ -447,3 +454,75 @@ nsMultiplexInputStream::Write(IPC::Message *aMsg)
WriteParam(aMsg, mStartedReadingCurrent);
WriteParam(aMsg, mStatus);
}
void
nsMultiplexInputStream::Serialize(InputStreamParams& aParams)
{
MultiplexInputStreamParams params;
PRUint32 streamCount = mStreams.Count();
if (streamCount) {
InfallibleTArray<InputStreamParams>& streams = params.streams();
streams.SetCapacity(streamCount);
for (PRUint32 index = 0; index < streamCount; index++) {
nsCOMPtr<nsIIPCSerializableInputStream> serializable =
do_QueryInterface(mStreams.ObjectAt(index));
NS_ASSERTION(serializable, "Child stream isn't serializable!");
if (serializable) {
InputStreamParams childStreamParams;
serializable->Serialize(childStreamParams);
NS_ASSERTION(childStreamParams.type() !=
InputStreamParams::T__None,
"Serialize failed!");
streams.AppendElement(childStreamParams);
}
}
}
params.currentStream() = mCurrentStream;
params.status() = mStatus;
params.startedReadingCurrent() = mStartedReadingCurrent;
aParams = params;
}
bool
nsMultiplexInputStream::Deserialize(const InputStreamParams& aParams)
{
if (aParams.type() !=
InputStreamParams::TMultiplexInputStreamParams) {
NS_ERROR("Received unknown parameters from the other process!");
return false;
}
const MultiplexInputStreamParams& params =
aParams.get_MultiplexInputStreamParams();
const InfallibleTArray<InputStreamParams>& streams = params.streams();
PRUint32 streamCount = streams.Length();
for (PRUint32 index = 0; index < streamCount; index++) {
nsCOMPtr<nsIInputStream> stream =
DeserializeInputStream(streams[index]);
if (!stream) {
NS_WARNING("Deserialize failed!");
return false;
}
if (NS_FAILED(AppendStream(stream))) {
NS_WARNING("AppendStream failed!");
return false;
}
}
mCurrentStream = params.currentStream();
mStatus = params.status();
mStartedReadingCurrent = params.startedReadingCurrent();
return true;
}

View File

@ -19,8 +19,12 @@
#include "prerror.h"
#include "plstr.h"
#include "nsIClassInfoImpl.h"
#include "nsIIPCSerializable.h"
#include "nsIIPCSerializableObsolete.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/IPCSerializableParams.h"
#include "nsIIPCSerializableInputStream.h"
using namespace mozilla::ipc;
//-----------------------------------------------------------------------------
// nsIStringInputStream implementation
@ -29,7 +33,8 @@
class nsStringInputStream MOZ_FINAL : public nsIStringInputStream
, public nsISeekableStream
, public nsISupportsCString
, public nsIIPCSerializable
, public nsIIPCSerializableObsolete
, public nsIIPCSerializableInputStream
{
public:
NS_DECL_ISUPPORTS
@ -38,7 +43,8 @@ public:
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSISUPPORTSPRIMITIVE
NS_DECL_NSISUPPORTSCSTRING
NS_DECL_NSIIPCSERIALIZABLE
NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
nsStringInputStream()
{
@ -80,18 +86,18 @@ NS_IMPL_THREADSAFE_RELEASE(nsStringInputStream)
NS_IMPL_CLASSINFO(nsStringInputStream, NULL, nsIClassInfo::THREADSAFE,
NS_STRINGINPUTSTREAM_CID)
NS_IMPL_QUERY_INTERFACE5_CI(nsStringInputStream,
NS_IMPL_QUERY_INTERFACE6_CI(nsStringInputStream,
nsIStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
nsIIPCSerializable)
NS_IMPL_CI_INTERFACE_GETTER5(nsStringInputStream,
nsIIPCSerializableObsolete,
nsIIPCSerializableInputStream)
NS_IMPL_CI_INTERFACE_GETTER4(nsStringInputStream,
nsIStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
nsIIPCSerializable)
nsISeekableStream)
/////////
// nsISupportsCString implementation
@ -288,7 +294,7 @@ nsStringInputStream::SetEOF()
}
/////////
// nsIIPCSerializable implementation
// nsIIPCSerializableObsolete implementation
/////////
bool
@ -316,6 +322,33 @@ nsStringInputStream::Write(IPC::Message *aMsg)
WriteParam(aMsg, static_cast<const nsCString&>(PromiseFlatCString(mData)));
}
void
nsStringInputStream::Serialize(InputStreamParams& aParams)
{
StringInputStreamParams params;
params.data() = PromiseFlatCString(mData);
aParams = params;
}
bool
nsStringInputStream::Deserialize(const InputStreamParams& aParams)
{
if (aParams.type() != InputStreamParams::TStringInputStreamParams) {
NS_ERROR("Received unknown parameters from the other process!");
return false;
}
const StringInputStreamParams& params =
aParams.get_StringInputStreamParams();
if (NS_FAILED(SetData(params.data()))) {
NS_WARNING("SetData failed!");
return false;
}
return true;
}
nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead, PRInt32 aLength,