DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (e5ef045527c6)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
/* -*- 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_IPCStreamSource_h
#define mozilla_ipc_IPCStreamSource_h

#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/dom/WorkerRef.h"

class nsIAsyncInputStream;

namespace mozilla {

namespace dom {
class ContentChild;
class ContentParent;
}  // namespace dom

namespace wr {
struct ByteBuffer;
}  // namespace wr

namespace ipc {

class PBackgroundChild;
class PBackgroundParent;
class PChildToParentStreamChild;
class PParentToChildStreamParent;

// The IPCStream IPC actor is designed to push an nsIInputStream from child to
// parent or parent to child incrementally.  This is mainly needed for streams
// such as nsPipe that may not yet have all their data available when the
// stream must be sent across an IPC boundary.  While many streams are handled
// by SerializeInputStream(), these streams cannot be serialized and must be
// sent using this actor.
//
// The IPCStream actor only support async, non-blocking streams because they
// must be read inline on the main thread and Worker threads.
//
// In general, the creation and handling of the IPCStream actor cannot be
// abstracted away behind SerializeInputStream() because the actor must be
// carefully managed.  Specifically:
//
//  1) The data flow must be explicitly initiated by calling
//     IPCStreamSource{Child,Parent}::Start() after the actor has been sent to
//     the other-side actor.
//  2) If the actor is never sent to the other-side, then this code must
//     call IPCStreamSource{Child,Parent}::StartDestroy() to avoid memory leaks.
//  3) The IPCStreamSource actor can only be used on threads that can be
//     guaranteed to stay alive as long as the actor is alive.  Right now
//     this limits IPCStream to the main thread and Worker threads.
//
// In general you should probably use the AutoIPCStreamSource RAII class
// defined in InputStreamUtils.h instead of using IPCStreamSource directly.
class IPCStreamSource {
 public:
  // Create a IPCStreamSource using a PContent IPC manager on the
  // main thread.  This can return nullptr if the provided stream is
  // blocking.
  static PChildToParentStreamChild* Create(nsIAsyncInputStream* aInputStream,
                                           dom::ContentChild* aManager);

  // Create a IPCStreamSource using a PBackground IPC manager on the
  // main thread or a Worker thread.  This can return nullptr if the provided
  // stream is blocking or if the Worker thread is already shutting down.
  static PChildToParentStreamChild* Create(nsIAsyncInputStream* aInputStream,
                                           PBackgroundChild* aManager);

  // Create a IPCStreamSource using a PContent IPC manager on the
  // main thread.  This can return nullptr if the provided stream is
  // blocking.
  static PParentToChildStreamParent* Create(nsIAsyncInputStream* aInputStream,
                                            dom::ContentParent* aManager);

  // Create a IPCStreamSource using a PBackground IPC manager on the
  // main thread or a Worker thread.  This can return nullptr if the provided
  // stream is blocking or if the Worker thread is already shutting down.
  static PParentToChildStreamParent* Create(nsIAsyncInputStream* aInputStream,
                                            PBackgroundParent* aManager);

  static IPCStreamSource* Cast(PChildToParentStreamChild* aActor);

  static IPCStreamSource* Cast(PParentToChildStreamParent* aActor);

  // Start reading data from the nsIAsyncInputStream used to create the actor.
  // This must be called after the actor is passed to the parent.  If you
  // use AutoIPCStream this is handled automatically.
  void Start();

  // Start cleaning up the actor.  This must be called if the actor is never
  // sent to the other side.  If you use AutoIPCStream this is handled
  // automatically.
  void StartDestroy();

 protected:
  IPCStreamSource(nsIAsyncInputStream* aInputStream);
  virtual ~IPCStreamSource();

  bool Initialize();

  void ActorDestroyed();

  void OnEnd(nsresult aRv);

  virtual void Close(nsresult aRv) = 0;

  virtual void SendData(const wr::ByteBuffer& aBuffer) = 0;

  void ActorConstructed();

 private:
  class Callback;

  void DoRead();

  void Wait();

  void OnStreamReady(Callback* aCallback);

  nsCOMPtr<nsIAsyncInputStream> mStream;
  RefPtr<Callback> mCallback;

  RefPtr<dom::StrongWorkerRef> mWorkerRef;

#ifdef DEBUG
 protected:
#endif

  enum { ePending, eActorConstructed, eClosed } mState;

 private:
  NS_DECL_OWNINGTHREAD
};

}  // namespace ipc
}  // namespace mozilla

#endif  // mozilla_ipc_IPCStreamSource_h