gecko-dev/ipc/glue/IPCStreamUtils.h

186 lines
6.0 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_IPCStreamUtils_h
#define mozilla_ipc_IPCStreamUtils_h
#include "mozilla/ipc/IPCStream.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace dom {
class nsIContentChild;
class PContentParent;
}
namespace ipc {
class PBackgroundChild;
class PBackgroundParent;
// Deserialize an IPCStream received from an actor call. These methods
// work in both the child and parent.
already_AddRefed<nsIInputStream>
DeserializeIPCStream(const IPCStream& aValue);
already_AddRefed<nsIInputStream>
DeserializeIPCStream(const OptionalIPCStream& aValue);
// RAII helper class that serializes an nsIInputStream into an IPCStream struct.
// Any file descriptor or PSendStream actors are automatically managed
// correctly.
//
// Here is a simple example:
//
// // in ipdl file
// Protocol PMyStuff
// {
// parent:
// async DoStuff(IPCStream aStream);
// child:
// async StuffDone(IPCStream aStream);
// };
//
// // in child c++ code
// void CallDoStuff(PMyStuffChild* aActor, nsIInputStream* aStream)
// {
// AutoIPCStream autoStream;
// autoStream.Serialize(aStream, aActor->Manager());
// aActor->SendDoStuff(autoStream.TakeValue());
// }
//
// // in parent c++ code
// bool
// MyStuffParent::RecvDoStuff(const IPCStream& aIPCStream) {
// nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aIPCStream);
// // Do something with stream...
//
// // You can also serialize streams from parent-to-child as long as
// // they don't require PSendStream actor support.
// AutoIPCStream anotherStream;
// anotherStream.Serialize(mFileStream, Manager());
// SendStuffDone(anotherStream.TakeValue());
// }
//
// The AutoIPCStream RAII class may also be used if your stream is embedded
// in a more complex IPDL structure. In this case you attach the AutoIPCStream
// to the embedded IPCStream and call TakeValue() after you pass the structure.
// For example:
//
// // in ipdl file
// struct Stuff
// {
// IPCStream stream;
// nsCString name;
// };
//
// Protocol PMyStuff
// {
// parent:
// async DoStuff(Stuff aStream);
// };
//
// // in child c++ code
// void CallDoStuff(PMyStuffChild* aActor, nsIInputStream* aStream)
// {
// Stuff stuff;
// AutoIPCStream autoStream(stuff.stream()); // attach to IPCStream here
// autoStream.Serialize(aStream, aActor->Manager());
// aActor->SendDoStuff(stuff);
// autoStream.TakeValue(); // call take value after send
// }
//
// // in parent c++ code
// bool
// MyStuffParent::RecvDoStuff(const Stuff& aStuff) {
// nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aStuff.stream());
// /* do something with the nsIInputStream */
// }
//
// The AutoIPCStream class also supports OptionalIPCStream values. As long as
// you did not initialize the object with a non-optional IPCStream, you can call
// TakeOptionalValue() instead.
//
// The AutoIPCStream class can also be used to serialize nsIInputStream objects
// on the parent side to send to the child. Currently, however, this only
// works for directly serializable stream types. The PSendStream actor mechanism
// is not supported in this direction yet.
//
// Like SerializeInputStream(), the AutoIPCStream will crash if
// serialization cannot be completed.
//
// NOTE: This is not a MOZ_STACK_CLASS so that it can be more easily integrated
// with complex ipdl structures. For example, you may want to create an
// array of RAII AutoIPCStream objects or build your own wrapping
// RAII object to handle other actors that need to be cleaned up.
class AutoIPCStream final
{
OptionalIPCStream mInlineValue;
IPCStream* mValue;
OptionalIPCStream* mOptionalValue;
bool mTaken;
bool
IsSet() const;
public:
// Implicitly create an OptionalIPCStream value. Either
// TakeValue() or TakeOptionalValue() can be used.
AutoIPCStream();
// Wrap an existing IPCStream. Only TakeValue() may be
// used. If a nullptr nsIInputStream is passed to SerializeOrSend() then
// a crash will be forced.
explicit AutoIPCStream(IPCStream& aTarget);
// Wrap an existing OptionalIPCStream. Either TakeValue()
// or TakeOptionalValue can be used.
explicit AutoIPCStream(OptionalIPCStream& aTarget);
~AutoIPCStream();
// Serialize the input stream or create a SendStream actor using the PContent
// manager. If neither of these succeed, then crash. This should only be
// used on the main thread.
void
Serialize(nsIInputStream* aStream, dom::nsIContentChild* aManager);
// Serialize the input stream or create a SendStream actor using the
// PBackground manager. If neither of these succeed, then crash. This can
// be called on the main thread or Worker threads.
void
Serialize(nsIInputStream* aStream, PBackgroundChild* aManager);
// Serialize the input stream. A PSendStream cannot be used when going
// from parent-to-child.
void
Serialize(nsIInputStream* aStream, dom::PContentParent* aManager);
// Serialize the input stream. A PSendStream cannot be used when going
// from parent-to-child.
void
Serialize(nsIInputStream* aStream, PBackgroundParent* aManager);
// Get the IPCStream as a non-optional value. This will
// assert if a stream has not been serialized or if it has already been taken.
// This should only be called if the value is being, or has already been, sent
// to the parent
IPCStream&
TakeValue();
// Get the OptionalIPCStream value. This will assert if
// the value has already been taken. This should only be called if the value
// is being, or has already been, sent to the parent
OptionalIPCStream&
TakeOptionalValue();
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_IPCStreamUtils_h