зеркало из https://github.com/mozilla/gecko-dev.git
204 строки
6.6 KiB
C++
204 строки
6.6 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 "nsCOMPtr.h"
|
|
#include "nsIInputStream.h"
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
class nsIContentChild;
|
|
class nsIContentParent;
|
|
}
|
|
|
|
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 PChildToParentStream 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 PChildToParentStream 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 */
|
|
// }
|
|
//
|
|
// Note: This example is about child-to-parent inputStream, but AutoIPCStream
|
|
// works also parent-to-child.
|
|
//
|
|
// 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 PChildToParentStream 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 mDelayedStart;
|
|
|
|
bool
|
|
IsSet() const;
|
|
|
|
public:
|
|
// Implicitly create an OptionalIPCStream value. Either
|
|
// TakeValue() or TakeOptionalValue() can be used.
|
|
explicit AutoIPCStream(bool aDelayedStart = false);
|
|
|
|
// 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, bool aDelayedStart = false);
|
|
|
|
// Wrap an existing OptionalIPCStream. Either TakeValue()
|
|
// or TakeOptionalValue can be used.
|
|
explicit AutoIPCStream(OptionalIPCStream& aTarget,
|
|
bool aDelayedStart = false);
|
|
|
|
~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.
|
|
bool
|
|
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.
|
|
bool
|
|
Serialize(nsIInputStream* aStream, PBackgroundChild* aManager);
|
|
|
|
// Serialize the input stream.
|
|
MOZ_MUST_USE bool
|
|
Serialize(nsIInputStream* aStream, dom::nsIContentParent* aManager);
|
|
|
|
// Serialize the input stream.
|
|
MOZ_MUST_USE bool
|
|
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 other side.
|
|
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 other side.
|
|
OptionalIPCStream&
|
|
TakeOptionalValue();
|
|
|
|
private:
|
|
AutoIPCStream(const AutoIPCStream& aOther) = delete;
|
|
AutoIPCStream& operator=(const AutoIPCStream& aOther) = delete;
|
|
AutoIPCStream& operator=(const AutoIPCStream&& aOther) = delete;
|
|
};
|
|
|
|
template<>
|
|
struct IPDLParamTraits<nsIInputStream>
|
|
{
|
|
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
|
nsIInputStream* aParam);
|
|
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
|
IProtocol* aActor, RefPtr<nsIInputStream>* aResult);
|
|
};
|
|
|
|
} // namespace ipc
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla_ipc_IPCStreamUtils_h
|