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 (45c0e8a9df93)

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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
/* -*- 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 _include_dom_media_ipc_RDDProcessHost_h_
#define _include_dom_media_ipc_RDDProcessHost_h_
#include "mozilla/ipc/GeckoChildProcessHost.h"

#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/TaskFactory.h"

namespace mozilla {
namespace ipc {
class SharedPreferenceSerializer;
}
}  // namespace mozilla
class nsITimer;

namespace mozilla {

class RDDChild;

// RDDProcessHost is the "parent process" container for a subprocess handle and
// IPC connection. It owns the parent process IPDL actor, which in this case,
// is a RDDChild.
//
// RDDProcessHosts are allocated and managed by RDDProcessManager. For all
// intents and purposes it is a singleton, though more than one may be allocated
// at a time due to its shutdown being asynchronous.
class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
  friend class RDDChild;

 public:
  class Listener {
   public:
    virtual void OnProcessLaunchComplete(RDDProcessHost* aHost) {}

    // The RDDProcessHost has unexpectedly shutdown or had its connection
    // severed. This is not called if an error occurs after calling
    // Shutdown().
    virtual void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) {}
  };

  explicit RDDProcessHost(Listener* listener);

  // Launch the subprocess asynchronously. On failure, false is returned.
  // Otherwise, true is returned, and the OnProcessLaunchComplete listener
  // callback will be invoked either when a connection has been established, or
  // if a connection could not be established due to an asynchronous error.
  //
  // @param aExtraOpts (StringVector)
  //        Extra options to pass to the subprocess.
  bool Launch(StringVector aExtraOpts);

  // If the process is being launched, block until it has launched and
  // connected. If a launch task is pending, it will fire immediately.
  //
  // Returns true if the process is successfully connected; false otherwise.
  bool WaitForLaunch();

  // Inform the process that it should clean up its resources and shut
  // down. This initiates an asynchronous shutdown sequence. After this
  // method returns, it is safe for the caller to forget its pointer to
  // the RDDProcessHost.
  //
  // After this returns, the attached Listener is no longer used.
  void Shutdown();

  // Return the actor for the top-level actor of the process. If the process
  // has not connected yet, this returns null.
  RDDChild* GetActor() const { return mRDDChild.get(); }

  // Return a unique id for this process, guaranteed not to be shared with any
  // past or future instance of RDDProcessHost.
  uint64_t GetProcessToken() const;

  bool IsConnected() const { return !!mRDDChild; }

  // Return the time stamp for when we tried to launch the RDD process.
  // This is currently used for Telemetry so that we can determine how
  // long RDD processes take to spin up. Note this doesn't denote a
  // successful launch, just when we attempted launch.
  TimeStamp GetLaunchTime() const { return mLaunchTime; }

  // Called on the IO thread.
  void OnChannelConnected(int32_t peer_pid) override;
  void OnChannelError() override;

  void SetListener(Listener* aListener);

  // Used for tests and diagnostics
  void KillProcess();

#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
  // To allow filling a MacSandboxInfo from the child
  // process without an instance of RDDProcessHost.
  // Only needed for late-start sandbox enabling.
  static bool StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);

  // Return the sandbox type to be used with this process type.
  static MacSandboxType GetMacSandboxType();
#endif

 private:
  ~RDDProcessHost();

  // Called on the main thread.
  void OnChannelConnectedTask();
  void OnChannelErrorTask();

  // Called on the main thread after a connection has been established.
  void InitAfterConnect(bool aSucceeded);

  // Called on the main thread when the mRDDChild actor is shutting down.
  void OnChannelClosed();

  // Kill the remote process, triggering IPC shutdown.
  void KillHard(const char* aReason);

  void DestroyProcess();

#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
  static bool sLaunchWithMacSandbox;

  // Sandbox the RDD process at launch for all instances
  bool IsMacSandboxLaunchEnabled() override { return sLaunchWithMacSandbox; }

  // Override so we can turn on RDD process-specific sandbox logging
  bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
#endif

  DISALLOW_COPY_AND_ASSIGN(RDDProcessHost);

  Listener* mListener;
  mozilla::ipc::TaskFactory<RDDProcessHost> mTaskFactory;

  enum class LaunchPhase { Unlaunched, Waiting, Complete };
  LaunchPhase mLaunchPhase;

  UniquePtr<RDDChild> mRDDChild;
  uint64_t mProcessToken;

  UniquePtr<ipc::SharedPreferenceSerializer> mPrefSerializer;

  bool mShutdownRequested;
  bool mChannelClosed;

  TimeStamp mLaunchTime;
};

}  // namespace mozilla

#endif  // _include_dom_media_ipc_RDDProcessHost_h_