diff options
Diffstat (limited to 'ipc/glue/IPCStreamUtils.h')
-rw-r--r-- | ipc/glue/IPCStreamUtils.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/ipc/glue/IPCStreamUtils.h b/ipc/glue/IPCStreamUtils.h new file mode 100644 index 000000000..a20f8a651 --- /dev/null +++ b/ipc/glue/IPCStreamUtils.h @@ -0,0 +1,185 @@ +/* -*- 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 |