1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CONTENT_PUBLIC_BROWSER_SERVICE_PROCESS_HOST_H_
6 #define CONTENT_PUBLIC_BROWSER_SERVICE_PROCESS_HOST_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/command_line.h"
14 #include "base/macros.h"
15 #include "base/observer_list.h"
16 #include "base/optional.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_piece.h"
19 #include "content/common/content_export.h"
20 #include "content/public/browser/sandbox_type.h"
21 #include "content/public/browser/service_process_info.h"
22 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
23 #include "mojo/public/cpp/bindings/pending_receiver.h"
24 #include "mojo/public/cpp/bindings/remote.h"
25 #include "mojo/public/cpp/system/message_pipe.h"
26 
27 namespace content {
28 
29 // ServiceProcessHost is used to launch new service processes given basic
30 // parameters like sandbox type, as well as a primordial Mojo interface to drive
31 // the service's behavior. See |Launch()| methods below for more details.
32 //
33 // Typical usage might look something like:
34 //
35 //   constexpr auto kFooServiceIdleTimeout = base::TimeDelta::FromSeconds(5);
36 //   auto foo_service = ServiceProcessHost::Launch<foo::mojom::FooService>(
37 //       ServiceProcessHost::Options()
38 //           .WithSandboxType(SandboxType::kUtility)
39 //           .WithDisplayName(IDS_FOO_SERVICE_DISPLAY_NAME)
40 //           .Pass());
41 //   foo_service.set_idle_handler(
42 //       kFooServiceIdleTimeout,
43 //       base::BindRepeating(
44 //           /* Something to reset |foo_service|,  killing the process. */));
45 //   foo_service->DoWork();
46 //
47 class CONTENT_EXPORT ServiceProcessHost {
48  public:
49   struct CONTENT_EXPORT Options {
50     Options();
51     ~Options();
52 
53     Options(Options&&);
54 
55     // Specifies the sandbox type with which to launch the service process.
56     // Defaults to a generic, restrictive utility process sandbox.
57     Options& WithSandboxType(SandboxType type);
58 
59     // Specifies the display name of the service process. This should generally
60     // be a human readable and meaningful application or service name and will
61     // appear in places like the system task viewer.
62     Options& WithDisplayName(const std::string& name);
63     Options& WithDisplayName(const base::string16& name);
64     Options& WithDisplayName(int resource_id);
65 
66     // Specifies additional flags to configure the launched process. See
67     // ChildProcessHost for flag definitions.
68     Options& WithChildFlags(int flags);
69 
70     // Specifies extra command line switches to append before launch.
71     Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
72 
73     // Passes the contents of this Options object to a newly returned Options
74     // value. This must be called when moving a built Options object into a call
75     // to |Launch()|.
76     Options Pass();
77 
78     SandboxType sandbox_type = SandboxType::kUtility;
79     base::string16 display_name;
80     base::Optional<int> child_flags;
81     std::vector<std::string> extra_switches;
82   };
83 
84   // An interface which can be implemented and registered/unregistered with
85   // |Add/RemoveObserver()| below to watch for all service process creation and
86   // and termination events globally. Methods are always called from the UI
87   // UI thread.
88   class CONTENT_EXPORT Observer : public base::CheckedObserver {
89    public:
~Observer()90     ~Observer() override {}
91 
OnServiceProcessLaunched(const ServiceProcessInfo & info)92     virtual void OnServiceProcessLaunched(const ServiceProcessInfo& info) {}
OnServiceProcessTerminatedNormally(const ServiceProcessInfo & info)93     virtual void OnServiceProcessTerminatedNormally(
94         const ServiceProcessInfo& info) {}
OnServiceProcessCrashed(const ServiceProcessInfo & info)95     virtual void OnServiceProcessCrashed(const ServiceProcessInfo& info) {}
96   };
97 
98   // Launches a new service process for asks it to bind the given interface
99   // receiver. |Interface| must be a service interface known to utility process
100   // code. See content/utility/services.cc and/or
101   // ContentUtilityClient::Run{Main,IO}ThreadService() methods.
102   //
103   // The launched process will (disregarding crashes) stay alive until either
104   // end of the |Interface| pipe is closed. Typically services are designed to
105   // never close their end of this pipe, and it's up to the browser to
106   // explicitly reset its corresponding Remote in order to induce service
107   // process termination.
108   //
109   // NOTE: The |Interface| type can be inferred from from the |receiver|
110   // argument's type.
111   //
112   // May be called from any thread.
113   template <typename Interface>
114   static void Launch(mojo::PendingReceiver<Interface> receiver,
115                      Options options = {}) {
116     Launch(mojo::GenericPendingReceiver(std::move(receiver)),
117            std::move(options));
118   }
119 
120   // Same as above but creates a new |Interface| pipe on the caller's behalf and
121   // returns its Remote endpoint.
122   //
123   // May be called from any thread.
124   template <typename Interface>
125   static mojo::Remote<Interface> Launch(Options options = {}) {
126     mojo::Remote<Interface> remote;
127     Launch(remote.BindNewPipeAndPassReceiver(), std::move(options));
128     return remote;
129   }
130 
131   // Yields information about currently active service processes. Must be called
132   // from the UI Thread only.
133   static std::vector<ServiceProcessInfo> GetRunningProcessInfo();
134 
135   // Registers a global observer of all service process lifetimes. Must be
136   // removed before destruction. Must be called from the UI thread only.
137   static void AddObserver(Observer* observer);
138 
139   // Removes a registered observer. This must be called some time before
140   // |*observer| is destroyed and must be called from the UI thread only.
141   static void RemoveObserver(Observer* observer);
142 
143  private:
144   // Launches a new service process and asks it to bind a receiver for the
145   // service interface endpoint carried by |receiver|, which should be connected
146   // to a Remote of the same interface type.
147   static void Launch(mojo::GenericPendingReceiver receiver, Options options);
148 };
149 
150 }  // namespace content
151 
152 #endif  // CONTENT_PUBLIC_BROWSER_SERVICE_PROCESS_HOST_H_
153