Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: services/shell/standalone/context.cc

Issue 2419723002: Move services/shell to services/service_manager (Closed)
Patch Set: rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 #include "services/shell/standalone/context.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_file_value_serializer.h"
17 #include "base/lazy_instance.h"
18 #include "base/location.h"
19 #include "base/macros.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/path_service.h"
22 #include "base/process/process_info.h"
23 #include "base/run_loop.h"
24 #include "base/single_thread_task_runner.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/threading/sequenced_worker_pool.h"
30 #include "base/threading/thread_task_runner_handle.h"
31 #include "base/trace_event/trace_event.h"
32 #include "build/build_config.h"
33 #include "components/tracing/common/tracing_switches.h"
34 #include "mojo/edk/embedder/embedder.h"
35 #include "mojo/public/cpp/bindings/strong_binding.h"
36 #include "services/catalog/catalog.h"
37 #include "services/catalog/store.h"
38 #include "services/shell/connect_params.h"
39 #include "services/shell/public/cpp/names.h"
40 #include "services/shell/runner/common/switches.h"
41 #include "services/shell/runner/host/in_process_native_runner.h"
42 #include "services/shell/runner/host/out_of_process_native_runner.h"
43 #include "services/shell/standalone/tracer.h"
44 #include "services/shell/switches.h"
45 #include "services/tracing/public/cpp/provider.h"
46 #include "services/tracing/public/cpp/switches.h"
47 #include "services/tracing/public/interfaces/tracing.mojom.h"
48
49 #if defined(OS_MACOSX)
50 #include "services/shell/runner/host/mach_broker.h"
51 #endif
52
53 namespace shell {
54 namespace {
55
56 base::FilePath::StringType GetPathFromCommandLineSwitch(
57 const base::StringPiece& value) {
58 #if defined(OS_POSIX)
59 return value.as_string();
60 #elif defined(OS_WIN)
61 return base::UTF8ToUTF16(value);
62 #endif // OS_POSIX
63 }
64
65 // Used to ensure we only init once.
66 class Setup {
67 public:
68 Setup() { mojo::edk::Init(); }
69
70 ~Setup() {}
71
72 private:
73 DISALLOW_COPY_AND_ASSIGN(Setup);
74 };
75
76 class TracingInterfaceProvider : public mojom::InterfaceProvider {
77 public:
78 explicit TracingInterfaceProvider(Tracer* tracer) : tracer_(tracer) {}
79 ~TracingInterfaceProvider() override {}
80
81 // mojom::InterfaceProvider:
82 void GetInterface(const std::string& interface_name,
83 mojo::ScopedMessagePipeHandle client_handle) override {
84 if (tracer_ && interface_name == tracing::mojom::Provider::Name_) {
85 tracer_->ConnectToProvider(
86 mojo::MakeRequest<tracing::mojom::Provider>(
87 std::move(client_handle)));
88 }
89 }
90
91 private:
92 Tracer* tracer_;
93
94 DISALLOW_COPY_AND_ASSIGN(TracingInterfaceProvider);
95 };
96
97 const size_t kMaxBlockingPoolThreads = 3;
98
99 std::unique_ptr<base::Thread> CreateIOThread(const char* name) {
100 std::unique_ptr<base::Thread> thread(new base::Thread(name));
101 base::Thread::Options options;
102 options.message_loop_type = base::MessageLoop::TYPE_IO;
103 thread->StartWithOptions(options);
104 return thread;
105 }
106
107 void OnInstanceQuit(const std::string& name, const Identity& identity) {
108 if (name == identity.name())
109 base::MessageLoop::current()->QuitWhenIdle();
110 }
111
112 } // namespace
113
114 Context::InitParams::InitParams() {}
115 Context::InitParams::~InitParams() {}
116
117 Context::Context()
118 : io_thread_(CreateIOThread("io_thread")),
119 main_entry_time_(base::Time::Now()) {}
120
121 Context::~Context() {
122 DCHECK(!base::MessageLoop::current());
123 blocking_pool_->Shutdown();
124 }
125
126 // static
127 void Context::EnsureEmbedderIsInitialized() {
128 static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
129 setup.Get();
130 }
131
132 void Context::Init(std::unique_ptr<InitParams> init_params) {
133 TRACE_EVENT0("mojo_shell", "Context::Init");
134 const base::CommandLine& command_line =
135 *base::CommandLine::ForCurrentProcess();
136
137 bool trace_startup = command_line.HasSwitch(::switches::kTraceStartup);
138 if (trace_startup) {
139 tracer_.Start(
140 command_line.GetSwitchValueASCII(::switches::kTraceStartup),
141 command_line.GetSwitchValueASCII(::switches::kTraceStartupDuration),
142 "mojo_runner.trace");
143 }
144
145 if (!init_params || init_params->init_edk)
146 EnsureEmbedderIsInitialized();
147
148 service_manager_runner_ = base::ThreadTaskRunnerHandle::Get();
149 blocking_pool_ =
150 new base::SequencedWorkerPool(kMaxBlockingPoolThreads, "blocking_pool",
151 base::TaskPriority::USER_VISIBLE);
152
153 init_edk_ = !init_params || init_params->init_edk;
154 if (init_edk_) {
155 mojo::edk::InitIPCSupport(this, io_thread_->task_runner().get());
156 #if defined(OS_MACOSX)
157 mojo::edk::SetMachPortProvider(MachBroker::GetInstance()->port_provider());
158 #endif
159 }
160
161 std::unique_ptr<NativeRunnerFactory> runner_factory;
162 if (command_line.HasSwitch(switches::kSingleProcess)) {
163 #if defined(COMPONENT_BUILD)
164 LOG(ERROR) << "Running Mojo in single process component build, which isn't "
165 << "supported because statics in apps interact. Use static build"
166 << " or don't pass --single-process.";
167 #endif
168 runner_factory.reset(
169 new InProcessNativeRunnerFactory(blocking_pool_.get()));
170 } else {
171 NativeRunnerDelegate* native_runner_delegate = init_params ?
172 init_params->native_runner_delegate : nullptr;
173 runner_factory.reset(new OutOfProcessNativeRunnerFactory(
174 blocking_pool_.get(), native_runner_delegate));
175 }
176 std::unique_ptr<catalog::Store> store;
177 if (init_params)
178 store = std::move(init_params->catalog_store);
179 catalog_.reset(
180 new catalog::Catalog(blocking_pool_.get(), std::move(store), nullptr));
181 service_manager_.reset(new ServiceManager(std::move(runner_factory),
182 catalog_->TakeService()));
183
184 if (command_line.HasSwitch(::switches::kServiceOverrides)) {
185 base::FilePath overrides_file(GetPathFromCommandLineSwitch(
186 command_line.GetSwitchValueASCII(::switches::kServiceOverrides)));
187 JSONFileValueDeserializer deserializer(overrides_file);
188 int error = 0;
189 std::string message;
190 std::unique_ptr<base::Value> contents =
191 deserializer.Deserialize(&error, &message);
192 if (!contents) {
193 LOG(ERROR) << "Failed to parse service overrides file: " << message;
194 } else {
195 std::unique_ptr<ServiceOverrides> service_overrides =
196 base::MakeUnique<ServiceOverrides>(std::move(contents));
197 for (const auto& iter : service_overrides->entries()) {
198 if (!iter.second.package_name.empty())
199 catalog_->OverridePackageName(iter.first, iter.second.package_name);
200 }
201 service_manager_->SetServiceOverrides(std::move(service_overrides));
202 }
203 }
204
205 mojom::InterfaceProviderPtr tracing_remote_interfaces;
206 mojom::InterfaceProviderPtr tracing_local_interfaces;
207 mojo::MakeStrongBinding(base::MakeUnique<TracingInterfaceProvider>(&tracer_),
208 mojo::GetProxy(&tracing_local_interfaces));
209
210 std::unique_ptr<ConnectParams> params(new ConnectParams);
211 params->set_source(CreateServiceManagerIdentity());
212 params->set_target(Identity("service:tracing", mojom::kRootUserID));
213 params->set_remote_interfaces(mojo::GetProxy(&tracing_remote_interfaces));
214 service_manager_->Connect(std::move(params));
215
216 if (command_line.HasSwitch(tracing::kTraceStartup)) {
217 tracing::mojom::CollectorPtr coordinator;
218 auto coordinator_request = GetProxy(&coordinator);
219 tracing_remote_interfaces->GetInterface(
220 tracing::mojom::Collector::Name_,
221 coordinator_request.PassMessagePipe());
222 tracer_.StartCollectingFromTracingService(std::move(coordinator));
223 }
224
225 // Record the shell startup metrics used for performance testing.
226 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
227 tracing::kEnableStatsCollectionBindings)) {
228 tracing::mojom::StartupPerformanceDataCollectorPtr collector;
229 tracing_remote_interfaces->GetInterface(
230 tracing::mojom::StartupPerformanceDataCollector::Name_,
231 mojo::GetProxy(&collector).PassMessagePipe());
232 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
233 // CurrentProcessInfo::CreationTime is only defined on some platforms.
234 const base::Time creation_time = base::CurrentProcessInfo::CreationTime();
235 collector->SetShellProcessCreationTime(creation_time.ToInternalValue());
236 #endif
237 collector->SetShellMainEntryPointTime(main_entry_time_.ToInternalValue());
238 }
239 }
240
241 void Context::Shutdown() {
242 // Actions triggered by Shell's destructor may require a current message loop,
243 // so we should destruct it explicitly now as ~Context() occurs post message
244 // loop shutdown.
245 service_manager_.reset();
246
247 DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), service_manager_runner_);
248
249 // If we didn't initialize the edk we should not shut it down.
250 if (!init_edk_)
251 return;
252
253 TRACE_EVENT0("mojo_shell", "Context::Shutdown");
254 // Post a task in case OnShutdownComplete is called synchronously.
255 base::ThreadTaskRunnerHandle::Get()->PostTask(
256 FROM_HERE, base::Bind(mojo::edk::ShutdownIPCSupport));
257 // We'll quit when we get OnShutdownComplete().
258 base::RunLoop().Run();
259 }
260
261 void Context::OnShutdownComplete() {
262 DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), service_manager_runner_);
263 base::MessageLoop::current()->QuitWhenIdle();
264 }
265
266 void Context::RunCommandLineApplication() {
267 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
268 base::CommandLine::StringVector args = command_line->GetArgs();
269 for (size_t i = 0; i < args.size(); ++i) {
270 #if defined(OS_WIN)
271 std::string possible_app = base::WideToUTF8(args[i]);
272 #else
273 std::string possible_app = args[i];
274 #endif
275 if (GetNameType(possible_app) == kNameType_Service) {
276 Run(possible_app);
277 break;
278 }
279 }
280 }
281
282 void Context::Run(const std::string& name) {
283 service_manager_->SetInstanceQuitCallback(base::Bind(&OnInstanceQuit, name));
284
285 mojom::InterfaceProviderPtr remote_interfaces;
286 mojom::InterfaceProviderPtr local_interfaces;
287
288 std::unique_ptr<ConnectParams> params(new ConnectParams);
289 params->set_source(CreateServiceManagerIdentity());
290 params->set_target(Identity(name, mojom::kRootUserID));
291 params->set_remote_interfaces(mojo::GetProxy(&remote_interfaces));
292 service_manager_->Connect(std::move(params));
293 }
294
295 } // namespace shell
OLDNEW
« no previous file with comments | « services/shell/standalone/context.h ('k') | services/shell/standalone/desktop/launcher_process.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698